package de.assecutor.votianlt.pages.view;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.GridVariant;
import com.vaadin.flow.component.grid.ColumnTextAlign;
import com.vaadin.flow.component.html.*;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.select.Select;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.renderer.ComponentRenderer;
import com.vaadin.flow.data.value.ValueChangeMode;
import com.vaadin.flow.router.HasDynamicTitle;
import com.vaadin.flow.router.Route;
import de.assecutor.votianlt.pages.base.ui.component.ViewToolbar;
import de.assecutor.votianlt.pages.base.ui.view.MainLayout;
import jakarta.annotation.security.RolesAllowed;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.server.StreamResource;
import com.vaadin.flow.server.StreamRegistration;
import de.assecutor.votianlt.service.SystemCompanyProfileService;
import de.assecutor.votianlt.service.SystemInvoiceService;
import de.assecutor.votianlt.util.DateTimeFormatUtil;
import de.assecutor.votianlt.model.invoices.SystemInvoiceData;
import de.assecutor.votianlt.model.invoices.SystemInvoiceItem;
import java.io.ByteArrayInputStream;

import java.text.NumberFormat;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
 * Meine Rechnungen – nutzerzentrierte Übersicht.
 *
 * Modernisierte Optik: Responsive Karten, Lumo-Theme-Varianten, Status-Badges,
 * Suche und leere Zustandsanzeige.
 */
@Route(value = "my-invoices", layout = MainLayout.class)
@RolesAllowed("USER")
public class MyInvoicesView extends Main implements HasDynamicTitle {

    private final Grid<MyInvoiceRow> grid = new Grid<>(MyInvoiceRow.class, false);
    private final List<MyInvoiceRow> allRows = new ArrayList<>(); // zunächst leer
    private final Div emptyState = new Div();
    private final SystemInvoiceService systemInvoiceService;
    private final SystemCompanyProfileService systemCompanyProfileService;

    private static final NumberFormat CURRENCY_FMT = NumberFormat.getCurrencyInstance(Locale.GERMANY);

    public MyInvoicesView(SystemInvoiceService systemInvoiceService,
            SystemCompanyProfileService systemCompanyProfileService) {
        this.systemInvoiceService = systemInvoiceService;
        this.systemCompanyProfileService = systemCompanyProfileService;
        addClassName("data-view");
        getStyle().set("max-width", "1100px");
        getStyle().set("margin-left", "auto");
        getStyle().set("margin-right", "auto");
        getStyle().set("padding", "var(--lumo-space-m)");

        // Toolbar / Titel
        add(new ViewToolbar(getTranslation("myinvoices.title")));

        // Kartenbereich oben
        add(createTopCards());

        // Rechnungsbereich unten
        add(createInvoicesSection());

        // Testdaten hinzufügen
        addTestInvoices();
    }

    private Component createTopCards() {
        // Container mit responsiven Spalten
        Div container = new Div();
        container.addClassName("invoice-top-grid");

        // Karte: Offene Rechnungen
        Paragraph hint = new Paragraph(getTranslation("myinvoices.hint.noopen"));
        hint.getStyle().set("color", "var(--lumo-success-text-color)");
        Div openInvoicesCard = createCard(getTranslation("myinvoices.card.open"), hint);

        // Karte: Bankverbindung
        VerticalLayout bankData = new VerticalLayout();
        bankData.setPadding(false);
        bankData.setSpacing(false);
        bankData.add(labeledValue(getTranslation("myinvoices.bank.institute"), "Hamburger Sparkasse"),
                labeledValue(getTranslation("myinvoices.bank.beneficiary"), "Assecutor Data Service GmbH"),
                labeledValue(getTranslation("myinvoices.bank.iban"), "DE67200505501217139888"),
                labeledValue(getTranslation("myinvoices.bank.reference"), "vlt-00000610"));
        Div bankCard = createCard(getTranslation("myinvoices.card.bank"), bankData);

        container.add(openInvoicesCard, bankCard);
        return container;
    }

    private Component createInvoicesSection() {
        Div card = new Div();
        // Abstand zur oberen Zeile
        card.getStyle().set("margin-top", "var(--lumo-space-l)");

        styleCard(card);

        // Kopfzeile
        H3 title = new H3(getTranslation("myinvoices.section.title"));
        title.getStyle().set("margin", "0");

        // Steuerleiste: Seitengröße + Suche
        Select<Integer> pageSize = new Select<>();
        pageSize.setItems(10, 25, 50);
        pageSize.setLabel(getTranslation("myinvoices.filter.pagesize"));
        pageSize.setValue(10);
        pageSize.setWidth("160px");

        TextField search = new TextField();
        search.setLabel(getTranslation("myinvoices.filter.search"));
        search.setPlaceholder(getTranslation("myinvoices.filter.search.placeholder"));
        search.setClearButtonVisible(true);
        search.setValueChangeMode(ValueChangeMode.EAGER);
        search.setWidth("300px");

        // Layout Kopf + Controls
        HorizontalLayout header = new HorizontalLayout();
        header.setWidthFull();
        header.setDefaultVerticalComponentAlignment(FlexComponent.Alignment.END);
        header.setJustifyContentMode(FlexComponent.JustifyContentMode.BETWEEN);
        header.add(title, new Div()); // Platzhalter zum Strecken

        HorizontalLayout controls = new HorizontalLayout(pageSize, search);
        controls.setWidthFull();
        controls.setJustifyContentMode(FlexComponent.JustifyContentMode.BETWEEN);
        controls.setAlignItems(FlexComponent.Alignment.END);

        // Grid konfigurieren
        grid.addThemeVariants(GridVariant.LUMO_ROW_STRIPES, GridVariant.LUMO_COMPACT,
                GridVariant.LUMO_WRAP_CELL_CONTENT, GridVariant.LUMO_COLUMN_BORDERS);
        grid.setWidthFull();
        grid.addColumn(new ComponentRenderer<>(row -> statusBadge(row.status())))
                .setHeader(getTranslation("myinvoices.column.status")).setAutoWidth(true).setFlexGrow(0);
        grid.addColumn(MyInvoicesView::formatInvoiceNumber).setHeader(getTranslation("myinvoices.column.number"))
                .setAutoWidth(true);
        grid.addColumn(row -> DateTimeFormatUtil.formatDate(row.date()))
                .setHeader(getTranslation("myinvoices.column.date")).setAutoWidth(true).setFlexGrow(0);
        grid.addColumn(row -> CURRENCY_FMT.format(row.amount())).setHeader(getTranslation("myinvoices.column.amount"))
                .setAutoWidth(true).setTextAlign(ColumnTextAlign.END).setFlexGrow(0);
        grid.setAllRowsVisible(true);
        grid.setItems(allRows); // zunächst leer
        grid.addItemClickListener(event -> {
            MyInvoiceRow row = event.getItem();
            if (row != null) {
                downloadInvoicePdf(row);
            }
        });

        // Leerer Zustand
        emptyState.removeAll();
        H4 emptyTitle = new H4(getTranslation("myinvoices.empty.title"));
        Paragraph emptyDesc = new Paragraph(getTranslation("myinvoices.empty.desc"));
        emptyState.add(emptyTitle, emptyDesc);
        emptyState.addClassName("empty-state-card");
        updateEmptyStateVisibility(allRows);

        // Suche (einfacher Text-Filter über alle sichtbaren Felder)
        search.addValueChangeListener(e -> applyFilter(e.getValue()));

        // Paginierungs-Buttons (vorerst ohne Funktion, als Platzhalter)
        Button prev = new Button(getTranslation("myinvoices.button.prev"), VaadinIcon.ANGLE_LEFT.create());
        Button next = new Button(getTranslation("myinvoices.button.next"), VaadinIcon.ANGLE_RIGHT.create());
        prev.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
        next.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
        prev.setEnabled(false);
        next.setEnabled(false);
        HorizontalLayout pager = new HorizontalLayout(prev, next);
        pager.setWidthFull();
        pager.setJustifyContentMode(FlexComponent.JustifyContentMode.END);

        // Zusammenbauen
        card.add(header, controls, grid, emptyState, pager);
        return card;
    }

    private void applyFilter(String filter) {
        String f = filter == null ? "" : filter.toLowerCase();
        List<MyInvoiceRow> filtered = allRows.stream()
                .filter(row -> row.status().toLowerCase().contains(f) || row.invoiceNumber().toLowerCase().contains(f)
                        || row.date().toString().toLowerCase().contains(f)
                        || String.valueOf(row.amount()).toLowerCase().contains(f))
                .toList();
        grid.setItems(filtered);
        updateEmptyStateVisibility(filtered);
    }

    private void updateEmptyStateVisibility(List<MyInvoiceRow> current) {
        emptyState.setVisible(current == null || current.isEmpty());
    }

    private static String formatInvoiceNumber(MyInvoiceRow row) {
        return row.invoiceNumber();
    }

    private Span statusBadge(String status) {
        Span badge = new Span(status);
        badge.getElement().getThemeList().add("badge pill contrast");
        String s = status == null ? "" : status.toLowerCase(Locale.ROOT);
        if (s.contains("bezahlt") || s.contains("paid")) {
            badge.getElement().getThemeList().add("success");
        } else if (s.contains("fällig") || s.contains("überfällig") || s.contains("overdue")) {
            badge.getElement().getThemeList().add("error");
        } else if (s.contains("offen") || s.contains("open")) {
            badge.getElement().getThemeList().add("warning");
        }
        return badge;
    }

    private void addTestInvoices() {
        // Drei Test-Rechnungen hinzufügen
        allRows.clear();
        allRows.add(new MyInvoiceRow("Offen", "MI-2025-001", LocalDate.now().minusDays(10), 199.99));
        allRows.add(new MyInvoiceRow("Bezahlt", "MI-2025-002", LocalDate.now().minusDays(5), 299.49));
        allRows.add(new MyInvoiceRow("Überfällig", "MI-2025-003", LocalDate.now().minusDays(20), 149.00));
        grid.setItems(allRows);
        updateEmptyStateVisibility(allRows);
    }

    private Div createCard(String title, Component content) {
        Div card = new Div();
        styleCard(card);
        H3 h3 = new H3(title);
        h3.getStyle().set("margin", "0");
        Div inner = new Div(content);
        inner.addClassName("invoice-card-inner");
        card.add(h3, inner);
        return card;
    }

    private Component labeledValue(String label, String value) {
        Paragraph p = new Paragraph();
        Span sLabel = new Span(label + " ");
        sLabel.getStyle().set("font-weight", "600");
        Span sValue = new Span(value);
        p.add(sLabel, sValue);
        p.getStyle().set("margin", "0");
        return p;
    }

    private void styleCard(Div card) {
        card.addClassName("invoice-summary-card");
        card.setWidthFull();
    }

    // Schlanke lokale Repräsentation für das Grid
    public record MyInvoiceRow(String status, String invoiceNumber, LocalDate date, double amount) {
    }

    private void downloadInvoicePdf(MyInvoiceRow row) {
        try {
            byte[] pdfBytes = generateSystemInvoicePdf(row);
            StreamResource resource = new StreamResource(row.invoiceNumber() + ".pdf",
                    () -> new ByteArrayInputStream(pdfBytes));
            resource.setContentType("application/pdf");
            resource.setCacheTime(0);

            StreamRegistration registration = UI.getCurrent().getSession().getResourceRegistry()
                    .registerResource(resource);
            UI.getCurrent().getPage().open(registration.getResourceUri().toString());
        } catch (Exception e) {
            // Optional: could log or show a simple notification
        }
    }

    private byte[] generateSystemInvoicePdf(MyInvoiceRow row) throws Exception {
        SystemInvoiceData data = systemCompanyProfileService.createSystemInvoiceData();
        data.setInvoiceNumber(row.invoiceNumber());
        data.setInvoiceDate(DateTimeFormatUtil.formatDate(row.date()));
        data.setInvoiceText("Rechnung " + row.invoiceNumber());

        // Minimal recipient information
        data.setRecipientName("Kunde");
        data.setRecipientDepartment("");
        data.setRecipientStreet("");
        data.setRecipientCity("");

        // One simple item based on row
        List<SystemInvoiceItem> items = new ArrayList<>();
        String netStr = CURRENCY_FMT.format(row.amount());
        items.add(new SystemInvoiceItem("1", "Position: " + row.invoiceNumber(), netStr, netStr));
        data.setInvoiceItems(items);

        double net = row.amount();
        double vat = Math.round(net * 0.19 * 100.0) / 100.0;
        double total = net + vat;
        data.setNetAmount(CURRENCY_FMT.format(net));
        data.setVatAmount(CURRENCY_FMT.format(vat));
        data.setTotalAmount(CURRENCY_FMT.format(total));

        return systemInvoiceService.generateInvoicePdfFromHtml(data);
    }

    @Override
    public String getPageTitle() {
        return getTranslation("page.title.myinvoices");
    }
}
