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.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.HasDynamicTitle;
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")
@AnonymousAllowed
public class RegisterView extends VerticalLayout implements HasDynamicTitle {
    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);
        addClassName("form-page");

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

    private VerticalLayout createFormContainer() {
        VerticalLayout container = new VerticalLayout();
        container.setWidth("980px");
        container.setMaxWidth("100%");
        container.setPadding(true);
        container.setSpacing(true);
        container.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.STRETCH);
        container.addClassNames("form-shell", "form-card");

        // Titel
        H1 title = new H1(getTranslation("register.title"));
        title.addClassName("form-title");

        // Formularfelder
        emailField = new TextField(getTranslation("register.email"));
        emailField.setWidthFull();
        emailField.setRequired(true);
        emailField.setPlaceholder("");

        passwordField = new PasswordField(getTranslation("register.password"));
        passwordField.setWidthFull();
        passwordField.setRequired(true);
        passwordField.setPlaceholder(getTranslation("register.password.placeholder"));

        confirmPasswordField = new PasswordField(getTranslation("register.password.confirm"));
        confirmPasswordField.setWidthFull();
        confirmPasswordField.setRequired(true);
        confirmPasswordField.setPlaceholder(getTranslation("register.password.confirm.placeholder"));

        // Pflichtfelder aus EditProfileView
        firstNameField = new TextField(getTranslation("register.firstname"));
        firstNameField.setWidthFull();
        firstNameField.setRequired(true);
        lastNameField = new TextField(getTranslation("register.lastname"));
        lastNameField.setWidthFull();
        lastNameField.setRequired(true);
        phoneField = new TextField(getTranslation("register.phone"));
        phoneField.setWidthFull();
        phoneField.setRequired(true);
        companyField = new TextField(getTranslation("register.company"));
        companyField.setWidthFull();
        companyField.setRequired(true);
        streetField = new TextField(getTranslation("register.street"));
        streetField.setWidthFull();
        streetField.setRequired(true);
        houseNumberField = new TextField(getTranslation("register.housenr"));
        houseNumberField.setWidthFull();
        houseNumberField.setRequired(true);
        zipField = new TextField(getTranslation("register.zip"));
        zipField.setWidthFull();
        zipField.setRequired(true);
        cityField = new TextField(getTranslation("register.city"));
        cityField.setWidthFull();
        cityField.setRequired(true);

        codeField = new TextField(getTranslation("register.code.label"));
        codeField.setWidthFull();
        codeField.setMaxLength(6);
        codeField.setPattern("\\d{6}");
        codeField.setPlaceholder(getTranslation("register.code.placeholder"));
        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(getTranslation("register.button.submit"), event -> onStartRegistration());
        submitButton.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_LARGE);
        submitButton.setWidthFull();

        verifyButton = new Button(getTranslation("register.button.verify"), event -> onVerifyCode());
        verifyButton.addThemeVariants(ButtonVariant.LUMO_SUCCESS);
        verifyButton.setWidthFull();
        verifyButton.setVisible(false);

        resendButton = new Button(getTranslation("register.button.resend"), event -> onResendCode());
        resendButton.addThemeVariants(ButtonVariant.LUMO_TERTIARY);
        resendButton.setWidthFull();
        resendButton.setVisible(false);

        // Zurück-Link
        Button backButton = new Button(getTranslation("register.button.back"),
                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, 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(getTranslation("register.notification.email.required"), 3000,
                    Notification.Position.MIDDLE);
            emailField.focus();
            return;
        }
        if (!email.contains("@") || !email.contains(".")) {
            Notification.show(getTranslation("register.notification.email.invalid"), 3000,
                    Notification.Position.MIDDLE);
            emailField.focus();
            return;
        }
        if (userService.existsByEmail(email)) {
            Notification.show(getTranslation("register.notification.email.duplicate"), 4000,
                    Notification.Position.MIDDLE);
            return;
        }
        if (password.isEmpty()) {
            Notification.show(getTranslation("register.notification.password.required"), 3000,
                    Notification.Position.MIDDLE);
            passwordField.focus();
            return;
        }
        if (password.length() < 6) {
            Notification.show(getTranslation("register.notification.password.min"), 3000, Notification.Position.MIDDLE);
            passwordField.focus();
            return;
        }
        if (!password.equals(confirmPassword)) {
            Notification.show(getTranslation("register.notification.password.mismatch"), 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(getTranslation("register.notification.firstname.required"), 3000,
                    Notification.Position.MIDDLE);
            firstNameField.focus();
            return;
        }
        var lastName = lastNameField.getValue() != null ? lastNameField.getValue().trim() : "";
        if (lastName.isEmpty()) {
            Notification.show(getTranslation("register.notification.lastname.required"), 3000,
                    Notification.Position.MIDDLE);
            lastNameField.focus();
            return;
        }
        var phone = phoneField.getValue() != null ? phoneField.getValue().trim() : "";
        if (phone.isEmpty()) {
            Notification.show(getTranslation("register.notification.phone.required"), 3000,
                    Notification.Position.MIDDLE);
            phoneField.focus();
            return;
        }
        var company = companyField.getValue() != null ? companyField.getValue().trim() : "";
        if (company.isEmpty()) {
            Notification.show(getTranslation("register.notification.company.required"), 3000,
                    Notification.Position.MIDDLE);
            companyField.focus();
            return;
        }
        var street = streetField.getValue() != null ? streetField.getValue().trim() : "";
        if (street.isEmpty()) {
            Notification.show(getTranslation("register.notification.street.required"), 3000,
                    Notification.Position.MIDDLE);
            streetField.focus();
            return;
        }
        var houseNo = houseNumberField.getValue() != null ? houseNumberField.getValue().trim() : "";
        if (houseNo.isEmpty()) {
            Notification.show(getTranslation("register.notification.housenr.required"), 3000,
                    Notification.Position.MIDDLE);
            houseNumberField.focus();
            return;
        }
        var zip = zipField.getValue() != null ? zipField.getValue().trim() : "";
        if (zip.isEmpty()) {
            Notification.show(getTranslation("register.notification.zip.required"), 3000, Notification.Position.MIDDLE);
            zipField.focus();
            return;
        }
        var city = cityField.getValue() != null ? cityField.getValue().trim() : "";
        if (city.isEmpty()) {
            Notification.show(getTranslation("register.notification.city.required"), 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(getTranslation("passwordreset.notification.wait", wait), 4000,
                    Notification.Position.MIDDLE);
            return;
        }
        String code = generateSixDigitCode();
        pendingCode = code;
        codeExpiresAt = LocalDateTime.now().plusMinutes(10);
        lastSentAt = LocalDateTime.now();

        String subject = getTranslation("email.2fa.subject");
        String body = getTranslation("email.2fa.body", code);
        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(getTranslation("register.notification.code.sent", email), 4000,
                    Notification.Position.MIDDLE);
        } catch (Exception e) {
            awaitingVerification = false;
            Notification.show(getTranslation("register.notification.code.emailerror", e.getMessage()), 5000,
                    Notification.Position.MIDDLE);
        }
    }

    private void onVerifyCode() {
        if (!awaitingVerification) {
            Notification.show(getTranslation("register.notification.code.startfirst"), 3000,
                    Notification.Position.MIDDLE);
            return;
        }
        String entered = codeField.getValue() != null ? codeField.getValue().trim() : "";
        if (!entered.matches("\\d{6}")) {
            Notification.show(getTranslation("register.notification.code.required"), 3000,
                    Notification.Position.MIDDLE);
            return;
        }
        if (codeExpiresAt == null || LocalDateTime.now().isAfter(codeExpiresAt)) {
            Notification.show(getTranslation("register.notification.code.expired"), 4000, Notification.Position.MIDDLE);
            return;
        }
        if (!entered.equals(pendingCode)) {
            Notification.show(getTranslation("register.notification.code.invalid"), 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", getTranslation("register.notification.success"));
            getUI().ifPresent(ui -> ui.navigate("login"));
        } catch (RuntimeException e) {
            Notification.show(getTranslation("register.notification.failed", 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);
    }

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