package de.assecutor.votianlt.pages.view;

import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.checkbox.Checkbox;
import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.html.H3;
import com.vaadin.flow.component.html.IFrame;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.EmailField;
import com.vaadin.flow.component.textfield.TextField;
import java.io.ByteArrayOutputStream;
import java.util.Base64;

import com.vaadin.flow.component.textfield.TextArea;
import com.vaadin.flow.component.tabs.TabSheet;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.data.validator.EmailValidator;
import com.vaadin.flow.data.value.ValueChangeMode;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import de.assecutor.votianlt.model.User;
import de.assecutor.votianlt.pages.service.UserService;
import de.assecutor.votianlt.security.SecurityService;
import jakarta.annotation.security.RolesAllowed;

@PageTitle("Profil bearbeiten")
@Route(value = "edit-profile", layout = de.assecutor.votianlt.pages.base.ui.view.MainLayout.class)
@RolesAllowed({ "USER", "ADMIN" })
public class EditProfileView extends HorizontalLayout {
    private final TextField prefixField;
    private final TextField ustIdField;
    private final TextField taxNumberField;
    private final TextField bankNameField;
    private final TextField ibanField;
    private final TextField taxRateField;
    private final TextArea introTextArea;
    private final TextArea termsTextArea;
    private final IFrame pdfFrame;

    private final Binder<User> binder = new Binder<>(User.class);
    private final User currentUser;

    public EditProfileView(UserService userService, SecurityService securityService) {
        this.currentUser = securityService.getCurrentDatabaseUser();
        setSizeFull();
        setPadding(true);
        setSpacing(true);
        setJustifyContentMode(JustifyContentMode.CENTER);
        // 2% Abstand zwischen den Spalten
        setWidthFull();
        setSpacing(false);
        getStyle().set("column-gap", "2%");

        setAlignItems(Alignment.START);

        // Linke Spalte: Formular
        VerticalLayout formColumn = new VerticalLayout();
        formColumn.setWidth("68%");
        formColumn.setHeightFull();
        formColumn.setPadding(false);
        formColumn.setSpacing(false);
        // TabSheet
        TabSheet tabSheet = new TabSheet();
        tabSheet.setSizeFull();
        formColumn.setFlexGrow(1, tabSheet);

        FormLayout form = new FormLayout();
        form.setWidthFull();
        form.setResponsiveSteps(new FormLayout.ResponsiveStep("0", 2));

        // Firmenfelder
        TextField companyField = new TextField("Firma");
        TextField companyAddField = new TextField("Firmenzusatz");
        TextField firstnameField = new TextField("Vorname");
        TextField lastnameField = new TextField("Nachname");
        TextField phoneField = new TextField("Telefonnummer");
        TextField faxField = new TextField("Telefon (Fax)");
        TextField mobileField = new TextField("Telefon (Mobil)");
        EmailField emailField = new EmailField("E-Mail-Adresse (Login)*");
        TextField streetField = new TextField("Straße");
        TextField houseNumberField = new TextField("Hausnr");
        TextField addressAddField = new TextField("Adresszusatz");
        TextField zipField = new TextField("Postleitzahl");
        TextField cityField = new TextField("Stadt");

        // Abweichende Rechnungsadresse
        Checkbox diffInvoiceAddress = new Checkbox("Abweichende Rechnungsadresse");
        diffInvoiceAddress.getStyle().set("marginTop", "1em");
        // Rechnungsadresse Felder (disabled by default)
        TextField invCompanyField = new TextField("Firma");
        TextField invCompanyAddField = new TextField("Firmenzusatz");
        TextField invFirstnameField = new TextField("Vorname");
        TextField invLastnameField = new TextField("Nachname");
        TextField invStreetField = new TextField("Straße");
        TextField invHouseNumberField = new TextField("Hausnr");
        TextField invAddressAddField = new TextField("Adresszusatz");
        TextField invZipField = new TextField("Postleitzahl");
        TextField invCityField = new TextField("Stadt");
        invCompanyField.setEnabled(false);
        invCompanyAddField.setEnabled(false);
        invFirstnameField.setEnabled(false);
        invLastnameField.setEnabled(false);
        invStreetField.setEnabled(false);
        invHouseNumberField.setEnabled(false);
        invAddressAddField.setEnabled(false);
        invZipField.setEnabled(false);
        invCityField.setEnabled(false);
        // Felder initial ausblenden
        invCompanyField.setVisible(false);
        invCompanyAddField.setVisible(false);
        invFirstnameField.setVisible(false);
        invLastnameField.setVisible(false);
        invStreetField.setVisible(false);
        invHouseNumberField.setVisible(false);
        invAddressAddField.setVisible(false);
        invZipField.setVisible(false);
        invCityField.setVisible(false);

        diffInvoiceAddress.addValueChangeListener(e -> {
            boolean enabled = e.getValue();
            invCompanyField.setEnabled(enabled);
            invCompanyAddField.setEnabled(enabled);
            invFirstnameField.setEnabled(enabled);
            invLastnameField.setEnabled(enabled);
            invStreetField.setEnabled(enabled);
            invHouseNumberField.setEnabled(enabled);
            invAddressAddField.setEnabled(enabled);
            // Sichtbarkeit an Checkbox koppeln
            invCompanyField.setVisible(enabled);
            invCompanyAddField.setVisible(enabled);
            invFirstnameField.setVisible(enabled);
            invLastnameField.setVisible(enabled);
            invStreetField.setVisible(enabled);
            invHouseNumberField.setVisible(enabled);
            invAddressAddField.setVisible(enabled);
            invZipField.setVisible(enabled);
            invCityField.setVisible(enabled);

            invZipField.setEnabled(enabled);
            invCityField.setEnabled(enabled);
        });

        // Formularfelder hinzufügen
        form.add(companyField, 2);
        form.add(companyAddField, 2);
        form.add(firstnameField, lastnameField);
        form.add(phoneField, faxField);
        form.add(mobileField, 2);
        form.add(emailField, 2);
        // Binder: Pflichtfelder und Bindings
        // UI-Pflichtfelder ohne Datenbindung (da nicht im User-Modell vorhanden)
        companyField.setRequiredIndicatorVisible(true);
        streetField.setRequiredIndicatorVisible(true);
        houseNumberField.setRequiredIndicatorVisible(true);
        zipField.setRequiredIndicatorVisible(true);
        cityField.setRequiredIndicatorVisible(true);

        binder.forField(companyField).asRequired("").bind(user -> null, (user, v) -> {
        });
        binder.forField(streetField).asRequired("").bind(user -> null, (user, v) -> {
        });
        binder.forField(houseNumberField).asRequired("").bind(user -> null, (user, v) -> {
        });
        binder.forField(zipField).asRequired("").bind(user -> null, (user, v) -> {
        });
        binder.forField(cityField).asRequired("").bind(user -> null, (user, v) -> {
        });

        binder.forField(firstnameField).asRequired("").bind(User::getFirstname, User::setFirstname);
        binder.forField(lastnameField).asRequired("").bind(User::getName, User::setName);
        binder.forField(phoneField).asRequired("").bind(User::getPhone, User::setPhone);
        binder.forField(emailField).asRequired("").withValidator(new EmailValidator("Ungültige E-Mail-Adresse"))
                .bind(User::getEmail, User::setEmail);
        // Optionale Felder
        binder.forField(mobileField).bind(User::getPhone2, User::setPhone2);
        binder.forField(faxField).bind(User::getFax, User::setFax);
        // Pflichtindikator sichtbar machen
        firstnameField.setRequiredIndicatorVisible(true);
        lastnameField.setRequiredIndicatorVisible(true);
        phoneField.setRequiredIndicatorVisible(true);
        emailField.setRequiredIndicatorVisible(true);
        // Aktuellen Benutzer in die Felder laden
        binder.readBean(currentUser);

        form.add(streetField, houseNumberField);
        form.add(addressAddField, 2);
        form.add(zipField, cityField);
        form.add(diffInvoiceAddress, 2);
        form.add(invCompanyField, 2);
        form.add(invCompanyAddField, 2);
        // Tabs hinzufügen
        form.add(invFirstnameField, invLastnameField);
        form.add(invStreetField, invHouseNumberField);
        form.add(invAddressAddField, 2);
        form.add(invZipField, invCityField);

        tabSheet.add("Stammdaten", form);

        // Karte (2. Tab)
        Span coordsLabel = new Span("53°36'25.1\"N 10°06'46.9\"E");
        coordsLabel.getStyle().set("fontWeight", "bold").set("marginTop", "1em");
        Div mapDiv = new Div();
        mapDiv.setWidth("100%");
        mapDiv.setHeight("400px");
        mapDiv.getElement().setProperty("innerHTML",
                "<iframe width='100%' height='100%' frameborder='0' style='border:0' "
                        + "src='https://www.google.com/maps/embed/v1/place?key=AIzaSyDnbitL06iLp3elmj-WtPudCykX9xvXcVE&q=53.6070,10.1125' allowfullscreen></iframe>");
        VerticalLayout mapTab = new VerticalLayout();
        mapTab.setPadding(false);
        mapTab.setSpacing(true);
        mapTab.add(coordsLabel, mapDiv);
        tabSheet.add("Karte", mapTab);
        // Dritter Tab: Rechnungsstellung
        HorizontalLayout billingTab = new HorizontalLayout();
        billingTab.setWidthFull();
        billingTab.setSpacing(true);
        billingTab.setPadding(false);

        // Linke Spalte: Rechnungsbestandteile
        VerticalLayout billingLeft = new VerticalLayout();
        billingLeft.setWidth("45%");
        billingLeft.setPadding(false);
        billingLeft.setSpacing(true);
        H3 partsTitle = new H3("Rechnungsbestandteile");
        partsTitle.getStyle().set("margin", "0 0 var(--lumo-space-s) 0");

        // Felder für Rechnungsstellung (für Live-Update)
        Checkbox billingEnabled = new Checkbox("Rechnungslegung über votianLT");
        billingEnabled.setValue(false);
        billingEnabled.addValueChangeListener(e -> toggleBilling(e.getValue()));

        prefixField = new TextField("Rechnungs Präfix");
        ustIdField = new TextField("USt-IdNr.");
        taxNumberField = new TextField("Steuernummer");
        bankNameField = new TextField("Bankname");
        ibanField = new TextField("IBAN");
        taxRateField = new TextField("Steuersatz");
        introTextArea = new TextArea("Einleitungstext");
        termsTextArea = new TextArea("Zahlungsbedingungen");
        introTextArea.setWidthFull();
        termsTextArea.setWidthFull();

        // Anfangszustand: Felder deaktiviert bis Checkbox aktiv
        setBillingFieldsEnabled(false);

        // Live-Update: EAGER und Listener
        prefixField.setValueChangeMode(ValueChangeMode.EAGER);
        ustIdField.setValueChangeMode(ValueChangeMode.EAGER);
        taxNumberField.setValueChangeMode(ValueChangeMode.EAGER);
        bankNameField.setValueChangeMode(ValueChangeMode.EAGER);
        ibanField.setValueChangeMode(ValueChangeMode.EAGER);
        taxRateField.setValueChangeMode(ValueChangeMode.EAGER);
        introTextArea.setValueChangeMode(ValueChangeMode.EAGER);
        termsTextArea.setValueChangeMode(ValueChangeMode.EAGER);
        prefixField.addValueChangeListener(e -> refreshPdf());
        ustIdField.addValueChangeListener(e -> refreshPdf());
        taxNumberField.addValueChangeListener(e -> refreshPdf());
        bankNameField.addValueChangeListener(e -> refreshPdf());
        ibanField.addValueChangeListener(e -> refreshPdf());
        taxRateField.addValueChangeListener(e -> refreshPdf());
        introTextArea.addValueChangeListener(e -> refreshPdf());
        termsTextArea.addValueChangeListener(e -> refreshPdf());

        billingLeft.add(partsTitle, billingEnabled, prefixField, ustIdField, taxNumberField, bankNameField, ibanField,
                taxRateField, introTextArea, termsTextArea);

        // Rechte Spalte: Vorschau
        VerticalLayout billingRight = new VerticalLayout();
        billingRight.setWidth("55%");
        billingRight.setPadding(false);
        billingRight.setSpacing(false);
        billingRight.setHeightFull();
        billingTab.setFlexGrow(1, billingRight);
        H3 previewTitle = new H3("Rechnungsvorschau");
        previewTitle.getStyle().set("margin", "0 0 var(--lumo-space-s) 0");

        // Echte PDF-Vorschau mittels StreamResource und iframe
        Div previewWrapper = new Div();
        previewWrapper.setWidth("100%");
        previewWrapper.setHeight("650px");
        previewWrapper.getStyle().set("overflow", "hidden").set("background", "var(--lumo-contrast-10pct)")
                .set("padding", "0");

        // Initial noch keine PDF laden (erst bei aktiver Checkbox)
        pdfFrame = new IFrame();
        pdfFrame.setWidth("99%");
        pdfFrame.setHeight("98%");
        pdfFrame.getStyle().set("border", "none");
        pdfFrame.getStyle().set("background", "var(--lumo-contrast-10pct)");
        previewWrapper.removeAll();
        previewWrapper.add(pdfFrame);

        billingRight.add(previewTitle, previewWrapper);

        billingTab.add(billingLeft, billingRight);
        tabSheet.add("Rechnungsstellung", billingTab);

        // Zweiter Tab: Einstellungen (Beispiel mit Schaltern)
        VerticalLayout switches = new VerticalLayout();
        switches.setPadding(false);
        switches.setSpacing(true);
        Checkbox locateAppUser = new Checkbox("App-Nutzer orten");
        Checkbox digitalProcess = new Checkbox("Digitale Abwicklung");
        switches.add(locateAppUser, digitalProcess);
        tabSheet.add("Einstellungen", switches);

        // Sicherheit-Tab (2FA, Passwort, Konto)
        VerticalLayout securityTab = new VerticalLayout();
        securityTab.setPadding(false);
        securityTab.setSpacing(true);

        // 2-Faktor Auth
        Checkbox twoFactor = new Checkbox("2-Faktor-Authentifizierung");
        Icon twoFactorInfo = VaadinIcon.QUESTION_CIRCLE_O.create();
        twoFactorInfo.getStyle().set("marginLeft", "0.3em");
        HorizontalLayout twoFactorLayout = new HorizontalLayout(twoFactor, twoFactorInfo);
        twoFactorLayout.setAlignItems(Alignment.CENTER);
        securityTab.add(twoFactorLayout);

        // Passwort ändern Button
        Button changePassword = new Button("Passwort ändern");
        changePassword.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
        securityTab.add(changePassword);

        // Benutzerkonto löschen Button
        Button deleteAccount = new Button("Benutzerkonto löschen");
        deleteAccount.addThemeVariants(ButtonVariant.LUMO_ERROR);
        securityTab.add(deleteAccount);

        tabSheet.add("Konto", securityTab);

        // Profil speichern Button (unten rechts)
        Button saveProfile = new Button("Profiländerungen speichern");
        saveProfile.addThemeVariants(ButtonVariant.LUMO_PRIMARY);
        saveProfile.addClickListener(e -> {
            if (binder.validate().isOk()) {
                try {
                    binder.writeBean(currentUser);
                    userService.save(currentUser);
                    Notification.show("Profil gespeichert", 3000, Notification.Position.BOTTOM_END);
                } catch (Exception ex) {
                    Notification.show("Fehler beim Speichern: " + ex.getMessage(), 4000, Notification.Position.MIDDLE);
                }
            }
        });
        // Tabs dem linken Bereich hinzufügen
        formColumn.add(tabSheet);

        // Button horizontal zentrieren unterhalb der Tabs
        HorizontalLayout buttonBar = new HorizontalLayout(saveProfile);
        buttonBar.setWidthFull();
        buttonBar.setJustifyContentMode(JustifyContentMode.CENTER);
        buttonBar.setPadding(false);
        buttonBar.setSpacing(false);
        // 20px Abstand nach oben
        buttonBar.getStyle().set("margin-top", "20px");
        // Fixieren am unteren Rand
        buttonBar.getStyle().set("position", "sticky");
        buttonBar.getStyle().set("bottom", "0");
        buttonBar.getStyle().set("background", "var(--lumo-base-color)");
        buttonBar.getStyle().set("padding", "var(--lumo-space-s) 0");
        buttonBar.getStyle().set("z-index", "1");
        formColumn.add(buttonBar);
        add(formColumn);
    }

    // PDF neu rendern und iframe aktualisieren
    // Felder im Billing-Tab aktivieren/deaktivieren
    private void setBillingFieldsEnabled(boolean enabled) {
        if (prefixField != null)
            prefixField.setEnabled(enabled);
        if (ustIdField != null)
            ustIdField.setEnabled(enabled);
        if (taxNumberField != null)
            taxNumberField.setEnabled(enabled);
        if (bankNameField != null)
            bankNameField.setEnabled(enabled);
        if (ibanField != null)
            ibanField.setEnabled(enabled);
        if (taxRateField != null)
            taxRateField.setEnabled(enabled);
        if (introTextArea != null)
            introTextArea.setEnabled(enabled);
        if (termsTextArea != null)
            termsTextArea.setEnabled(enabled);
    }

    // Checkbox steuert Aktivierung und PDF
    private void toggleBilling(boolean enabled) {
        setBillingFieldsEnabled(enabled);
        if (enabled) {
            refreshPdf();
        } else {
            if (pdfFrame != null) {
                pdfFrame.setSrc("about:blank");
            }
        }
        // Sicherstellen, dass das IFrame den verfügbaren Raum nutzt
        if (pdfFrame != null) {
            pdfFrame.setWidth("100%");
            pdfFrame.setHeight("100%");
            pdfFrame.getStyle().set("border", "none");
            pdfFrame.getStyle().set("display", "block");
        }
    }

    private void refreshPdf() {
        byte[] bytes = generatePreviewPdf();
        String dataUrl = "data:application/pdf;base64," + Base64.getEncoder().encodeToString(bytes)
                + "#toolbar=0&navpanes=0&statusbar=0&view=Fit&zoom=page-fit";
        if (pdfFrame != null) {
            pdfFrame.setSrc(dataUrl);
        }
    }

    // Einfache PDF-Vorschau generieren (kann später durch echte Logik ersetzt
    // werden)
    private byte[] generatePreviewPdf() {
        try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
            com.lowagie.text.Document document = new com.lowagie.text.Document();
            com.lowagie.text.pdf.PdfWriter.getInstance(document, out);
            document.open();
            document.add(new com.lowagie.text.Paragraph("Rechnungsvorschau"));
            document.add(new com.lowagie.text.Paragraph(" "));
            document.add(new com.lowagie.text.Paragraph("Rechnungs Präfix: " + safe(prefixField)));
            document.add(new com.lowagie.text.Paragraph("USt-IdNr.: " + safe(ustIdField)));
            document.add(new com.lowagie.text.Paragraph("Steuernummer: " + safe(taxNumberField)));
            document.add(new com.lowagie.text.Paragraph("Bankname: " + safe(bankNameField)));
            document.add(new com.lowagie.text.Paragraph("IBAN: " + safe(ibanField)));
            document.add(new com.lowagie.text.Paragraph("Steuersatz: " + safe(taxRateField)));
            document.add(new com.lowagie.text.Paragraph(" "));
            document.add(new com.lowagie.text.Paragraph("Einleitungstext:"));
            document.add(new com.lowagie.text.Paragraph(safe(introTextArea)));
            document.add(new com.lowagie.text.Paragraph(" "));
            document.add(new com.lowagie.text.Paragraph("Zahlungsbedingungen:"));
            document.add(new com.lowagie.text.Paragraph(safe(termsTextArea)));
            document.close();
            return out.toByteArray();
        } catch (Exception e) {
            throw new RuntimeException("PDF-Generierung fehlgeschlagen: " + e.getMessage(), e);
        }
    }

    // Utility: safe getter für TextField/TextArea
    private String safe(TextField f) {
        return f != null && f.getValue() != null ? f.getValue() : "";
    }

    private String safe(TextArea f) {
        return f != null && f.getValue() != null ? f.getValue() : "";
    }

}
