using Microsoft.EntityFrameworkCore;
using bitforum.Constants;
using bitforum.Models.Account;

namespace bitforum.Repository
{
    public interface IEmailVerifyNumberRepository
    {
        /// <summary>
        /// 새 인증번호 생성 및 저장
        /// </summary>
        public Task<string> GenerateCodeAsync(string email, VerificationType type);

        /// <summary>
        /// 인증번호 검증 및 사용 처리
        /// </summary>
        public Task<bool> ValidateCodeAsync(string email, string code, VerificationType type);

        /// <summary>
        /// 만료된 인증번호 삭제
        /// </summary>
        public Task CleanupExpiredCodesAsync();
    }

    public class EmailVerifyNumberRepository : IEmailVerifyNumberRepository
    {
        private readonly DefaultDbContext _db;
        private readonly int _codeExpirationMinutes = 2;

        public EmailVerifyNumberRepository(DefaultDbContext db)
        {
            _db = db;
        }

        public async Task<string> GenerateCodeAsync(string email, VerificationType type)
        {
            _db.EmailVerifyNumber.RemoveRange(
                _db.EmailVerifyNumber.Where(x => x.Email == email && x.Type == type)
            );

            var code = Random.Shared.Next(100000, 999999).ToString(); // 6자리 숫자 인증번호 생성
            var expiration = DateTime.UtcNow.AddMinutes(_codeExpirationMinutes);

            _db.EmailVerifyNumber.Add(new EmailVerifyNumber
            {
                Type = type,
                Email = email,
                Code = code,
                Expiration = expiration
            });

            await _db.SaveChangesAsync();

            return code;
        }

        public async Task<bool> ValidateCodeAsync(string email, string code, VerificationType type)
        {
            var data = await _db.EmailVerifyNumber.FirstOrDefaultAsync(x => x.Email == email && x.Code == code && x.Type == type && !x.IsVerified && x.Expiration > DateTime.UtcNow);

            if (data == null)
            {
                return false;
            }

            data.IsVerified = true; // 사용 처리
            await _db.SaveChangesAsync();

            return true;
        }

        public async Task CleanupExpiredCodesAsync()
        {
            _db.EmailVerifyNumber.RemoveRange(
                _db.EmailVerifyNumber.Where(x => x.Expiration < DateTime.UtcNow)
            );

            await _db.SaveChangesAsync();
        }
    }
}
