using System.Security.Claims;
using HoneyBox.Core.Interfaces;
using HoneyBox.Model.Base;
using HoneyBox.Model.Models.Auth;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace HoneyBox.Api.Controllers;

/// <summary>
/// 认证控制器 - 处理用户登录、注册、Token刷新和手机号绑定
/// </summary>
/// <remarks>
/// 提供微信小程序登录、手机号验证码登录、Token刷新、手机号绑定等功能
/// </remarks>
[ApiController]
[Route("api")]
public class AuthController : ControllerBase
{
    private readonly IAuthService _authService;
    private readonly ILogger<AuthController> _logger;

    public AuthController(
        IAuthService authService,
        ILogger<AuthController> logger)
    {
        _authService = authService;
        _logger = logger;
    }

    /// <summary>
    /// 微信小程序登录
    /// </summary>
    /// <remarks>
    /// POST /api/login
    /// 
    /// 使用微信小程序授权code进行登录，返回双Token（Access Token + Refresh Token）
    /// Requirements: 1.1, 1.2, 6.1
    /// </remarks>
    /// <param name="request">微信登录请求参数，包含授权code</param>
    /// <returns>登录成功返回LoginResponse（包含accessToken、refreshToken、expiresIn），失败返回错误信息</returns>
    [HttpPost("login")]
    [ProducesResponseType(typeof(ApiResponse<LoginResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<LoginResponse>> WechatMiniProgramLogin([FromBody] WechatLoginRequest request)
    {
        if (request == null || string.IsNullOrWhiteSpace(request.Code))
        {
            return ApiResponse<LoginResponse>.Fail("授权code不能为空");
        }

        var result = await _authService.WechatMiniProgramLoginAsync(
            request.Code,
            request.Pid,
            request.ClickId);

        if (result.Success && result.LoginResponse != null)
        {
            _logger.LogInformation("WeChat login successful: UserId={UserId}", result.UserId);
            return ApiResponse<LoginResponse>.Success(result.LoginResponse, "登录成功");
        }

        _logger.LogWarning("WeChat login failed: {Error}", result.ErrorMessage);
        return ApiResponse<LoginResponse>.Fail(result.ErrorMessage ?? "登录失败");
    }

    /// <summary>
    /// 手机号验证码登录
    /// </summary>
    /// <remarks>
    /// POST /api/mobileLogin
    /// 
    /// 使用手机号和验证码进行登录，返回双Token（Access Token + Refresh Token）
    /// Requirements: 1.1, 1.2, 6.1
    /// </remarks>
    /// <param name="request">手机号登录请求参数，包含手机号和验证码</param>
    /// <returns>登录成功返回LoginResponse（包含accessToken、refreshToken、expiresIn），失败返回错误信息</returns>
    [HttpPost("mobileLogin")]
    [ProducesResponseType(typeof(ApiResponse<LoginResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<LoginResponse>> MobileLogin([FromBody] MobileLoginRequest request)
    {
        if (request == null)
        {
            return ApiResponse<LoginResponse>.Fail("请求参数不能为空");
        }

        if (string.IsNullOrWhiteSpace(request.Mobile))
        {
            return ApiResponse<LoginResponse>.Fail("手机号不能为空");
        }

        if (string.IsNullOrWhiteSpace(request.Code))
        {
            return ApiResponse<LoginResponse>.Fail("验证码不能为空");
        }

        var result = await _authService.MobileLoginAsync(
            request.Mobile,
            request.Code,
            request.Pid,
            request.ClickId);

        if (result.Success && result.LoginResponse != null)
        {
            _logger.LogInformation("Mobile login successful: UserId={UserId}", result.UserId);
            return ApiResponse<LoginResponse>.Success(result.LoginResponse, "登录成功");
        }

        _logger.LogWarning("Mobile login failed: {Error}", result.ErrorMessage);
        return ApiResponse<LoginResponse>.Fail(result.ErrorMessage ?? "登录失败");
    }

    /// <summary>
    /// 微信手机号快速验证登录
    /// </summary>
    /// <remarks>
    /// POST /api/wxPhoneLogin
    /// 
    /// 使用微信getPhoneNumber获取的code进行登录，同时使用uni.login的code获取openid用于微信支付
    /// 返回双Token（Access Token + Refresh Token）
    /// </remarks>
    /// <param name="request">微信手机号登录请求参数，包含手机号授权code和登录code</param>
    /// <returns>登录成功返回LoginResponse（包含accessToken、refreshToken、expiresIn），失败返回错误信息</returns>
    [HttpPost("wxPhoneLogin")]
    [ProducesResponseType(typeof(ApiResponse<LoginResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<LoginResponse>> WechatPhoneLogin([FromBody] WechatPhoneLoginRequest request)
    {
        if (request == null || string.IsNullOrWhiteSpace(request.PhoneCode))
        {
            return ApiResponse<LoginResponse>.Fail("手机号授权code不能为空");
        }

        var result = await _authService.WechatPhoneLoginAsync(request.PhoneCode, request.LoginCode, request.Pid);

        if (result.Success && result.LoginResponse != null)
        {
            _logger.LogInformation("WeChat phone login successful: UserId={UserId}", result.UserId);
            return ApiResponse<LoginResponse>.Success(result.LoginResponse, "登录成功");
        }

        _logger.LogWarning("WeChat phone login failed: {Error}", result.ErrorMessage);
        return ApiResponse<LoginResponse>.Fail(result.ErrorMessage ?? "登录失败");
    }

    /// <summary>
    /// 刷新 Token
    /// </summary>
    /// <remarks>
    /// POST /api/refresh
    /// 
    /// 使用 Refresh Token 获取新的 Access Token 和 Refresh Token
    /// Requirements: 2.1, 2.2, 2.3, 2.4
    /// </remarks>
    /// <param name="request">刷新请求，包含 Refresh Token</param>
    /// <returns>刷新成功返回新的 LoginResponse，失败返回错误信息</returns>
    [HttpPost("refresh")]
    [AllowAnonymous]
    [ProducesResponseType(typeof(ApiResponse<LoginResponse>), StatusCodes.Status200OK)]
    public async Task<ApiResponse<LoginResponse>> RefreshToken([FromBody] RefreshTokenRequest request)
    {
        if (request == null || string.IsNullOrWhiteSpace(request.RefreshToken))
        {
            return ApiResponse<LoginResponse>.Fail("刷新令牌不能为空");
        }

        var clientIp = GetClientIp();
        var result = await _authService.RefreshTokenAsync(request.RefreshToken, clientIp);

        if (result.Success && result.LoginResponse != null)
        {
            _logger.LogInformation("Token refresh successful: UserId={UserId}", result.LoginResponse.UserId);
            return ApiResponse<LoginResponse>.Success(result.LoginResponse, "刷新成功");
        }

        _logger.LogWarning("Token refresh failed: {Error}", result.ErrorMessage);
        
        // 根据错误类型返回不同的状态码
        // -1 表示未登录/Token无效，前端需要跳转登录页
        return ApiResponse<LoginResponse>.Fail(result.ErrorMessage ?? "刷新失败", -1);
    }

    /// <summary>
    /// 退出登录（撤销 Token）
    /// </summary>
    /// <remarks>
    /// POST /api/logout
    /// 
    /// 撤销用户的 Refresh Token，使其失效
    /// Requirements: 4.4
    /// </remarks>
    /// <param name="request">退出请求，包含要撤销的 Refresh Token（可选，不传则撤销当前用户所有Token）</param>
    /// <returns>退出成功返回成功消息</returns>
    [HttpPost("logout")]
    [Authorize]
    [ProducesResponseType(typeof(ApiResponse), StatusCodes.Status200OK)]
    public async Task<ApiResponse> Logout([FromBody] RefreshTokenRequest? request)
    {
        var userId = GetCurrentUserId();
        var clientIp = GetClientIp();

        try
        {
            if (request != null && !string.IsNullOrWhiteSpace(request.RefreshToken))
            {
                // 撤销指定的 Refresh Token
                await _authService.RevokeTokenAsync(request.RefreshToken, clientIp);
                _logger.LogInformation("Token revoked: UserId={UserId}", userId);
            }
            else if (userId.HasValue)
            {
                // 撤销用户的所有 Refresh Token
                await _authService.RevokeAllUserTokensAsync(userId.Value, clientIp);
                _logger.LogInformation("All tokens revoked: UserId={UserId}", userId);
            }

            return ApiResponse.Success("退出成功");
        }
        catch (Exception ex)
        {
            _logger.LogWarning("Logout failed: UserId={UserId}, Error={Error}", userId, ex.Message);
            return ApiResponse.Fail("退出失败");
        }
    }


    /// <summary>
    /// 微信授权绑定手机号
    /// </summary>
    /// <remarks>
    /// POST /api/login_bind_mobile
    /// 
    /// 使用微信授权code获取手机号并绑定到当前用户
    /// Requirements: 5.1-5.5
    /// </remarks>
    /// <param name="request">绑定手机号请求参数，包含微信授权code</param>
    /// <returns>绑定成功返回手机号信息，失败返回错误信息</returns>
    [HttpPost("login_bind_mobile")]
    [Authorize]
    [ProducesResponseType(typeof(ApiResponse<BindMobileResponse>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<BindMobileResponse>), StatusCodes.Status401Unauthorized)]
    public async Task<ApiResponse<BindMobileResponse>> LoginBindMobile([FromBody] BindMobileRequest request)
    {
        var userId = GetCurrentUserId();
        if (userId == null)
        {
            return ApiResponse<BindMobileResponse>.Unauthorized();
        }

        if (request == null || string.IsNullOrWhiteSpace(request.Code))
        {
            return ApiResponse<BindMobileResponse>.Fail("微信授权code不能为空");
        }

        try
        {
            var result = await _authService.WechatBindMobileAsync(userId.Value, request.Code);
            _logger.LogInformation("WeChat bind mobile successful: UserId={UserId}", userId);
            return ApiResponse<BindMobileResponse>.Success(result, "绑定成功");
        }
        catch (InvalidOperationException ex)
        {
            _logger.LogWarning("WeChat bind mobile failed: UserId={UserId}, Error={Error}", userId, ex.Message);
            return ApiResponse<BindMobileResponse>.Fail(ex.Message);
        }
    }

    /// <summary>
    /// 验证码绑定手机号
    /// </summary>
    /// <remarks>
    /// POST /api/bindMobile
    /// 
    /// 使用手机号和验证码绑定手机号到当前用户
    /// Requirements: 5.1-5.5
    /// </remarks>
    /// <param name="request">绑定手机号请求参数，包含手机号和验证码</param>
    /// <returns>绑定成功返回手机号信息，失败返回错误信息</returns>
    [HttpPost("bindMobile")]
    [Authorize]
    [ProducesResponseType(typeof(ApiResponse<BindMobileResponse>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<BindMobileResponse>), StatusCodes.Status401Unauthorized)]
    public async Task<ApiResponse<BindMobileResponse>> BindMobile([FromBody] BindMobileWithCodeRequest request)
    {
        var userId = GetCurrentUserId();
        if (userId == null)
        {
            return ApiResponse<BindMobileResponse>.Unauthorized();
        }

        if (request == null)
        {
            return ApiResponse<BindMobileResponse>.Fail("请求参数不能为空");
        }

        if (string.IsNullOrWhiteSpace(request.Mobile))
        {
            return ApiResponse<BindMobileResponse>.Fail("手机号不能为空");
        }

        if (string.IsNullOrWhiteSpace(request.Code))
        {
            return ApiResponse<BindMobileResponse>.Fail("验证码不能为空");
        }

        try
        {
            var result = await _authService.BindMobileAsync(userId.Value, request.Mobile, request.Code);
            _logger.LogInformation("Bind mobile successful: UserId={UserId}", userId);
            return ApiResponse<BindMobileResponse>.Success(result, "绑定成功");
        }
        catch (InvalidOperationException ex)
        {
            _logger.LogWarning("Bind mobile failed: UserId={UserId}, Error={Error}", userId, ex.Message);
            return ApiResponse<BindMobileResponse>.Fail(ex.Message);
        }
    }

    /// <summary>
    /// H5绑定手机号（无需验证码）
    /// </summary>
    /// <remarks>
    /// POST /api/login_bind_mobile_h5
    /// 
    /// H5端直接绑定手机号到当前用户，无需短信验证码
    /// Requirements: 13.1
    /// </remarks>
    /// <param name="request">绑定手机号请求参数，包含手机号</param>
    /// <returns>绑定成功返回结果，失败返回错误信息</returns>
    [HttpPost("login_bind_mobile_h5")]
    [Authorize]
    [ProducesResponseType(typeof(ApiResponse<BindMobileResponse>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<BindMobileResponse>), StatusCodes.Status401Unauthorized)]
    public async Task<ApiResponse<BindMobileResponse>> LoginBindMobileH5([FromBody] BindMobileH5Request request)
    {
        var userId = GetCurrentUserId();
        if (userId == null)
        {
            return ApiResponse<BindMobileResponse>.Unauthorized();
        }

        if (request == null)
        {
            return ApiResponse<BindMobileResponse>.Fail("请求参数不能为空");
        }

        if (string.IsNullOrWhiteSpace(request.Mobile))
        {
            return ApiResponse<BindMobileResponse>.Fail("手机号不能为空");
        }

        try
        {
            var result = await _authService.BindMobileH5Async(userId.Value, request.Mobile);
            _logger.LogInformation("H5 Bind mobile successful: UserId={UserId}", userId);
            return ApiResponse<BindMobileResponse>.Success(result, "绑定成功");
        }
        catch (InvalidOperationException ex)
        {
            _logger.LogWarning("H5 Bind mobile failed: UserId={UserId}, Error={Error}", userId, ex.Message);
            return ApiResponse<BindMobileResponse>.Fail(ex.Message);
        }
    }

    /// <summary>
    /// 记录用户登录
    /// </summary>
    /// <remarks>
    /// GET|POST /api/login_record
    /// 
    /// 记录用户登录信息，包括设备信息和IP地址
    /// Requirements: 6.1-6.4
    /// </remarks>
    /// <param name="request">登录记录请求参数，包含设备信息（可选）</param>
    /// <returns>登录记录结果</returns>
    [HttpPost("login_record")]
    [HttpGet("login_record")]
    [Authorize]
    [ProducesResponseType(typeof(ApiResponse<RecordLoginResponse>), StatusCodes.Status200OK)]
    [ProducesResponseType(typeof(ApiResponse<RecordLoginResponse>), StatusCodes.Status401Unauthorized)]
    public async Task<ApiResponse<RecordLoginResponse>> RecordLogin([FromBody] RecordLoginRequest? request)
    {
        var userId = GetCurrentUserId();
        if (userId == null)
        {
            return ApiResponse<RecordLoginResponse>.Unauthorized();
        }

        try
        {
            // 获取客户端IP
            var clientIp = GetClientIp();
            
            var result = await _authService.RecordLoginAsync(
                userId.Value,
                request?.Device,
                clientIp);

            return ApiResponse<RecordLoginResponse>.Success(result);
        }
        catch (InvalidOperationException ex)
        {
            _logger.LogWarning("Record login failed: UserId={UserId}, Error={Error}", userId, ex.Message);
            return ApiResponse<RecordLoginResponse>.Fail(ex.Message);
        }
    }

    #region Private Helper Methods

    /// <summary>
    /// 获取当前登录用户ID
    /// </summary>
    private int? GetCurrentUserId()
    {
        var userIdClaim = User.FindFirst(ClaimTypes.NameIdentifier);
        if (userIdClaim == null || !int.TryParse(userIdClaim.Value, out var userId))
        {
            return null;
        }
        return userId;
    }

    /// <summary>
    /// 获取客户端IP地址
    /// </summary>
    private string GetClientIp()
    {
        // 优先从X-Forwarded-For头获取（经过代理的情况）
        var forwardedFor = HttpContext.Request.Headers["X-Forwarded-For"].FirstOrDefault();
        if (!string.IsNullOrWhiteSpace(forwardedFor))
        {
            // X-Forwarded-For可能包含多个IP，取第一个
            var ip = forwardedFor.Split(',').FirstOrDefault()?.Trim();
            if (!string.IsNullOrWhiteSpace(ip))
            {
                return ip;
            }
        }

        // 从X-Real-IP头获取
        var realIp = HttpContext.Request.Headers["X-Real-IP"].FirstOrDefault();
        if (!string.IsNullOrWhiteSpace(realIp))
        {
            return realIp;
        }

        // 从连接获取
        var remoteIp = HttpContext.Connection.RemoteIpAddress;
        if (remoteIp != null)
        {
            // 如果是IPv6的本地回环地址，转换为IPv4
            if (remoteIp.IsIPv4MappedToIPv6)
            {
                return remoteIp.MapToIPv4().ToString();
            }
            return remoteIp.ToString();
        }

        return string.Empty;
    }

    #endregion
}
