using System;
using System.Security.Cryptography;
using System.Text;
using BCrypt.Net;
using CncModels.Constants;
using CncModels.Dto.Login;
using CncService.Interface;
using CncService;
using CncRepository.Interface;
using System.Linq;

namespace CncService.Impl
{
    /// <summary>
    /// 登录认证实现
    /// </summary>
    public class AuthService : IAuthService
    {
        private readonly ISysConfigRepository _sysConfigRepository;
        private readonly string _jwtSecret;

        public AuthService(ISysConfigRepository sysConfigRepository, string jwtSecret)
        {
            _sysConfigRepository = sysConfigRepository ?? throw new ArgumentNullException(nameof(sysConfigRepository));
            _jwtSecret = jwtSecret ?? throw new ArgumentNullException(nameof(jwtSecret));
        }

        /// <inheritdoc/>
        public LoginResponse Login(LoginRequest request)
        {
            if (request == null) throw new BusinessException(ErrorCode.BadRequest, "请求参数错误");
            // 读取管理员用户名与哈希
            var userCfg = _sysConfigRepository.GetByKey("admin_username");
            var pwdCfg = _sysConfigRepository.GetByKey("admin_password_hash");

            var usernameStored = userCfg?.ConfigValue;
            var passwordHash = pwdCfg?.ConfigValue;

            if (string.IsNullOrWhiteSpace(usernameStored) || string.IsNullOrWhiteSpace(passwordHash))
            {
                throw new BusinessException(ErrorCode.BadRequest, "用户名或密码错误");
            }

            if (!string.Equals(request.Username, usernameStored, StringComparison.OrdinalIgnoreCase))
            {
                throw new BusinessException(ErrorCode.BadRequest, "用户名或密码错误");
            }

            // 验证密码
            if (!BCrypt.Net.BCrypt.Verify(request.Password ?? string.Empty, passwordHash))
            {
                throw new BusinessException(ErrorCode.BadRequest, "用户名或密码错误");
            }

            // 过期时间
            int expiresIn = (request.RememberMe ?? false) ? 24 * 3600 : 8 * 3600;

            // 生成简易 JWT
            var token = GenerateJwtToken(request.Username, expiresIn);

            return new LoginResponse
            {
                Token = token,
                ExpiresIn = expiresIn
            };
        }

        private string GenerateJwtToken(string username, int expiresInSeconds)
        {
            // Header
            const string headerJson = "{\"alg\":\"HS256\",\"typ\":\"JWT\"}";
            long exp = DateTimeOffset.UtcNow.ToUnixTimeSeconds() + expiresInSeconds;
            // Payload
            string payloadJson = $"{{\"sub\":\"admin\",\"name\":\"{Escape(username)}\",\"exp\":{exp}}}";

            string header = Base64UrlEncode(Encoding.UTF8.GetBytes(headerJson));
            string payload = Base64UrlEncode(Encoding.UTF8.GetBytes(payloadJson));
            string unsigned = header + "." + payload;

            // Signature
            using (var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(_jwtSecret)))
            {
                var sig = hmac.ComputeHash(Encoding.UTF8.GetBytes(unsigned));
                string signature = Base64UrlEncode(sig);
                return unsigned + "." + signature;
            }
        }

        private string Escape(string input)
        {
            if (string.IsNullOrEmpty(input)) return string.Empty;
            return input.Replace("\\", "\\\\").Replace("\"", "\\\"");
        }

        private string Base64UrlEncode(byte[] input)
        {
            var base64 = Convert.ToBase64String(input);
            return base64.Replace("+", "-").Replace("/", "_").TrimEnd('=');
        }
    }
}
