using Service.EmailParseServices;

namespace Service.EmailServices;

public interface IEmailHandleService
{
    Task<bool> HandleEmailAsync(
        string to,
        string from,
        string subject,
        DateTime date,
        string body
    );

    Task<bool> RefreshTransactionRecordsAsync(long emailMessageId);
}

public class EmailHandleService(
    IOptions<EmailSettings> emailSettings,
    ILogger<EmailHandleService> logger,
    IEmailMessageRepository emailRepo,
    ITransactionRecordRepository trxRepo,
    IEnumerable<IEmailParseServices> emailParsers,
    IMessageRecordService messageRecordService,
    ISmartHandleService smartHandleService
) : IEmailHandleService
{
    public async Task<bool> HandleEmailAsync(
        string to,
        string from,
        string subject,
        DateTime date,
        string body
    )
    {
        var filterForm = emailSettings.Value.FilterFromAddresses;
        if (filterForm.Length == 0)
        {
            logger.LogWarning("未配置邮件过滤条件，跳过账单处理");
            return false;
        }

        if (!filterForm.Any(f => from.Contains(f)))
        {
            logger.LogInformation("邮件不符合发件人过滤条件，跳过账单处理");
            return false;
        }

        var emailMessage = await SaveEmailAsync(to, from, subject, date, body);

        if (emailMessage == null)
        {
            throw new InvalidOperationException("邮件保存失败，无法继续处理");
        }

        var parsed = await ParseEmailBodyAsync(
            from,
            subject,
            string.IsNullOrEmpty(emailMessage.Body)
                ? emailMessage.HtmlBody
                : emailMessage.Body
            );
        if (parsed == null || parsed.Length == 0)
        {
            await messageRecordService.AddAsync(
                "邮件解析失败",
                $"来自 {from} 发送给 {to} 的邮件（主题：{subject}）未能成功解析内容，可能格式已变更或不受支持。"
            );
            logger.LogWarning("未能成功解析邮件内容，跳过账单处理");
            return true;
        }

        await messageRecordService.AddAsync(
            "邮件解析成功",
            $"来自 {from} 发送给 {to} 的邮件（主题：{subject}）已成功解析出 {parsed.Length} 条交易记录。"
        );
        logger.LogInformation("成功解析邮件，共 {Count} 条交易记录", parsed.Length);

        bool allSuccess = true;
        var records = new List<TransactionRecord>();
        foreach (var (card, reason, amount, balance, type, occurredAt) in parsed)
        {
            logger.LogInformation("处理交易记录: 卡号 {Card}, 交易原因 {Reason}, 金额 {Amount}, 余额 {Balance}, 类型 {Type}", card, reason, amount, balance, type);



            var record = await SaveTransactionRecordAsync(
                card,
                reason,
                amount,
                balance,
                type,
                occurredAt ?? date,
                emailMessage.Id,
                $"邮件 By {GetEmailByName(to)}"
            );

            if (record == null)
            {
                allSuccess = false;
                continue;
            }

            records.Add(record);
        }

        _ = await AnalyzeClassifyAsync(records.ToArray());

        return allSuccess;
    }

    public async Task<bool> RefreshTransactionRecordsAsync(long emailMessageId)
    {
        var emailMessage = await emailRepo.GetByIdAsync(emailMessageId);

        if (emailMessage == null)
        {
            logger.LogWarning("未找到指定ID的邮件记录，无法刷新交易记录，ID: {Id}", emailMessageId);
            return false;
        }

        var filterForm = emailSettings.Value.FilterFromAddresses;
        if (filterForm.Length == 0)
        {
            logger.LogWarning("未配置邮件过滤条件，跳过账单处理");
            return false;
        }

        if (!filterForm.Any(f => emailMessage.From.Contains(f)))
        {
            logger.LogInformation("邮件不符合发件人过滤条件，跳过账单处理");
            return true;
        }

        var parsed = await ParseEmailBodyAsync(
            emailMessage.From,
            emailMessage.Subject,
            string.IsNullOrEmpty(emailMessage.Body)
                ? emailMessage.HtmlBody
                : emailMessage.Body
            );
        if (parsed == null || parsed.Length == 0)
        {
            logger.LogWarning("未能成功解析邮件内容，跳过账单处理");
            return false;
        }

        logger.LogInformation("成功解析邮件，共 {Count} 条交易记录", parsed.Length);

        bool allSuccess = true;
        var records = new List<TransactionRecord>();
        foreach (var (card, reason, amount, balance, type, occurredAt) in parsed)
        {
            logger.LogInformation("刷新交易记录: 卡号 {Card}, 交易原因 {Reason}, 金额 {Amount}, 余额 {Balance}, 类型 {Type}", card, reason, amount, balance, type);

            var record = await SaveTransactionRecordAsync(
                card,
                reason,
                amount,
                balance,
                type,
                occurredAt ?? emailMessage.ReceivedDate,
                emailMessage.Id,
                $"邮件 By {GetEmailByName(emailMessage.To)}"
            );

            if (record == null)
            {
                allSuccess = false;
                continue;
            }

            records.Add(record);
        }

        _ = await AnalyzeClassifyAsync(records.ToArray());

        return allSuccess;
    }

    private string GetEmailByName(string to)
    {
        return emailSettings.Value.SmtpList.FirstOrDefault(s => s.Email == to)?.Name ?? to;
    }

    private async Task<EmailMessage?> SaveEmailAsync(
        string to,
        string from,
        string subject,
        DateTime date,
        string body
    )
    {
        var emailEntity = new EmailMessage
        {
            From = from,
            Subject = subject,
            ReceivedDate = date,
        };

        // 正则判断是否为HTML内容
        if (Regex.IsMatch(body, @"<[^>]+>"))
        {
            emailEntity.HtmlBody = body;
        }
        else
        {
            emailEntity.Body = body;
        }

        try
        {
            var emailMd5 = emailEntity.ComputeBodyHash();
            var existsEmail = await emailRepo.ExistsAsync(emailMd5);
            if (existsEmail != null)
            {
                logger.LogInformation("检测到重复邮件，跳过入库：{From} | {Subject} | {Date}", from, subject, date);
                return existsEmail;
            }

            emailEntity.Md5 = emailMd5;
            var toName = emailSettings.Value.SmtpList
                .FirstOrDefault(s => s.Email == to)?.Name ?? "";
            emailEntity.To = string.IsNullOrEmpty(toName) ? to : $"{toName} <{to}>";
            var ok = await emailRepo.AddAsync(emailEntity);
            if (ok)
            {
                logger.LogInformation("邮件已落库，ID: {Id}", emailEntity.Id);
                return emailEntity;
            }

            logger.LogError("邮件落库失败");
            return null;
        }
        catch (Exception ex)
        {
            // 原始邮件落库失败不阻塞交易记录，但记录告警
            logger.LogWarning(ex, "原始邮件落库失败");
            return null;
        }
    }

    private async Task<TransactionRecord?> SaveTransactionRecordAsync(
        string card,
        string reason,
        decimal amount,
        decimal balance,
        TransactionType type,
        DateTime occurredAt,
        long emailMessageId,
        string importFrom
    )
    {
        // 根据 emailMessageId 检查是否已存在记录：存在则更新，否则新增
        var existing = await trxRepo.ExistsByEmailMessageIdAsync(emailMessageId, occurredAt);

        if (existing != null)
        {
            existing.Card = card;
            existing.Reason = reason;
            existing.Amount = amount;
            existing.Balance = balance;
            existing.Type = type;
            existing.OccurredAt = occurredAt;

            var updated = await trxRepo.UpdateAsync(existing);
            if (updated)
            {
                logger.LogInformation("交易记录已更新，卡号 {Card}, 金额 {Amount}", card, amount);
            }
            else
            {
                logger.LogWarning("交易记录更新失败，卡号 {Card}, 金额 {Amount}", card, amount);
                return null;
            }

            return existing;
        }

        var trx = new TransactionRecord
        {
            Card = card,
            Reason = reason,
            Amount = amount,
            Balance = balance,
            Type = type,
            OccurredAt = occurredAt,
            EmailMessageId = emailMessageId,
            ImportFrom = importFrom
        };

        var inserted = await trxRepo.AddAsync(trx);
        if (inserted)
        {
            logger.LogInformation("交易记录已落库，卡号 {Card}, 金额 {Amount}", card, amount);
        }
        else
        {
            logger.LogWarning("交易记录落库失败，卡号 {Card}, 金额 {Amount}", card, amount);
            return null;
        }

        return trx;
    }

    private async Task<(string card, string reason, decimal amount, decimal balance, TransactionType type, DateTime? occurredAt)[]?> ParseEmailBodyAsync(string from, string subject, string body)
    {
        var service = emailParsers.FirstOrDefault(s => s.CanParse(from, subject, body));

        if (service == null)
        {
            logger.LogWarning("未找到合适的邮件解析服务，跳过解析");
            return null;
        }

        return await service.ParseAsync(body);
    }

    private async Task<TransactionRecord[]> AnalyzeClassifyAsync(TransactionRecord[] records)
    {
        var result = new List<TransactionRecord>();
        await smartHandleService.SmartClassifyAsync(records.Select(r => r.Id).ToArray(), chunk =>
       {
           // 处理分类结果
           var (type, data) = chunk;

           if (type != "data")
           {
               logger.LogWarning("未知的分类结果类型: {Type}, {Data}. 跳过分类", type, data);
               return;
           }

           try
           {
               var item = JsonSerializer.Deserialize<JsonObject>(data);

               var recordId = item?["id"]?.GetValue<long>();
               var classify = item?["Classify"]?.GetValue<string>();
               var recordType = item?["Type"]?.GetValue<int>();

               if (recordId == null || string.IsNullOrEmpty(classify) || recordType == null)
               {
                   logger.LogWarning("AI分类结果数据不完整，跳过分类: {Data}", data);
                   return;
               }

               if (recordType < (int)TransactionType.Expense || recordType > (int)TransactionType.None)
               {
                   logger.LogWarning("AI分类结果交易类型无效，跳过分类: {Data}", data);
                   return;
               }

               var record = records.FirstOrDefault(r => r.Id == recordId);
               if (record == null)
               {
                   logger.LogWarning("未找到对应的交易记录(AI返回内容有误)，跳过分类，ID: {Id}", recordId);
                   return;
               }

               record.Classify = classify;
               record.Type = (TransactionType)recordType;

               result.Add(record);
           }
           catch (Exception ex)
           {
               logger.LogWarning(ex, "解析AI分类结果失败，跳过分类: {Data}", data);
           }
       });

        return result.ToArray();
    }
}