using System.Text.Json;
using System.Web;
using BimAI.Domain.Entities;
using BimAI.Infrastructure.Data;
using Microsoft.Extensions.Configuration;

namespace BimAI.Infrastructure.Sync;

public class InvoiceSyncService(HttpClient httpClient, BimAIDbContext db, IConfiguration configuration)
{
    private string DecodeHtmlEntities(string text)
    {
        if (string.IsNullOrEmpty(text))
            return text;

        return HttpUtility.HtmlDecode(text);
    }

    public async Task RunAsync()
    {
        var apiKey = configuration["TWINPOL_CRM:ApiKey"];
        var syncState = db.SyncStates.FirstOrDefault(x => x.Entity == "Invoice") ?? new SyncState { Entity = "Invoice", LastSynced = 0 };

        var url = $"https://crm.twinpol.com/REST/index.php?key={apiKey}&action=bimai.export.ecommerce&since=0";
        var response = await httpClient.GetStringAsync(url);

        var jsonDoc = JsonSerializer.Deserialize<JsonElement>(response);
        if (!jsonDoc.TryGetProperty("data", out var dataElement))
        {
            Console.WriteLine("[SYNC] No 'data' property in response");
            return;
        }

        var invoices = dataElement.EnumerateArray();
        var now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();

        foreach (var invoiceJson in invoices)
        {
            try
            {
                var e5Id = invoiceJson.GetProperty("e5Id").GetString() ?? "";
                var documentNo = DecodeHtmlEntities(invoiceJson.GetProperty("documentNo").GetString() ?? "");
                var type = DecodeHtmlEntities(invoiceJson.GetProperty("type").GetString() ?? "");
                var registerDateStr = invoiceJson.GetProperty("registerDate").GetString() ?? "";
                var sellDateStr = invoiceJson.GetProperty("sellDate").GetString() ?? "";
                var clientName = DecodeHtmlEntities(invoiceJson.GetProperty("clientName").GetString() ?? "");
                var clientId = DecodeHtmlEntities(invoiceJson.GetProperty("clientId").GetString() ?? "");
                var clientNip = DecodeHtmlEntities(invoiceJson.GetProperty("clientNip").GetString() ?? "");
                var clientAddress = DecodeHtmlEntities(invoiceJson.GetProperty("clientAddress").GetString() ?? "");
                var currency = invoiceJson.GetProperty("currency").GetString() ?? "PLN";
                var totalNettoStr = invoiceJson.GetProperty("totalNetto").GetString() ?? "0";
                var totalBruttoStr = invoiceJson.GetProperty("totalBrutto").GetString() ?? "0";
                var totalVatStr = invoiceJson.GetProperty("totalVat").GetString() ?? "0";
                var source = invoiceJson.GetProperty("source").GetString() ?? "";

                if (!DateTime.TryParse(registerDateStr, out var registerDate))
                {
                    Console.WriteLine($"[SYNC] Invalid registerDate for invoice {documentNo}: {registerDateStr}");
                    continue;
                }

                if (!DateTime.TryParse(sellDateStr, out var sellDate))
                {
                    Console.WriteLine($"[SYNC] Invalid sellDate for invoice {documentNo}: {sellDateStr}");
                    continue;
                }

                if (!decimal.TryParse(totalNettoStr, out var totalNetto))
                    totalNetto = 0;

                if (!decimal.TryParse(totalBruttoStr, out var totalBrutto))
                    totalBrutto = 0;

                if (!decimal.TryParse(totalVatStr, out var totalVat))
                    totalVat = 0;

                var existing = db.Invoices.FirstOrDefault(x => x.DocumentNo == documentNo && x.Source == source);

                if (existing == null)
                {
                    var invoice = new Invoice
                    {
                        DocumentNo = documentNo,
                        Type = type,
                        RegisterDate = registerDate,
                        SellDate = sellDate,
                        ClientName = clientName,
                        ClientId = string.IsNullOrWhiteSpace(clientId) ? null : clientId,
                        ClientNip = string.IsNullOrWhiteSpace(clientNip) ? null : clientNip,
                        ClientAddress = string.IsNullOrWhiteSpace(clientAddress) ? null : clientAddress,
                        Currency = currency,
                        TotalNetto = totalNetto,
                        TotalBrutto = totalBrutto,
                        TotalVat = totalVat,
                        Source = source,
                        CreatedAt = DateTime.UtcNow,
                        UpdatedAt = DateTime.UtcNow
                    };
                    db.Invoices.Add(invoice);
                    Console.WriteLine($"[SYNC] Added invoice: {documentNo} from {source}");
                }
                else
                {
                    existing.Type = type;
                    existing.RegisterDate = registerDate;
                    existing.SellDate = sellDate;
                    existing.ClientName = clientName;
                    existing.ClientId = string.IsNullOrWhiteSpace(clientId) ? null : clientId;
                    existing.ClientNip = string.IsNullOrWhiteSpace(clientNip) ? null : clientNip;
                    existing.ClientAddress = string.IsNullOrWhiteSpace(clientAddress) ? null : clientAddress;
                    existing.Currency = currency;
                    existing.TotalNetto = totalNetto;
                    existing.TotalBrutto = totalBrutto;
                    existing.TotalVat = totalVat;
                    existing.UpdatedAt = DateTime.UtcNow;
                    Console.WriteLine($"[SYNC] Updated invoice: {documentNo} from {source}");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[SYNC] Error processing invoice: {ex.Message}");
            }
        }

        syncState.LastSynced = now;
        if (db.SyncStates.FirstOrDefault(x => x.Entity == "Invoice") == null)
        {
            db.SyncStates.Add(syncState);
        }
        else
        {
            db.SyncStates.Update(syncState);
        }
        await db.SaveChangesAsync();
        Console.WriteLine("[SYNC] Invoice sync completed");
    }
}
