@*
    EN: Receipt template management — create, edit, preview, switch, delete receipt templates.
    VI: Quản lý mẫu hoá đơn — tạo, sửa, xem trước, chuyển đổi, xoá mẫu hoá đơn in.
*@
@using System.Text.Json
@inject IJSRuntime JS
@inject ISnackbar Snackbar
@inject IDialogService DialogService

@* ═══ TEMPLATE LIST + EDITOR LAYOUT ═══ *@
<div style="display:flex;gap:24px;align-items:flex-start;">
    @* ─── LEFT: Template list ─── *@
    <div style="flex:1;min-width:0;">
        <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:16px;">
            <h3 style="font-size:16px;font-weight:700;margin:0;">Danh sách mẫu hoá đơn</h3>
            <button class="admin-btn-primary" @onclick="CreateNewTemplate" style="display:inline-flex;align-items:center;gap:8px;">
                <i data-lucide="plus" style="width:16px;height:16px;"></i>Tạo mới
            </button>
        </div>

        @if (_templates.Count == 0)
        {
            <div class="admin-panel">
                <div class="admin-panel__body" style="text-align:center;padding:40px;">
                    <div style="width:64px;height:64px;border-radius:20px;background:rgba(255,92,0,0.1);display:flex;align-items:center;justify-content:center;margin:0 auto 16px;">
                        <i data-lucide="receipt" style="width:28px;height:28px;color:var(--admin-orange-primary);"></i>
                    </div>
                    <p style="font-size:14px;color:var(--admin-text-tertiary);margin:0;">Chưa có mẫu hoá đơn nào.</p>
                </div>
            </div>
        }
        else
        {
            <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:16px;">
                @foreach (var tpl in _templates)
                {
                    var isSelected = _editingTemplate?.Id == tpl.Id;
                    var capturedTpl = tpl;
                    <div @onclick="@(() => SelectTemplate(capturedTpl))"
                         style="border-radius:12px;border:2px solid @(isSelected ? "var(--admin-orange-primary)" : "var(--admin-border-subtle)");background:var(--admin-bg-elevated);cursor:pointer;overflow:hidden;transition:border-color 0.2s;">
                        @* EN: Mini receipt preview thumbnail *@
                        @* VI: Hình thu nhỏ xem trước hoá đơn *@
                        <div style="padding:16px;background:var(--admin-bg-base);display:flex;justify-content:center;">
                            <div style="width:100px;background:#fff;border-radius:4px;padding:8px;transform:scale(0.85);">
                                <div style="text-align:center;font-size:6px;color:#333;font-weight:700;margin-bottom:4px;">
                                    @(string.IsNullOrWhiteSpace(capturedTpl.HeaderText) ? "TÊN CỬA HÀNG" : capturedTpl.HeaderText)
                                </div>
                                @if (capturedTpl.ShowItemList)
                                {
                                    <div style="border-top:1px dashed #ccc;margin:3px 0;"></div>
                                    <div style="font-size:5px;color:#666;">Sản phẩm x1 ... 50,000</div>
                                    <div style="font-size:5px;color:#666;">Sản phẩm x2 ... 30,000</div>
                                }
                                @if (capturedTpl.ShowTotal)
                                {
                                    <div style="border-top:1px dashed #ccc;margin:3px 0;"></div>
                                    <div style="font-size:6px;color:#333;font-weight:700;text-align:right;">TỔNG: 80,000đ</div>
                                }
                                @if (!string.IsNullOrWhiteSpace(capturedTpl.FooterText))
                                {
                                    <div style="text-align:center;font-size:5px;color:#999;margin-top:4px;">@capturedTpl.FooterText</div>
                                }
                            </div>
                        </div>
                        <div style="padding:12px 16px;display:flex;align-items:center;justify-content:space-between;">
                            <div>
                                <div style="font-size:13px;font-weight:600;">@capturedTpl.Name</div>
                                <div style="font-size:11px;color:var(--admin-text-tertiary);margin-top:2px;">@capturedTpl.PaperWidth &middot; @GetFontSizeLabel(capturedTpl.FontSize)</div>
                            </div>
                            @if (capturedTpl.IsDefault)
                            {
                                <span style="font-size:10px;font-weight:700;color:var(--admin-orange-primary);background:rgba(255,92,0,0.12);padding:3px 8px;border-radius:6px;">Mặc định</span>
                            }
                        </div>
                    </div>
                }
            </div>
        }
    </div>

    @* ─── RIGHT: Editor + Live Preview ─── *@
    @if (_editingTemplate != null)
    {
        <div style="width:720px;flex-shrink:0;position:sticky;top:24px;">
            <div class="admin-panel">
                <div class="admin-panel__header" style="display:flex;align-items:center;justify-content:space-between;">
                    <h3 class="admin-panel__title" style="display:flex;align-items:center;gap:8px;">
                        <i data-lucide="pencil" style="width:16px;height:16px;color:var(--admin-orange-primary);"></i>
                        Chỉnh sửa mẫu
                    </h3>
                    <button @onclick="@(() => _editingTemplate = null)" style="background:none;border:none;cursor:pointer;color:var(--admin-text-tertiary);padding:4px;">
                        <i data-lucide="x" style="width:18px;height:18px;"></i>
                    </button>
                </div>
                <div class="admin-panel__body" style="padding:0;">
                    <div style="display:flex;">
                        @* ─── Editor fields ─── *@
                        <div style="flex:1;padding:20px;border-right:1px solid var(--admin-border-subtle);max-height:600px;overflow-y:auto;">
                            @* EN: Template name *@
                            @* VI: Tên mẫu hoá đơn *@
                            <div style="margin-bottom:16px;">
                                <label style="font-size:12px;font-weight:600;display:block;margin-bottom:4px;">Tên mẫu</label>
                                <input type="text" @bind="_editingTemplate.Name" @bind:event="oninput"
                                       style="width:100%;padding:10px 14px;border-radius:8px;background:var(--admin-bg-elevated);border:1px solid var(--admin-border-subtle);font-size:14px;color:var(--admin-text-primary);" />
                            </div>

                            @* EN: Paper width + Font size *@
                            @* VI: Khổ giấy + Cỡ chữ *@
                            <div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:16px;">
                                <div>
                                    <label style="font-size:12px;font-weight:600;display:block;margin-bottom:4px;">Khổ giấy</label>
                                    <select @bind="_editingTemplate.PaperWidth"
                                            style="width:100%;padding:10px 14px;border-radius:8px;background:var(--admin-bg-elevated);border:1px solid var(--admin-border-subtle);color:var(--admin-text-primary);font-size:14px;">
                                        <option value="58mm">58mm</option>
                                        <option value="80mm">80mm</option>
                                    </select>
                                </div>
                                <div>
                                    <label style="font-size:12px;font-weight:600;display:block;margin-bottom:4px;">Cỡ chữ</label>
                                    <select @bind="_editingTemplate.FontSize"
                                            style="width:100%;padding:10px 14px;border-radius:8px;background:var(--admin-bg-elevated);border:1px solid var(--admin-border-subtle);color:var(--admin-text-primary);font-size:14px;">
                                        <option value="small">Nhỏ (11px)</option>
                                        <option value="medium">Trung bình (13px)</option>
                                        <option value="large">Lớn (15px)</option>
                                    </select>
                                </div>
                            </div>

                            @* EN: Header + Footer text *@
                            @* VI: Tiêu đề + Chân hoá đơn *@
                            <div style="margin-bottom:16px;">
                                <label style="font-size:12px;font-weight:600;display:block;margin-bottom:4px;">Tiêu đề hoá đơn</label>
                                <input type="text" @bind="_editingTemplate.HeaderText" @bind:event="oninput" placeholder="Tên cửa hàng / tiêu đề"
                                       style="width:100%;padding:10px 14px;border-radius:8px;background:var(--admin-bg-elevated);border:1px solid var(--admin-border-subtle);font-size:14px;color:var(--admin-text-primary);" />
                            </div>
                            <div style="margin-bottom:16px;">
                                <label style="font-size:12px;font-weight:600;display:block;margin-bottom:4px;">Chân hoá đơn</label>
                                <input type="text" @bind="_editingTemplate.FooterText" @bind:event="oninput" placeholder="Cảm ơn quý khách!"
                                       style="width:100%;padding:10px 14px;border-radius:8px;background:var(--admin-bg-elevated);border:1px solid var(--admin-border-subtle);font-size:14px;color:var(--admin-text-primary);" />
                            </div>

                            @* EN: Wifi password (conditional) *@
                            @* VI: Mật khẩu wifi (nếu bật) *@
                            @if (_editingTemplate.ShowWifiPassword)
                            {
                                <div style="margin-bottom:16px;">
                                    <label style="font-size:12px;font-weight:600;display:block;margin-bottom:4px;">Mật khẩu Wifi</label>
                                    <input type="text" @bind="_editingTemplate.WifiPassword" @bind:event="oninput" placeholder="wifi-password-123"
                                           style="width:100%;padding:10px 14px;border-radius:8px;background:var(--admin-bg-elevated);border:1px solid var(--admin-border-subtle);font-size:14px;color:var(--admin-text-primary);font-family:monospace;" />
                                </div>
                            }

                            @* EN: Field toggles *@
                            @* VI: Bật/tắt các trường hiển thị *@
                            <label style="font-size:12px;font-weight:600;display:block;margin-bottom:8px;">Hiển thị trường</label>
                            <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;">
                                @{
                                    void RenderToggle(string label, bool isOn, Action<bool> setter) {
                                        <div @onclick="@(() => { setter(!isOn); StateHasChanged(); })"
                                             style="display:flex;align-items:center;gap:8px;padding:8px 12px;border-radius:8px;border:1px solid var(--admin-border-subtle);cursor:pointer;transition:background 0.15s;">
                                            <div style="width:32px;height:18px;border-radius:9px;background:@(isOn ? "var(--admin-orange-primary)" : "var(--admin-border-subtle)");position:relative;transition:0.2s;flex-shrink:0;">
                                                <div style="width:14px;height:14px;border-radius:50%;background:white;position:absolute;top:2px;@(isOn ? "right:2px;" : "left:2px;");transition:0.2s;"></div>
                                            </div>
                                            <span style="font-size:12px;font-weight:500;white-space:nowrap;">@label</span>
                                        </div>;
                                    }
                                }
                                @{ RenderToggle("Logo", _editingTemplate.ShowLogo, v => _editingTemplate.ShowLogo = v); }
                                @{ RenderToggle("Địa chỉ", _editingTemplate.ShowAddress, v => _editingTemplate.ShowAddress = v); }
                                @{ RenderToggle("Số điện thoại", _editingTemplate.ShowPhone, v => _editingTemplate.ShowPhone = v); }
                                @{ RenderToggle("Mã số thuế", _editingTemplate.ShowTaxId, v => _editingTemplate.ShowTaxId = v); }
                                @{ RenderToggle("Mã đơn hàng", _editingTemplate.ShowOrderNumber, v => _editingTemplate.ShowOrderNumber = v); }
                                @{ RenderToggle("Ngày giờ", _editingTemplate.ShowDateTime, v => _editingTemplate.ShowDateTime = v); }
                                @{ RenderToggle("Tên nhân viên", _editingTemplate.ShowStaffName, v => _editingTemplate.ShowStaffName = v); }
                                @{ RenderToggle("Danh sách SP", _editingTemplate.ShowItemList, v => _editingTemplate.ShowItemList = v); }
                                @{ RenderToggle("Tạm tính", _editingTemplate.ShowSubtotal, v => _editingTemplate.ShowSubtotal = v); }
                                @{ RenderToggle("Phí dịch vụ", _editingTemplate.ShowServiceCharge, v => _editingTemplate.ShowServiceCharge = v); }
                                @{ RenderToggle("VAT %", _editingTemplate.ShowVat, v => _editingTemplate.ShowVat = v); }
                                @{ RenderToggle("Giảm giá", _editingTemplate.ShowDiscount, v => _editingTemplate.ShowDiscount = v); }
                                @{ RenderToggle("Tổng cộng", _editingTemplate.ShowTotal, v => _editingTemplate.ShowTotal = v); }
                                @{ RenderToggle("Phương thức TT", _editingTemplate.ShowPaymentMethod, v => _editingTemplate.ShowPaymentMethod = v); }
                                @{ RenderToggle("Tiền thừa", _editingTemplate.ShowChangeAmount, v => _editingTemplate.ShowChangeAmount = v); }
                                @{ RenderToggle("Mã giao dịch", _editingTemplate.ShowTransactionId, v => _editingTemplate.ShowTransactionId = v); }
                                @{ RenderToggle("Barcode/QR", _editingTemplate.ShowBarcode, v => _editingTemplate.ShowBarcode = v); }
                                @{ RenderToggle("Mật khẩu Wifi", _editingTemplate.ShowWifiPassword, v => _editingTemplate.ShowWifiPassword = v); }
                            </div>

                            @* EN: Action buttons *@
                            @* VI: Các nút hành động *@
                            <div style="margin-top:20px;display:flex;flex-wrap:wrap;gap:8px;">
                                <button class="admin-btn-primary" @onclick="SaveTemplate" style="display:inline-flex;align-items:center;gap:6px;">
                                    <i data-lucide="save" style="width:14px;height:14px;"></i>Lưu mẫu
                                </button>
                                @if (!_editingTemplate.IsDefault)
                                {
                                    <button @onclick="SetAsDefault"
                                            style="display:inline-flex;align-items:center;gap:6px;padding:8px 16px;border-radius:8px;border:1px solid var(--admin-orange-primary);background:transparent;color:var(--admin-orange-primary);cursor:pointer;font-size:13px;font-weight:600;">
                                        <i data-lucide="star" style="width:14px;height:14px;"></i>Đặt mặc định
                                    </button>
                                }
                                @if (_templates.Count > 1)
                                {
                                    <button @onclick="DeleteTemplate"
                                            style="display:inline-flex;align-items:center;gap:6px;padding:8px 16px;border-radius:8px;border:1px solid #EF4444;background:transparent;color:#EF4444;cursor:pointer;font-size:13px;font-weight:600;">
                                        <i data-lucide="trash-2" style="width:14px;height:14px;"></i>Xoá
                                    </button>
                                }
                            </div>
                        </div>

                        @* ─── Live Preview ─── *@
                        <div style="width:300px;padding:20px;display:flex;flex-direction:column;align-items:center;">
                            <label style="font-size:12px;font-weight:600;display:block;margin-bottom:12px;color:var(--admin-text-tertiary);text-transform:uppercase;letter-spacing:0.5px;">Xem trước</label>
                            @{
                                var t = _editingTemplate;
                                var paperW = t.PaperWidth == "58mm" ? "200px" : "260px";
                                var fontSize = GetFontSizePx(t.FontSize);
                            }
                            <div style="width:@paperW;background:#FFFFFF;border-radius:4px;padding:16px 12px;font-family:'Courier New',monospace;color:#1a1a1a;font-size:@fontSize;box-shadow:0 2px 12px rgba(0,0,0,0.15);position:relative;">
                                @* EN: Torn paper top edge *@
                                <div style="position:absolute;top:-6px;left:0;right:0;height:6px;background:repeating-linear-gradient(90deg,transparent,transparent 4px,#FFFFFF 4px,#FFFFFF 8px);"></div>

                                @* ── Header ── *@
                                @if (t.ShowLogo)
                                {
                                    <div style="text-align:center;margin-bottom:6px;">
                                        <div style="width:40px;height:40px;border-radius:8px;background:#f0f0f0;display:inline-flex;align-items:center;justify-content:center;">
                                            <span style="font-size:18px;color:#999;">&#9741;</span>
                                        </div>
                                    </div>
                                }
                                <div style="text-align:center;font-weight:700;font-size:calc(@fontSize + 2px);margin-bottom:2px;">
                                    @(string.IsNullOrWhiteSpace(t.HeaderText) ? "TÊN CỬA HÀNG" : t.HeaderText)
                                </div>
                                @if (t.ShowAddress)
                                {
                                    <div style="text-align:center;font-size:calc(@fontSize - 1px);color:#666;">123 Nguyễn Huệ, Q.1, TP.HCM</div>
                                }
                                @if (t.ShowPhone)
                                {
                                    <div style="text-align:center;font-size:calc(@fontSize - 1px);color:#666;">ĐT: 0909 123 456</div>
                                }
                                @if (t.ShowTaxId)
                                {
                                    <div style="text-align:center;font-size:calc(@fontSize - 1px);color:#666;">MST: 0123456789</div>
                                }

                                <div style="border-top:1px dashed #ccc;margin:8px 0;"></div>

                                @* ── Order info ── *@
                                @if (t.ShowOrderNumber)
                                {
                                    <div style="display:flex;justify-content:space-between;font-size:calc(@fontSize - 1px);">
                                        <span>Đơn #:</span><span style="font-weight:600;">HD-00042</span>
                                    </div>
                                }
                                @if (t.ShowDateTime)
                                {
                                    <div style="display:flex;justify-content:space-between;font-size:calc(@fontSize - 1px);">
                                        <span>Ngày:</span><span>29/03/2026 14:35</span>
                                    </div>
                                }
                                @if (t.ShowStaffName)
                                {
                                    <div style="display:flex;justify-content:space-between;font-size:calc(@fontSize - 1px);">
                                        <span>Thu ngân:</span><span>Nguyễn Văn A</span>
                                    </div>
                                }

                                @if (t.ShowOrderNumber || t.ShowDateTime || t.ShowStaffName)
                                {
                                    <div style="border-top:1px dashed #ccc;margin:8px 0;"></div>
                                }

                                @* ── Item list ── *@
                                @if (t.ShowItemList)
                                {
                                    <div style="font-size:calc(@fontSize - 1px);margin-bottom:2px;">
                                        <div style="display:flex;justify-content:space-between;font-weight:600;margin-bottom:4px;border-bottom:1px solid #eee;padding-bottom:4px;">
                                            <span>Sản phẩm</span><span>Tiền</span>
                                        </div>
                                        <div style="display:flex;justify-content:space-between;margin-bottom:2px;">
                                            <span>Cà phê sữa đá x2</span><span>58,000</span>
                                        </div>
                                        <div style="display:flex;justify-content:space-between;margin-bottom:2px;">
                                            <span>Trà đào cam sả x1</span><span>45,000</span>
                                        </div>
                                        <div style="display:flex;justify-content:space-between;margin-bottom:2px;">
                                            <span>Bánh mì bơ tỏi x1</span><span>25,000</span>
                                        </div>
                                    </div>
                                    <div style="border-top:1px dashed #ccc;margin:8px 0;"></div>
                                }

                                @* ── Totals ── *@
                                @if (t.ShowSubtotal)
                                {
                                    <div style="display:flex;justify-content:space-between;font-size:calc(@fontSize - 1px);">
                                        <span>Tạm tính:</span><span>128,000</span>
                                    </div>
                                }
                                @if (t.ShowServiceCharge)
                                {
                                    <div style="display:flex;justify-content:space-between;font-size:calc(@fontSize - 1px);">
                                        <span>Phí dịch vụ (5%):</span><span>6,400</span>
                                    </div>
                                }
                                @if (t.ShowVat)
                                {
                                    <div style="display:flex;justify-content:space-between;font-size:calc(@fontSize - 1px);">
                                        <span>VAT (10%):</span><span>12,800</span>
                                    </div>
                                }
                                @if (t.ShowDiscount)
                                {
                                    <div style="display:flex;justify-content:space-between;font-size:calc(@fontSize - 1px);color:#d32f2f;">
                                        <span>Giảm giá:</span><span>-10,000</span>
                                    </div>
                                }
                                @if (t.ShowTotal)
                                {
                                    <div style="border-top:1px dashed #ccc;margin:6px 0;"></div>
                                    <div style="display:flex;justify-content:space-between;font-weight:700;font-size:calc(@fontSize + 2px);">
                                        <span>TỔNG CỘNG:</span><span>@(ComputePreviewTotal())đ</span>
                                    </div>
                                }

                                @* ── Payment info ── *@
                                @if (t.ShowPaymentMethod)
                                {
                                    <div style="display:flex;justify-content:space-between;font-size:calc(@fontSize - 1px);margin-top:4px;">
                                        <span>Thanh toán:</span><span>Tiền mặt</span>
                                    </div>
                                }
                                @if (t.ShowChangeAmount)
                                {
                                    <div style="display:flex;justify-content:space-between;font-size:calc(@fontSize - 1px);">
                                        <span>Tiền khách đưa:</span><span>150,000</span>
                                    </div>
                                    <div style="display:flex;justify-content:space-between;font-size:calc(@fontSize - 1px);">
                                        <span>Tiền thừa:</span><span>@(ComputePreviewChange())</span>
                                    </div>
                                }
                                @if (t.ShowTransactionId)
                                {
                                    <div style="display:flex;justify-content:space-between;font-size:calc(@fontSize - 2px);color:#999;margin-top:4px;">
                                        <span>Mã GD:</span><span>TXN-20260329-0042</span>
                                    </div>
                                }

                                @* ── Barcode ── *@
                                @if (t.ShowBarcode)
                                {
                                    <div style="text-align:center;margin-top:8px;">
                                        <div style="display:inline-block;padding:8px;background:#f5f5f5;border-radius:4px;">
                                            <div style="width:80px;height:80px;display:grid;grid-template-columns:repeat(8,1fr);grid-template-rows:repeat(8,1fr);gap:1px;">
                                                @for (var i = 0; i < 64; i++)
                                                {
                                                    var fill = (i % 3 == 0 || i % 7 == 0) ? "#1a1a1a" : "#fff";
                                                    <div style="background:@fill;"></div>
                                                }
                                            </div>
                                        </div>
                                    </div>
                                }

                                @* ── Wifi ── *@
                                @if (t.ShowWifiPassword)
                                {
                                    <div style="text-align:center;margin-top:6px;font-size:calc(@fontSize - 1px);color:#666;">
                                        Wifi: <strong>@(t.WifiPassword ?? "goodgo-wifi")</strong>
                                    </div>
                                }

                                @* ── Footer ── *@
                                @if (!string.IsNullOrWhiteSpace(t.FooterText))
                                {
                                    <div style="border-top:1px dashed #ccc;margin:8px 0;"></div>
                                    <div style="text-align:center;font-size:calc(@fontSize - 1px);color:#666;font-style:italic;">@t.FooterText</div>
                                }

                                @* EN: Torn paper bottom edge *@
                                <div style="position:absolute;bottom:-6px;left:0;right:0;height:6px;background:repeating-linear-gradient(90deg,transparent,transparent 4px,#FFFFFF 4px,#FFFFFF 8px);"></div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    }
</div>

@code {
    [Parameter] public Guid ShopId { get; set; }

    private List<ReceiptTemplate> _templates = new();
    private ReceiptTemplate? _editingTemplate;

    private string StorageKey => $"aPOS_receipt_templates_{ShopId}";

    /// <summary>
    /// EN: Receipt template data model — stored in localStorage per shop.
    /// VI: Mô hình dữ liệu mẫu hoá đơn — lưu trong localStorage theo từng cửa hàng.
    /// </summary>
    private class ReceiptTemplate
    {
        public Guid Id { get; set; } = Guid.NewGuid();
        public string Name { get; set; } = "Mẫu mặc định";
        public bool IsDefault { get; set; }
        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; }
    }

    protected override async Task OnInitializedAsync()
    {
        await LoadTemplates();
    }

    /// <summary>
    /// EN: Load templates from localStorage, create default if none exist.
    /// VI: Tải mẫu từ localStorage, tạo mẫu mặc định nếu chưa có.
    /// </summary>
    private async Task LoadTemplates()
    {
        try
        {
            var json = await JS.InvokeAsync<string?>("localStorage.getItem", StorageKey);
            if (!string.IsNullOrWhiteSpace(json))
            {
                var loaded = JsonSerializer.Deserialize<List<ReceiptTemplate>>(json, _jsonOptions);
                if (loaded != null && loaded.Count > 0)
                {
                    _templates = loaded;
                    return;
                }
            }
        }
        catch { /* localStorage read error — use defaults */ }

        // EN: Create default template if none exist
        // VI: Tạo mẫu mặc định nếu chưa có
        _templates = new List<ReceiptTemplate>
        {
            new ReceiptTemplate
            {
                Id = Guid.NewGuid(),
                Name = "Mẫu mặc định",
                IsDefault = true,
                PaperWidth = "80mm",
                FontSize = "medium",
                HeaderText = "",
                FooterText = "Cảm ơn quý khách!",
                ShowLogo = true,
                ShowAddress = true,
                ShowPhone = true,
                ShowOrderNumber = true,
                ShowDateTime = true,
                ShowItemList = true,
                ShowSubtotal = true,
                ShowDiscount = true,
                ShowTotal = true,
                ShowPaymentMethod = true,
                ShowChangeAmount = true,
                ShowTransactionId = true
            }
        };
        await PersistTemplates();
    }

    /// <summary>
    /// EN: Persist templates to localStorage.
    /// VI: Lưu mẫu vào localStorage.
    /// </summary>
    private async Task PersistTemplates()
    {
        try
        {
            var json = JsonSerializer.Serialize(_templates, _jsonOptions);
            await JS.InvokeVoidAsync("localStorage.setItem", StorageKey, json);
        }
        catch (Exception ex)
        {
            Snackbar.Add($"Lỗi lưu mẫu: {ex.Message}", MudBlazor.Severity.Error);
        }
    }

    private static readonly JsonSerializerOptions _jsonOptions = new()
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        PropertyNameCaseInsensitive = true,
        WriteIndented = false
    };

    /// <summary>
    /// EN: Select a template for editing (deep clone to avoid live mutation until save).
    /// VI: Chọn mẫu để sửa (clone sâu để tránh thay đổi trực tiếp cho đến khi lưu).
    /// </summary>
    private void SelectTemplate(ReceiptTemplate tpl)
    {
        _editingTemplate = CloneTemplate(tpl);
    }

    /// <summary>
    /// EN: Create a new template with default values.
    /// VI: Tạo mẫu mới với giá trị mặc định.
    /// </summary>
    private void CreateNewTemplate()
    {
        _editingTemplate = new ReceiptTemplate
        {
            Id = Guid.NewGuid(),
            Name = $"Mẫu {_templates.Count + 1}",
            IsDefault = false,
            PaperWidth = "80mm",
            FontSize = "medium",
            FooterText = "Cảm ơn quý khách!"
        };
    }

    /// <summary>
    /// EN: Save editing template (insert or update).
    /// VI: Lưu mẫu đang sửa (thêm mới hoặc cập nhật).
    /// </summary>
    private async Task SaveTemplate()
    {
        if (_editingTemplate == null) return;

        var existing = _templates.FindIndex(t => t.Id == _editingTemplate.Id);
        if (existing >= 0)
        {
            _templates[existing] = CloneTemplate(_editingTemplate);
        }
        else
        {
            _templates.Add(CloneTemplate(_editingTemplate));
        }

        await PersistTemplates();
        Snackbar.Add("Đã lưu mẫu hoá đơn!", MudBlazor.Severity.Success);
        StateHasChanged();
    }

    /// <summary>
    /// EN: Set editing template as default.
    /// VI: Đặt mẫu đang sửa làm mặc định.
    /// </summary>
    private async Task SetAsDefault()
    {
        if (_editingTemplate == null) return;

        foreach (var tItem in _templates) tItem.IsDefault = false;
        var target = _templates.Find(tItem => tItem.Id == _editingTemplate.Id);
        if (target != null) target.IsDefault = true;
        _editingTemplate.IsDefault = true;

        await PersistTemplates();
        Snackbar.Add("Đã đặt mẫu mặc định!", MudBlazor.Severity.Success);
        StateHasChanged();
    }

    /// <summary>
    /// EN: Delete editing template (cannot delete last or default).
    /// VI: Xoá mẫu đang sửa (không được xoá mẫu cuối hoặc mặc định).
    /// </summary>
    private async Task DeleteTemplate()
    {
        if (_editingTemplate == null) return;

        if (_templates.Count <= 1)
        {
            Snackbar.Add("Không thể xoá mẫu duy nhất.", MudBlazor.Severity.Warning);
            return;
        }

        if (_editingTemplate.IsDefault)
        {
            Snackbar.Add("Không thể xoá mẫu mặc định. Hãy chuyển mặc định sang mẫu khác trước.", MudBlazor.Severity.Warning);
            return;
        }

        var confirmed = await DialogService.ShowMessageBox(
            "Xoá mẫu hoá đơn",
            $"Bạn có chắc muốn xoá mẫu \"{_editingTemplate.Name}\"?",
            yesText: "Xoá", cancelText: "Hủy");

        if (confirmed != true) return;

        _templates.RemoveAll(tItem => tItem.Id == _editingTemplate.Id);
        _editingTemplate = null;
        await PersistTemplates();
        Snackbar.Add("Đã xoá mẫu hoá đơn.", MudBlazor.Severity.Success);
        StateHasChanged();
    }

    /// <summary>
    /// EN: Get the name of the currently active (default) template.
    /// VI: Lấy tên mẫu đang kích hoạt (mặc định).
    /// </summary>
    public string GetActiveTemplateName()
    {
        return _templates.FirstOrDefault(tItem => tItem.IsDefault)?.Name ?? _templates.FirstOrDefault()?.Name ?? "—";
    }

    /// <summary>
    /// EN: Deep clone a template to avoid reference sharing.
    /// VI: Clone sâu mẫu hoá đơn để tránh chia sẻ tham chiếu.
    /// </summary>
    private static ReceiptTemplate CloneTemplate(ReceiptTemplate src) => new()
    {
        Id = src.Id,
        Name = src.Name,
        IsDefault = src.IsDefault,
        PaperWidth = src.PaperWidth,
        FontSize = src.FontSize,
        HeaderText = src.HeaderText,
        FooterText = src.FooterText,
        ShowLogo = src.ShowLogo,
        ShowAddress = src.ShowAddress,
        ShowPhone = src.ShowPhone,
        ShowTaxId = src.ShowTaxId,
        ShowOrderNumber = src.ShowOrderNumber,
        ShowDateTime = src.ShowDateTime,
        ShowStaffName = src.ShowStaffName,
        ShowItemList = src.ShowItemList,
        ShowSubtotal = src.ShowSubtotal,
        ShowServiceCharge = src.ShowServiceCharge,
        ShowVat = src.ShowVat,
        ShowDiscount = src.ShowDiscount,
        ShowTotal = src.ShowTotal,
        ShowPaymentMethod = src.ShowPaymentMethod,
        ShowChangeAmount = src.ShowChangeAmount,
        ShowTransactionId = src.ShowTransactionId,
        ShowBarcode = src.ShowBarcode,
        ShowWifiPassword = src.ShowWifiPassword,
        WifiPassword = src.WifiPassword
    };

    private static string GetFontSizeLabel(string size) => size switch
    {
        "small" => "Nhỏ",
        "large" => "Lớn",
        _ => "Trung bình"
    };

    private static string GetFontSizePx(string size) => size switch
    {
        "small" => "11px",
        "large" => "15px",
        _ => "13px"
    };

    /// <summary>
    /// EN: Compute preview total based on shown fields.
    /// VI: Tính tổng xem trước dựa trên các trường hiển thị.
    /// </summary>
    private string ComputePreviewTotal()
    {
        if (_editingTemplate == null) return "128,000";
        decimal total = 128000;
        if (_editingTemplate.ShowServiceCharge) total += 6400;
        if (_editingTemplate.ShowVat) total += 12800;
        if (_editingTemplate.ShowDiscount) total -= 10000;
        return total.ToString("N0");
    }

    private string ComputePreviewChange()
    {
        if (_editingTemplate == null) return "22,000";
        decimal total = 128000;
        if (_editingTemplate.ShowServiceCharge) total += 6400;
        if (_editingTemplate.ShowVat) total += 12800;
        if (_editingTemplate.ShowDiscount) total -= 10000;
        var change = 150000 - total;
        return change.ToString("N0");
    }
}
