// EN: Service to generate receipt HTML from saved templates and print via browser popup.
// VI: Service tạo HTML hoá đơn từ mẫu đã lưu và in qua popup trình duyệt.

using System.Text;
using System.Text.Json;
using Microsoft.JSInterop;

namespace WebClientTpos.Client.Services;

/// <summary>
/// EN: Receipt data passed from POS page to the print service.
/// VI: Dữ liệu hoá đơn truyền từ POS page đến service in.
/// </summary>
public record ReceiptData
{
    public string ShopName { get; init; } = "Cửa hàng";
    public string? ShopAddress { get; init; }
    public string? ShopPhone { get; init; }
    public string? TaxId { get; init; }
    public string OrderNumber { get; init; } = "";
    public DateTime OrderDate { get; init; } = DateTime.Now;
    public string? StaffName { get; init; }
    public List<ReceiptItem> Items { get; init; } = new();
    public decimal Subtotal { get; init; }
    public decimal DiscountAmount { get; init; }
    public decimal ServiceCharge { get; init; }
    public decimal VatAmount { get; init; }
    public decimal Total { get; init; }
    public string PaymentMethod { get; init; } = "Tiền mặt";
    public decimal? AmountTendered { get; init; }
    public decimal? ChangeAmount { get; init; }
    public string? TransactionId { get; init; }
}

public record ReceiptItem(string Name, int Qty, decimal Price);

/// <summary>
/// EN: Generates receipt HTML using saved templates from localStorage.
/// VI: Tạo HTML hoá đơn sử dụng mẫu đã lưu từ localStorage.
/// </summary>
public class ReceiptPrintService
{
    private readonly IJSRuntime _js;
    private static readonly JsonSerializerOptions _jsonOptions = new()
    {
        PropertyNameCaseInsensitive = true,
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase
    };

    public ReceiptPrintService(IJSRuntime js) => _js = js;

    /// <summary>
    /// EN: Print receipt using default template for the given shop.
    /// VI: In hoá đơn sử dụng mẫu mặc định của cửa hàng.
    /// </summary>
    public async Task PrintAsync(Guid shopId, ReceiptData data)
    {
        var template = await LoadDefaultTemplateAsync(shopId);
        var html = BuildReceiptHtml(template, data);
        await _js.InvokeVoidAsync("printPosReceipt", html);
    }

    /// <summary>
    /// EN: Load default receipt template from localStorage for a shop.
    /// VI: Tải mẫu hoá đơn mặc định từ localStorage cho cửa hàng.
    /// </summary>
    private async Task<ReceiptTemplateSettings> LoadDefaultTemplateAsync(Guid shopId)
    {
        try
        {
            var key = $"aPOS_receipt_templates_{shopId}";
            var json = await _js.InvokeAsync<string?>("localStorage.getItem", key);
            if (!string.IsNullOrWhiteSpace(json))
            {
                var templates = JsonSerializer.Deserialize<List<ReceiptTemplateSettings>>(json, _jsonOptions);
                var def = templates?.FirstOrDefault(t => t.IsDefault) ?? templates?.FirstOrDefault();
                if (def != null) return def;
            }
        }
        catch { /* fallback to default */ }

        return new ReceiptTemplateSettings();
    }

    /// <summary>
    /// EN: Build complete receipt HTML from template settings and order data.
    /// VI: Tạo HTML hoá đơn hoàn chỉnh từ cài đặt mẫu và dữ liệu đơn hàng.
    /// </summary>
    private static string BuildReceiptHtml(ReceiptTemplateSettings t, ReceiptData d)
    {
        var paperMm = t.PaperWidth == "58mm" ? 58 : 80;
        var contentW = paperMm - 8; // 4mm margin each side
        var fontSize = t.FontSize switch { "small" => "11px", "large" => "15px", _ => "13px" };
        var titleSize = t.FontSize switch { "small" => "14px", "large" => "18px", _ => "16px" };

        var sb = new StringBuilder();
        sb.Append("<!DOCTYPE html><html><head><meta charset='utf-8'>");
        sb.Append($"<title>Hóa đơn - {Enc(d.OrderNumber)}</title>");
        sb.Append("<style>");
        sb.Append($"@page {{ margin: 4mm; size: {paperMm}mm auto; }}");
        sb.Append($"body {{ font-family: 'Courier New', monospace; font-size: {fontSize}; width: {contentW}mm; margin: 0 auto; color: #000; }}");
        sb.Append(".c { text-align: center; } .b { font-weight: bold; }");
        sb.Append(".d { border-top: 1px dashed #000; margin: 6px 0; }");
        sb.Append(".r { display: flex; justify-content: space-between; padding: 2px 0; }");
        sb.Append(".f { text-align: center; margin-top: 8px; color: #555; }");
        sb.Append("</style></head><body>");

        // ── HEADER ──
        if (t.ShowLogo)
        {
            sb.Append($"<div class='c b' style='font-size:{titleSize};'>");
            sb.Append(Enc(string.IsNullOrWhiteSpace(t.HeaderText) ? d.ShopName : t.HeaderText));
            sb.Append("</div>");
        }
        if (t.ShowAddress && !string.IsNullOrEmpty(d.ShopAddress))
            sb.Append($"<div class='c' style='font-size:10px;'>{Enc(d.ShopAddress)}</div>");
        if (t.ShowPhone && !string.IsNullOrEmpty(d.ShopPhone))
            sb.Append($"<div class='c' style='font-size:10px;'>ĐT: {Enc(d.ShopPhone)}</div>");
        if (t.ShowTaxId && !string.IsNullOrEmpty(d.TaxId))
            sb.Append($"<div class='c' style='font-size:10px;'>MST: {Enc(d.TaxId)}</div>");

        sb.Append("<div class='d'></div>");

        // ── ORDER INFO ──
        if (t.ShowOrderNumber)
            sb.Append($"<div class='r'><span>Đơn #:</span><b>{Enc(d.OrderNumber)}</b></div>");
        if (t.ShowDateTime)
            sb.Append($"<div class='r'><span>Ngày:</span><span>{d.OrderDate:dd/MM/yyyy HH:mm}</span></div>");
        if (t.ShowStaffName && !string.IsNullOrEmpty(d.StaffName))
            sb.Append($"<div class='r'><span>NV:</span><span>{Enc(d.StaffName)}</span></div>");

        sb.Append("<div class='d'></div>");

        // ── ITEMS ──
        if (t.ShowItemList && d.Items.Count > 0)
        {
            sb.Append("<div style='border-bottom:1px solid #000;padding:2px 0;display:flex;justify-content:space-between;font-weight:bold;'>");
            sb.Append("<span>Sản phẩm</span><span>Tiền</span></div>");
            foreach (var item in d.Items)
            {
                sb.Append($"<div style='display:flex;justify-content:space-between;padding:2px 0;'>");
                sb.Append($"<span>{Enc(item.Name)} x{item.Qty}</span>");
                sb.Append($"<span>{item.Qty * item.Price:N0}</span></div>");
            }
            sb.Append("<div class='d'></div>");
        }

        // ── TOTALS ──
        if (t.ShowSubtotal)
            sb.Append($"<div class='r'><span>Tạm tính:</span><span>{d.Subtotal:N0}</span></div>");
        if (t.ShowDiscount && d.DiscountAmount > 0)
            sb.Append($"<div class='r' style='color:#c00;'><span>Giảm giá:</span><span>-{d.DiscountAmount:N0}</span></div>");
        if (t.ShowServiceCharge && d.ServiceCharge > 0)
            sb.Append($"<div class='r'><span>Phí dịch vụ:</span><span>{d.ServiceCharge:N0}</span></div>");
        if (t.ShowVat && d.VatAmount > 0)
            sb.Append($"<div class='r'><span>VAT:</span><span>{d.VatAmount:N0}</span></div>");
        if (t.ShowTotal)
            sb.Append($"<div class='r b' style='font-size:{titleSize};padding:4px 0;'><span>TỔNG CỘNG:</span><span>{d.Total:N0}₫</span></div>");

        sb.Append("<div class='d'></div>");

        // ── PAYMENT ──
        if (t.ShowPaymentMethod)
            sb.Append($"<div class='r'><span>Thanh toán:</span><span>{Enc(d.PaymentMethod)}</span></div>");
        if (t.ShowChangeAmount && d.AmountTendered.HasValue)
        {
            sb.Append($"<div class='r'><span>Tiền khách đưa:</span><span>{d.AmountTendered.Value:N0}</span></div>");
            if (d.ChangeAmount.HasValue)
                sb.Append($"<div class='r'><span>Tiền thừa:</span><span>{d.ChangeAmount.Value:N0}</span></div>");
        }
        if (t.ShowTransactionId && !string.IsNullOrEmpty(d.TransactionId))
            sb.Append($"<div class='r' style='font-size:10px;'><span>Mã GD:</span><span>{Enc(d.TransactionId)}</span></div>");

        // ── FOOTER ──
        if (t.ShowBarcode && !string.IsNullOrEmpty(d.OrderNumber))
            sb.Append($"<div class='c' style='margin-top:8px;font-family:monospace;letter-spacing:4px;'>|||{Enc(d.OrderNumber)}|||</div>");
        if (t.ShowWifiPassword && !string.IsNullOrEmpty(t.WifiPassword))
            sb.Append($"<div class='c' style='margin-top:6px;font-size:10px;'>WiFi: {Enc(t.WifiPassword)}</div>");
        if (!string.IsNullOrEmpty(t.FooterText))
            sb.Append($"<div class='f'>{Enc(t.FooterText)}</div>");
        sb.Append("<div class='f' style='font-size:9px;'>Powered by aPOS</div>");

        sb.Append("<script>window.onload=function(){window.print();window.onafterprint=function(){window.close();}}</script>");
        sb.Append("</body></html>");

        return sb.ToString();
    }

    private static string Enc(string? s) => System.Net.WebUtility.HtmlEncode(s ?? "");

    /// <summary>
    /// EN: Template settings model — matches ReceiptTemplates.razor localStorage structure.
    /// VI: Mô hình cài đặt mẫu — khớp cấu trúc localStorage của ReceiptTemplates.razor.
    /// </summary>
    private class ReceiptTemplateSettings
    {
        public bool IsDefault { get; set; } = true;
        public string PaperWidth { get; set; } = "80mm";
        public string FontSize { get; set; } = "medium";
        public string HeaderText { get; set; } = "";
        public string FooterText { get; set; } = "Cảm ơn quý khách!";
        public bool ShowLogo { get; set; } = true;
        public bool ShowAddress { get; set; } = true;
        public bool ShowPhone { get; set; } = true;
        public bool ShowTaxId { get; set; }
        public bool ShowOrderNumber { get; set; } = true;
        public bool ShowDateTime { get; set; } = true;
        public bool ShowStaffName { get; set; }
        public bool ShowItemList { get; set; } = true;
        public bool ShowSubtotal { get; set; } = true;
        public bool ShowServiceCharge { get; set; }
        public bool ShowVat { get; set; }
        public bool ShowDiscount { get; set; } = true;
        public bool ShowTotal { get; set; } = true;
        public bool ShowPaymentMethod { get; set; } = true;
        public bool ShowChangeAmount { get; set; } = true;
        public bool ShowTransactionId { get; set; } = true;
        public bool ShowBarcode { get; set; }
        public bool ShowWifiPassword { get; set; }
        public string? WifiPassword { get; set; }
    }
}
