"""
Allauth forms as mizan server functions.

This module wraps allauth forms with mizanFormMixin, exposing them as
typed server functions for the React frontend.

Each form becomes three server functions:
  - {name}.schema - Get form field definitions
  - {name}.validate - Validate form data
  - {name}.submit - Submit form

Import this module in your app's ready() to register the forms:

    class MyAppConfig(AppConfig):
        def ready(self):
            import mizan.allauth.forms  # noqa
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

from django.http import HttpRequest

from mizan.forms import mizanFormMixin, mizanFormMeta

# Account forms
from allauth.account.forms import (
    AddEmailForm,
    ChangePasswordForm,
    ConfirmLoginCodeForm,
    LoginForm,
    RequestLoginCodeForm,
    ResetPasswordForm,
    ResetPasswordKeyForm,
    SetPasswordForm,
    SignupForm,
    UserTokenForm,
)

# Password reauthentication form - conditionally import
try:
    from allauth.account.forms import ReauthenticateForm

    HAS_REAUTH = True
except ImportError:
    HAS_REAUTH = False

# MFA forms - conditionally import
try:
    from allauth.mfa.base.forms import AuthenticateForm as MFAAuthenticateForm
    from allauth.mfa.base.forms import ReauthenticateForm as MFAReauthenticateForm
    from allauth.mfa.totp.forms import ActivateTOTPForm, DeactivateTOTPForm
    from allauth.mfa.recovery_codes.forms import GenerateRecoveryCodesForm

    HAS_MFA = True
except ImportError:
    HAS_MFA = False

# WebAuthn forms (if available)
try:
    from allauth.mfa.webauthn.forms import AuthenticateWebAuthnForm

    HAS_WEBAUTHN = True
except ImportError:
    HAS_WEBAUTHN = False

if TYPE_CHECKING:
    from mizan.forms.schemas import FormValidation


# =============================================================================
# Account Forms
# =============================================================================


class mizanLoginForm(LoginForm, mizanFormMixin):
    """Sign in with email and password."""

    mizan = mizanFormMeta(
        name="login",
        title="Sign In",
        subtitle="Welcome back. Enter your credentials to continue.",
        submit_label="Sign In",
        live_validation=False,  # Don't validate credentials as user types
    )

    @classmethod
    def get_init_kwargs(cls, request: HttpRequest) -> dict[str, Any]:
        return {"request": request}

    def on_submit_success(self, request: HttpRequest) -> dict | None:
        self.login(request)
        return None


class mizanSignupForm(SignupForm, mizanFormMixin):
    """Create a new account."""

    mizan = mizanFormMeta(
        name="signup",
        title="Create Account",
        subtitle="Enter your details to get started.",
        submit_label="Create Account",
    )

    @classmethod
    def get_init_kwargs(cls, request: HttpRequest) -> dict[str, Any]:
        return {"request": request}

    def on_submit_success(self, request: HttpRequest) -> dict | None:
        self.save(request)
        return None


class mizanAddEmailForm(AddEmailForm, mizanFormMixin):
    """Add another email address to your account."""

    mizan = mizanFormMeta(
        name="add_email",
        title="Add Email Address",
        subtitle="Add another email address to your account.",
        submit_label="Add Email",
    )

    @classmethod
    def get_init_kwargs(cls, request: HttpRequest) -> dict[str, Any]:
        return {"request": request, "user": request.user}

    def on_submit_success(self, request: HttpRequest) -> dict | None:
        self.save()
        return None


class mizanChangePasswordForm(ChangePasswordForm, mizanFormMixin):
    """Change your account password."""

    mizan = mizanFormMeta(
        name="change_password",
        title="Change Password",
        subtitle="Update your password to keep your account secure.",
        submit_label="Change Password",
    )

    @classmethod
    def get_init_kwargs(cls, request: HttpRequest) -> dict[str, Any]:
        return {"request": request, "user": request.user}

    def on_submit_success(self, request: HttpRequest) -> dict | None:
        self.save()
        return None


class mizanSetPasswordForm(SetPasswordForm, mizanFormMixin):
    """Set a password for accounts created via social login."""

    mizan = mizanFormMeta(
        name="set_password",
        title="Set Password",
        subtitle="Create a password for your account.",
        submit_label="Set Password",
    )

    @classmethod
    def get_init_kwargs(cls, request: HttpRequest) -> dict[str, Any]:
        return {"request": request, "user": request.user}

    def on_submit_success(self, request: HttpRequest) -> dict | None:
        self.save()
        return None


class mizanResetPasswordForm(ResetPasswordForm, mizanFormMixin):
    """Request a password reset email."""

    mizan = mizanFormMeta(
        name="reset_password",
        title="Reset Password",
        subtitle="Enter your email address and we'll send you a link to reset your password.",
        submit_label="Send Reset Link",
    )

    @classmethod
    def get_init_kwargs(cls, request: HttpRequest) -> dict[str, Any]:
        return {"request": request}

    def on_submit_success(self, request: HttpRequest) -> dict | None:
        self.save(request)
        return None


class mizanResetPasswordKeyForm(ResetPasswordKeyForm, mizanFormMixin):
    """Set a new password using a reset key."""

    mizan = mizanFormMeta(
        name="reset_password_from_key",
        title="Set New Password",
        subtitle="Enter your new password below.",
        submit_label="Reset Password",
    )

    @classmethod
    def get_init_kwargs(cls, request: HttpRequest) -> dict[str, Any]:
        return {"request": request, "user": request.user}

    def on_submit_success(self, request: HttpRequest) -> dict | None:
        self.save()
        return None


class mizanRequestLoginCodeForm(RequestLoginCodeForm, mizanFormMixin):
    """Request a login code via email."""

    mizan = mizanFormMeta(
        name="request_login_code",
        title="Sign In with Code",
        subtitle="Enter your email address and we'll send you a login code.",
        submit_label="Send Code",
    )

    @classmethod
    def get_init_kwargs(cls, request: HttpRequest) -> dict[str, Any]:
        return {"request": request}

    def on_submit_success(self, request: HttpRequest) -> dict | None:
        self.save()
        return None


class mizanConfirmLoginCodeForm(ConfirmLoginCodeForm, mizanFormMixin):
    """Confirm a login code."""

    mizan = mizanFormMeta(
        name="confirm_login_code",
        title="Enter Code",
        subtitle="Enter the code we sent to your email.",
        submit_label="Verify Code",
    )

    @classmethod
    def get_init_kwargs(cls, request: HttpRequest) -> dict[str, Any]:
        return {"request": request}

    def on_submit_success(self, request: HttpRequest) -> dict | None:
        self.save()
        return None


class mizanUserTokenForm(UserTokenForm, mizanFormMixin):
    """Verify an email with a token."""

    mizan = mizanFormMeta(
        name="user_token",
        title="Verify Email",
        subtitle="Enter the verification code from your email.",
        submit_label="Verify",
    )

    @classmethod
    def get_init_kwargs(cls, request: HttpRequest) -> dict[str, Any]:
        return {"request": request}

    def on_submit_success(self, request: HttpRequest) -> dict | None:
        self.save()
        return None


# Password reauthentication - conditionally define
if HAS_REAUTH:

    class mizanReauthenticateForm(ReauthenticateForm, mizanFormMixin):
        """Re-authenticate with password for sensitive actions."""

        mizan = mizanFormMeta(
            name="reauthenticate",
            title="Confirm Your Identity",
            subtitle="Please enter your password to continue.",
            submit_label="Confirm",
            live_validation=False,
        )

        @classmethod
        def get_init_kwargs(cls, request: HttpRequest) -> dict[str, Any]:
            return {"request": request, "user": request.user}

        def on_submit_success(self, request: HttpRequest) -> dict | None:
            from allauth.account.internal.flows import reauthentication

            reauthentication.reauthenticate_by_password(request)
            return None


# =============================================================================
# MFA Forms
# =============================================================================

if HAS_MFA:

    class mizanMFAAuthenticateForm(MFAAuthenticateForm, mizanFormMixin):
        """Authenticate with MFA during login."""

        mizan = mizanFormMeta(
            name="mfa_authenticate",
            title="Two-Factor Authentication",
            subtitle="Enter your authentication code to continue.",
            submit_label="Verify",
        )

        @classmethod
        def get_init_kwargs(cls, request: HttpRequest) -> dict[str, Any]:
            return {"request": request, "user": request.user}

        def on_submit_success(self, request: HttpRequest) -> dict | None:
            self.save()
            return None

    class mizanMFAReauthenticateForm(MFAReauthenticateForm, mizanFormMixin):
        """Re-authenticate with MFA for sensitive actions."""

        mizan = mizanFormMeta(
            name="mfa_reauthenticate",
            title="Confirm Your Identity",
            subtitle="Enter your authentication code to continue.",
            submit_label="Confirm",
        )

        @classmethod
        def get_init_kwargs(cls, request: HttpRequest) -> dict[str, Any]:
            return {"request": request, "user": request.user}

        def on_submit_success(self, request: HttpRequest) -> dict | None:
            self.save()
            return None

    class mizanActivateTOTPForm(ActivateTOTPForm, mizanFormMixin):
        """Activate TOTP authenticator."""

        mizan = mizanFormMeta(
            name="activate_totp",
            title="Set Up Authenticator",
            subtitle="Enter the code from your authenticator app to complete setup.",
            submit_label="Activate",
        )

        @classmethod
        def get_init_kwargs(cls, request: HttpRequest) -> dict[str, Any]:
            return {"request": request, "user": request.user}

        def on_submit_success(self, request: HttpRequest) -> dict | None:
            self.save()
            return None

    class mizanDeactivateTOTPForm(DeactivateTOTPForm, mizanFormMixin):
        """Deactivate TOTP authenticator."""

        mizan = mizanFormMeta(
            name="deactivate_totp",
            title="Disable Authenticator",
            subtitle="Enter your password to disable two-factor authentication.",
            submit_label="Disable",
        )

        @classmethod
        def get_init_kwargs(cls, request: HttpRequest) -> dict[str, Any]:
            return {"request": request, "user": request.user}

        def on_submit_success(self, request: HttpRequest) -> dict | None:
            self.save()
            return None

    class mizanGenerateRecoveryCodesForm(GenerateRecoveryCodesForm, mizanFormMixin):
        """Generate new recovery codes."""

        mizan = mizanFormMeta(
            name="generate_recovery_codes",
            title="Recovery Codes",
            subtitle="Generate new recovery codes for your account.",
            submit_label="Generate Codes",
        )

        @classmethod
        def get_init_kwargs(cls, request: HttpRequest) -> dict[str, Any]:
            return {"request": request, "user": request.user}

        def on_submit_success(self, request: HttpRequest) -> dict | None:
            self.save()
            return None


if HAS_WEBAUTHN:

    class mizanAuthenticateWebAuthnForm(AuthenticateWebAuthnForm, mizanFormMixin):
        """Authenticate with WebAuthn security key."""

        mizan = mizanFormMeta(
            name="webauthn_authenticate",
            title="Security Key",
            subtitle="Use your security key to authenticate.",
            submit_label="Use Security Key",
        )

        @classmethod
        def get_init_kwargs(cls, request: HttpRequest) -> dict[str, Any]:
            return {"request": request, "user": request.user}

        def on_submit_success(self, request: HttpRequest) -> dict | None:
            self.save()
            return None
