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.html.H1;
import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.formlayout.FormLayout;
import com.vaadin.flow.component.textfield.PasswordField;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.VaadinSession;
import com.vaadin.flow.server.auth.AnonymousAllowed;
import de.assecutor.votianlt.pages.service.UserService;
import de.assecutor.votianlt.service.EmailService;

import java.security.SecureRandom;
import java.time.Duration;
import java.time.LocalDateTime;

@Route("register")
@PageTitle("Bei VotianLT registrieren")
@AnonymousAllowed
public class RegisterView extends VerticalLayout {
    private final UserService userService;
    private final EmailService emailService;

    private TextField emailField;
    private PasswordField passwordField;
    private PasswordField confirmPasswordField;

    // Zusätzliche Pflichtfelder aus EditProfileView
    private TextField firstNameField;
    private TextField lastNameField;
    private TextField phoneField;
    private TextField companyField;
    private TextField streetField;
    private TextField houseNumberField;
    private TextField zipField;
    private TextField cityField;

    private TextField codeField;
    private Button submitButton;
    private Button verifyButton;
    private Button resendButton;

    private String pendingCode; // 6-stelliger Code im View-Zustand
    private LocalDateTime codeExpiresAt;
    private LocalDateTime lastSentAt;
    private boolean awaitingVerification = false;

    public RegisterView(UserService userService, EmailService emailService) {
        this.userService = userService;
        this.emailService = emailService;
        // Layout-Konfiguration für vollständige Zentrierung
        setSizeFull();
        setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
        setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.CENTER);
        setPadding(true);
        setSpacing(false);

        // Hauptcontainer für das Formular
        VerticalLayout formContainer = createFormContainer();
        add(formContainer);
    }

    private VerticalLayout createFormContainer() {
        VerticalLayout container = new VerticalLayout();
        container.setWidth("980px");
        container.setPadding(true);
        container.setSpacing(true);
        container.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.STRETCH);

        // Styling für den Container
        container.getStyle().set("background-color", "var(--lumo-base-color)");
        container.getStyle().set("border", "1px solid var(--lumo-contrast-20pct)");
        container.getStyle().set("border-radius", "var(--lumo-border-radius-m)");
        container.getStyle().set("box-shadow", "var(--lumo-box-shadow-s)");

        // Titel
        H1 title = new H1("Registrierung");
        title.getStyle().set("text-align", "center");
        title.getStyle().set("color", "var(--lumo-primary-color)");
        title.getStyle().set("margin-top", "0");

        H2 subtitle = new H2("Erstellen Sie Ihr VotianLT-Konto");
        subtitle.getStyle().set("text-align", "center");
        subtitle.getStyle().set("color", "var(--lumo-secondary-text-color)");
        subtitle.getStyle().set("font-size", "var(--lumo-font-size-l)");
        subtitle.getStyle().set("font-weight", "normal");
        subtitle.getStyle().set("margin-bottom", "var(--lumo-space-l)");

        // Formularfelder
        emailField = new TextField("E-Mail-Adresse");
        emailField.setWidthFull();
        emailField.setRequired(true);
        emailField.setPlaceholder("");

        passwordField = new PasswordField("Passwort");
        passwordField.setWidthFull();
        passwordField.setRequired(true);
        passwordField.setPlaceholder("Mindestens 6 Zeichen");

        confirmPasswordField = new PasswordField("Passwort bestätigen");
        confirmPasswordField.setWidthFull();
        confirmPasswordField.setRequired(true);
        confirmPasswordField.setPlaceholder("Passwort wiederholen");

        // Pflichtfelder aus EditProfileView
        firstNameField = new TextField("Vorname");
        firstNameField.setWidthFull();
        firstNameField.setRequired(true);
        lastNameField = new TextField("Nachname");
        lastNameField.setWidthFull();
        lastNameField.setRequired(true);
        phoneField = new TextField("Telefonnummer");
        phoneField.setWidthFull();
        phoneField.setRequired(true);
        companyField = new TextField("Firma");
        companyField.setWidthFull();
        companyField.setRequired(true);
        streetField = new TextField("Straße");
        streetField.setWidthFull();
        streetField.setRequired(true);
        houseNumberField = new TextField("Hausnr");
        houseNumberField.setWidthFull();
        houseNumberField.setRequired(true);
        zipField = new TextField("Postleitzahl");
        zipField.setWidthFull();
        zipField.setRequired(true);
        cityField = new TextField("Stadt");
        cityField.setWidthFull();
        cityField.setRequired(true);

        codeField = new TextField("Bestätigungscode (6 Ziffern)");
        codeField.setWidthFull();
        codeField.setMaxLength(6);
        codeField.setPattern("\\d{6}");
        codeField.setPlaceholder("z. B. 123456");
        codeField.setVisible(false);
        codeField.addValueChangeListener(e -> {
            String v = e.getValue();
            if (v != null && !v.matches("\\d*")) {
                codeField.setValue(v.replaceAll("[^0-9]", ""));
            }
        });

        // Buttons
        submitButton = new Button("Registrieren", event -> onStartRegistration());
        submitButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_LARGE);
        submitButton.setWidthFull();

        verifyButton = new Button("Code prüfen und registrieren", event -> onVerifyCode());
        verifyButton.addThemeVariants(ButtonVariant.LUMO_SUCCESS);
        verifyButton.setWidthFull();
        verifyButton.setVisible(false);

        resendButton = new Button("Code erneut senden", event -> onResendCode());
        resendButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
        resendButton.setWidthFull();
        resendButton.setVisible(false);

        // Zurück-Link
        Button backButton = new Button("Zurück zur Startseite", event -> getUI().ifPresent(ui -> ui.navigate("")));
        backButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
        backButton.setWidthFull();

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

        // Firma zuerst, volle Breite
        form.add(companyField);
        form.setColspan(companyField, 2);

        // Zugangsdaten
        form.add(emailField, passwordField, confirmPasswordField);
        form.setColspan(emailField, 2);

        // Personen-/Adressdaten
        form.add(firstNameField, lastNameField);
        form.add(phoneField);
        form.add(streetField, houseNumberField);
        form.add(zipField, cityField);

        // Code und Verifikations-Buttons (ausgeblendet bis Versand)
        form.add(codeField);
        form.setColspan(codeField, 2);

        // Button-Zeile: Verifizieren/Resenden nebeneinander
        HorizontalLayout verifyRow = new HorizontalLayout(verifyButton, resendButton);
        verifyRow.setWidthFull();
        verifyRow.setSpacing(true);
        verifyRow.setAlignItems(FlexComponent.Alignment.STRETCH);
        verifyRow.setFlexGrow(1, verifyButton, resendButton);
        form.add(verifyRow);
        form.setColspan(verifyRow, 2);

        // Haupt-Submit-Button und Zurück-Link über volle Breite
        // Fester Abstand oberhalb des Registrieren-Buttons
        com.vaadin.flow.component.html.Div spacer = new com.vaadin.flow.component.html.Div();
        spacer.getStyle().set("height", "15px");
        form.add(spacer);
        form.setColspan(spacer, 2);

        form.add(submitButton);
        form.setColspan(submitButton, 2);
        form.add(backButton);
        form.setColspan(backButton, 2);

        container.add(title, subtitle, form);
        return container;
    }

    private void onStartRegistration() {
        var email = emailField.getValue().trim();
        var password = passwordField.getValue();
        var confirmPassword = confirmPasswordField.getValue();

        // Validierung
        if (email.isEmpty()) {
            Notification.show("Bitte geben Sie eine E-Mail-Adresse ein.", 3000, Notification.Position.MIDDLE);
            emailField.focus();
            return;
        }
        if (!email.contains("@") || !email.contains(".")) {
            Notification.show("Bitte geben Sie eine gültige E-Mail-Adresse ein.", 3000, Notification.Position.MIDDLE);
            emailField.focus();
            return;
        }
        if (userService.existsByEmail(email)) {
            Notification.show("Ein Benutzer mit dieser E-Mail-Adresse existiert bereits.", 4000,
                    Notification.Position.MIDDLE);
            return;
        }
        if (password.isEmpty()) {
            Notification.show("Bitte geben Sie ein Passwort ein.", 3000, Notification.Position.MIDDLE);
            passwordField.focus();
            return;
        }
        if (password.length() < 6) {
            Notification.show("Das Passwort muss mindestens 6 Zeichen lang sein.", 3000, Notification.Position.MIDDLE);
            passwordField.focus();
            return;
        }
        if (!password.equals(confirmPassword)) {
            Notification.show("Die Passwörter stimmen nicht überein.", 3000, Notification.Position.MIDDLE);
            confirmPasswordField.focus();
            return;
        }

        // Weitere Pflichtfelder prüfen (aus Edit-Profile)
        var firstName = firstNameField.getValue() != null ? firstNameField.getValue().trim() : "";
        if (firstName.isEmpty()) {
            Notification.show("Bitte geben Sie Ihren Vornamen ein.", 3000, Notification.Position.MIDDLE);
            firstNameField.focus();
            return;
        }
        var lastName = lastNameField.getValue() != null ? lastNameField.getValue().trim() : "";
        if (lastName.isEmpty()) {
            Notification.show("Bitte geben Sie Ihren Nachnamen ein.", 3000, Notification.Position.MIDDLE);
            lastNameField.focus();
            return;
        }
        var phone = phoneField.getValue() != null ? phoneField.getValue().trim() : "";
        if (phone.isEmpty()) {
            Notification.show("Bitte geben Sie Ihre Telefonnummer ein.", 3000, Notification.Position.MIDDLE);
            phoneField.focus();
            return;
        }
        var company = companyField.getValue() != null ? companyField.getValue().trim() : "";
        if (company.isEmpty()) {
            Notification.show("Bitte geben Sie den Firmennamen ein.", 3000, Notification.Position.MIDDLE);
            companyField.focus();
            return;
        }
        var street = streetField.getValue() != null ? streetField.getValue().trim() : "";
        if (street.isEmpty()) {
            Notification.show("Bitte geben Sie die Straße ein.", 3000, Notification.Position.MIDDLE);
            streetField.focus();
            return;
        }
        var houseNo = houseNumberField.getValue() != null ? houseNumberField.getValue().trim() : "";
        if (houseNo.isEmpty()) {
            Notification.show("Bitte geben Sie die Hausnummer ein.", 3000, Notification.Position.MIDDLE);
            houseNumberField.focus();
            return;
        }
        var zip = zipField.getValue() != null ? zipField.getValue().trim() : "";
        if (zip.isEmpty()) {
            Notification.show("Bitte geben Sie die Postleitzahl ein.", 3000, Notification.Position.MIDDLE);
            zipField.focus();
            return;
        }
        var city = cityField.getValue() != null ? cityField.getValue().trim() : "";
        if (city.isEmpty()) {
            Notification.show("Bitte geben Sie die Stadt ein.", 3000, Notification.Position.MIDDLE);
            cityField.focus();
            return;
        }

        // Alles ok: Code erzeugen und senden
        sendVerificationCode(email);
    }

    private void sendVerificationCode(String email) {
        // Rate-Limit: 60 Sekunden zwischen Sendungen
        if (lastSentAt != null && Duration.between(lastSentAt, LocalDateTime.now()).getSeconds() < 60) {
            long wait = 60 - Duration.between(lastSentAt, LocalDateTime.now()).getSeconds();
            Notification.show("Bitte warten Sie " + wait + " Sekunden, bevor Sie den Code erneut senden.", 4000,
                    Notification.Position.MIDDLE);
            return;
        }
        String code = generateSixDigitCode();
        pendingCode = code;
        codeExpiresAt = LocalDateTime.now().plusMinutes(10);
        lastSentAt = LocalDateTime.now();

        String subject = "Ihr VotianLT Bestätigungscode";
        String body = "Ihr Bestätigungscode lautet: " + code + "\n\n" + "Dieser Code ist 10 Minuten gültig.\n"
                + "Wenn Sie diese Registrierung nicht angefragt haben, ignorieren Sie diese E-Mail.";
        try {
            emailService.sendSimpleEmail(email, subject, body);
            awaitingVerification = true;
            // UI umstellen: Code-Eingabe anzeigen
            codeField.clear();
            codeField.setVisible(true);
            verifyButton.setVisible(true);
            resendButton.setVisible(true);

            emailField.setReadOnly(true);
            passwordField.setReadOnly(true);
            confirmPasswordField.setReadOnly(true);

            // Zusätzliche Felder sperren
            firstNameField.setReadOnly(true);
            lastNameField.setReadOnly(true);
            phoneField.setReadOnly(true);
            companyField.setReadOnly(true);
            streetField.setReadOnly(true);
            houseNumberField.setReadOnly(true);
            zipField.setReadOnly(true);
            cityField.setReadOnly(true);

            submitButton.setEnabled(false);

            Notification.show("Ein Bestätigungscode wurde an " + email + " gesendet.", 4000,
                    Notification.Position.MIDDLE);
        } catch (Exception e) {
            awaitingVerification = false;
            Notification.show("Fehler beim Senden der E-Mail: " + e.getMessage(), 5000, Notification.Position.MIDDLE);
        }
    }

    private void onVerifyCode() {
        if (!awaitingVerification) {
            Notification.show("Bitte starten Sie zuerst die Registrierung.", 3000, Notification.Position.MIDDLE);
            return;
        }
        String entered = codeField.getValue() != null ? codeField.getValue().trim() : "";
        if (!entered.matches("\\d{6}")) {
            Notification.show("Bitte geben Sie den 6-stelligen Code ein.", 3000, Notification.Position.MIDDLE);
            return;
        }
        if (codeExpiresAt == null || LocalDateTime.now().isAfter(codeExpiresAt)) {
            Notification.show("Der Code ist abgelaufen. Bitte senden Sie einen neuen Code.", 4000,
                    Notification.Position.MIDDLE);
            return;
        }
        if (!entered.equals(pendingCode)) {
            Notification.show("Der eingegebene Code ist ungültig.", 3000, Notification.Position.MIDDLE);
            return;
        }

        // Code korrekt -> Benutzer erstellen
        var email = emailField.getValue().trim();
        var password = passwordField.getValue();
        var firstName = firstNameField.getValue() != null ? firstNameField.getValue().trim() : "";
        var lastName = lastNameField.getValue() != null ? lastNameField.getValue().trim() : "";
        var phone = phoneField.getValue() != null ? phoneField.getValue().trim() : "";
        try {
            var user = userService.createUser(email, password, firstName, lastName);
            // Persistiere zusätzliche Profil-/Adressdaten
            if (!phone.isBlank())
                user.setPhone(phone);
            var company = companyField.getValue() != null ? companyField.getValue().trim() : null;
            var street = streetField.getValue() != null ? streetField.getValue().trim() : null;
            var houseNo = houseNumberField.getValue() != null ? houseNumberField.getValue().trim() : null;
            var zip = zipField.getValue() != null ? zipField.getValue().trim() : null;
            var city = cityField.getValue() != null ? cityField.getValue().trim() : null;
            user.setCompany(company);
            user.setStreet(street);
            user.setHouseNumber(houseNo);
            user.setZip(zip);
            user.setCity(city);
            userService.save(user);
            VaadinSession.getCurrent().setAttribute("flashMessage",
                    "Registrierung erfolgreich. Bitte melden Sie sich an.");
            getUI().ifPresent(ui -> ui.navigate("login"));
        } catch (RuntimeException e) {
            Notification.show("Registrierung fehlgeschlagen: " + e.getMessage(), 5000, Notification.Position.MIDDLE);
        }
    }

    private void onResendCode() {
        if (emailField.isReadOnly()) {
            sendVerificationCode(emailField.getValue().trim());
        }
    }

    private String generateSixDigitCode() {
        SecureRandom random = new SecureRandom();
        int num = random.nextInt(1_000_000); // 0..999999
        return String.format("%06d", num);
    }
}
