using HtmlAgilityPack;

namespace Service.EmailServices.EmailParse;

public class EmailParseFormCcsvc(
    ILogger<EmailParseFormCcsvc> logger,
    IOpenAiService openAiService
) : EmailParseServicesBase(logger, openAiService)
{
    public override bool CanParse(string from, string subject, string body)
    {
        if (!from.Contains("ccsvc@message.cmbchina.com"))
        {
            return false;
        }

        if (!subject.Contains("每日信用管家"))
        {
            return false;
        }

        // 必须包含HTML标签
        if (!Regex.IsMatch(body, "<.*?>"))
        {
            return false;
        }

        return true;
    }

    public override async Task<(
        string card,
        string reason,
        decimal amount,
        decimal balance,
        TransactionType type,
        DateTime? occurredAt
    )[]> ParseEmailContentAsync(string emailContent)
    {
        var doc = new HtmlDocument();
        doc.LoadHtml(emailContent);

        var result = new List<(string, string, decimal, decimal, TransactionType, DateTime?)>();

        // 1. Get Date
        var dateNode = doc.DocumentNode.SelectSingleNode("//font[contains(text(), '您的消费明细如下')]");

        var dateText = dateNode.InnerText.Trim();
        // "2025/12/21&nbsp;您的消费明细如下："
        var dateMatch = Regex.Match(dateText, @"\d{4}/\d{1,2}/\d{1,2}");
        if (!dateMatch.Success || !DateTime.TryParse(dateMatch.Value, out var date))
        {
            logger.LogWarning("Failed to parse date from: {DateText}", dateText);
            return [];
        }

        // 2. Get Balance (Available Limit)
        decimal balance = 0;
        // Find "可用额度" label
        var limitLabelNode = doc.DocumentNode.SelectSingleNode("//font[contains(text(), '可用额度')]");
        {
            // Go up to TR
            var tr = limitLabelNode.Ancestors("tr").FirstOrDefault();
            if (tr != null)
            {
                var prevTr = tr.PreviousSibling;
                while (prevTr.Name != "tr") prevTr = prevTr.PreviousSibling;

                var balanceNode = prevTr.SelectSingleNode(".//font[contains(text(), '￥')]");
                var balanceStr = balanceNode.InnerText.Replace("￥", "").Replace(",", "").Trim();
                decimal.TryParse(balanceStr, out balance);
            }
        }

        // 3. Get Transactions
        var transactionNodes = doc.DocumentNode.SelectNodes("//span[@id='fixBand4']");
        foreach (var node in transactionNodes)
        {
            try
            {
                // Time
                var timeNode = node.SelectSingleNode(".//span[@id='fixBand5']//font");
                var timeText = timeNode.InnerText.Trim(); // "10:13:43"

                DateTime? occurredAt = date;
                if (!string.IsNullOrEmpty(timeText) && DateTime.TryParse($"{date:yyyy-MM-dd} {timeText}", out var dt))
                {
                    occurredAt = dt;
                }

                // Info Block
                var infoNode = node.SelectSingleNode(".//span[@id='fixBand12']");

                // Amount
                var amountNode = infoNode.SelectSingleNode(".//font[contains(text(), 'CNY')]");
                var amountText = amountNode.InnerText.Replace("CNY", "").Replace("&nbsp;", "").Trim();
                if (!decimal.TryParse(amountText, out var amount))
                {
                    continue;
                }

                // Description
                var descNode = infoNode.SelectSingleNode(".//tr[2]//font");
                var descText = descNode.InnerText;
                // Replace &nbsp; and non-breaking space (\u00A0) with normal space
                descText = descText.Replace("&nbsp;", " ");
                descText = HtmlEntity.DeEntitize(descText).Replace((char)160, ' ').Trim();

                // Parse Description: "尾号4390 消费 财付通-luckincoffee瑞幸咖啡"
                var parts = descText.Split([' '], StringSplitOptions.RemoveEmptyEntries);

                string card = "";
                string reason = descText;
                TransactionType type;

                if (parts.Length > 0 && parts[0].StartsWith("尾号"))
                {
                    card = parts[0].Replace("尾号", "");
                }

                if (parts.Length > 2)
                {
                    reason = string.Join(" ", parts.Skip(2));
                }

                // 招商信用卡特殊，消费金额为正数，退款为负数
                if(amount > 0)
                {
                    type = TransactionType.Expense;
                }
                else
                {
                    type = TransactionType.Income;
                    amount = Math.Abs(amount);
                }

                result.Add((card, reason, amount, balance, type, occurredAt));
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "Error parsing transaction node");
            }
        }

        return await Task.FromResult(result.ToArray());
    }
}