using Microsoft.AspNetCore.Mvc;
using bitforum.DTOs.Request;
using bitforum.DTOs.Response;
using bitforum.Helpers;
using bitforum.Services;
using bitforum.Constants;
using bitforum.Repository;
using bitforum.Models.Account;

namespace bitforum.Controllers.API.Auth
{
    [ApiController]
    [Route("api/auth")]
    public class RegisterController : ControllerBase
    {
        private readonly ILogger<RegisterController> _logger;
        private readonly DefaultDbContext _db;
        private readonly IConfigService _configService;
        private readonly IMailService _mailService;
        private readonly IMemberRepository _memberRepository;
        private ResultDto _result = new ResultDto();

        public RegisterController(ILogger<RegisterController> logger, DefaultDbContext db, IConfigService configService, IMailService mailService, IMemberRepository memberRepository)
        {
            _logger = logger;
            _db = db;
            _configService = configService;
            _mailService = mailService;
            _memberRepository = memberRepository;
        }

        // 회원가입 요청
        [HttpPost("register")]
        public async Task<ActionResult<ResultDto>> Register([FromBody] RegisterDto request)
        {
            try
            {
                // 회원 가입 차단
                if (_configService.IsRegisterBlock())
                {
                    throw new Exception("현재 회원가입이 일시 중단되었습니다.");
                }

                // 유효성 검사
                if (!ModelState.IsValid)
                {
                    _result.Errors = ModelState.GetErrors();
                    throw new Exception("유효성 검사에 실패하였습니다.");
                }

                // 이메일 거부 목록 확인
                if (_configService.IsDeniedEmail(request.Email))
                {
                    throw new Exception($"`{request.Email}`은 사용할 수 없는 이메일입니다.");
                }

                // 이메일 중복 확인
                if (await _memberRepository.IsExistEmail(request.Email))
                {
                    throw new Exception("이미 가입된 이메일입니다.");
                }

                // 비밀번호 정책 확인
                if (!_configService.IsPasswordPolicyValid(request.Password))
                {
                    throw new Exception("비밀번호 구성이 적절하지 않습니다.");
                }

                bool isNew = false;
                var member = await _memberRepository.FindNonMemberByEmail(request.Email);
                if (member == null)
                {
                    member = new Models.Account.Member
                    {
                        Email = request.Email,
                        CreatedAt = DateTime.UtcNow
                    };

                    isNew = true;
                }

                member.Password = BCrypt.Net.BCrypt.HashPassword(request.Password);
                member.SignupIP = HttpContext.GetClientIP();
                member.PasswordUpdatedAt = DateTime.UtcNow;

                if (isNew)
                {
                    await _db.Member.AddAsync(member);
                }

                await _db.SaveChangesAsync();

                if (member.ID > 0)
                {
                    await _db.MemberApprove.AddAsync(new MemberApprove
                    {
                        MemberID = member.ID
                    });
                }

                bool isRegisterEmailAuth = _configService.IsRegisterEmailAuth();
                if (isRegisterEmailAuth)
                {
                    // 회원가입 이메일 인증 메일 발송
                    await _mailService.SendRegisterEmailAsync(member);
                    _result.Message = "이메일 인증 후 회원가입이 완료됩니다.";
                } 
                else
                {
                    // 회원가입 완료 메일 발송
                    await _mailService.SendRegistrationEmailAsync(member);
                    _result.Message = "회원가입을 환영합니다.";
                }

                _result.Data = new { isRegisterEmailAuth };
        
            }
            catch (Exception e)
            {
                _logger.LogError(e, e.Message);
                _result.Ok = false;
                _result.Status = StatusCodes.Status400BadRequest;
                _result.Message = e.Message;
            }

            return _result;
        }

        // 회원가입 수락
        [HttpGet("registration/{email}")]
        public async Task<ActionResult<ResultDto>> Registration([FromRoute] string email)
        {
            try
            {
                var cookieName = $"isVerified-{VerificationType.Registration}";
                if (!Request.Cookies.ContainsKey(cookieName) || Request.Cookies[cookieName] != "true")
                {
                    throw new Exception("사전 인증을 먼저 수행하세요.");
                }

                if (string.IsNullOrEmpty(email))
                {
                    throw new Exception("이메일을 입력해주세요.");
                }

                // 회원 확인
                var member = await _memberRepository.FindNonMemberByEmail(email);
                if (member is null)
                {
                    throw new Exception("회원 정보를 찾을 수 없습니다.");
                }

                member.IsEmailVerified = true;
                member.EmailVerifiedAt = DateTime.UtcNow;

                await _db.SaveChangesAsync();
                await _mailService.SendRegistrationEmailAsync(member);

                _result.Message = "회원가입을 환영합니다."; 

                // 쿠키 삭제
                Response.Cookies.Delete(cookieName);
            }
            catch (Exception e)
            {
                _logger.LogError(e, e.Message);
                _result.Ok = false;
                _result.Status = StatusCodes.Status400BadRequest;
                _result.Message = e.Message;
            }

            return _result;
        }
    }
}
