from __future__ import annotations

from flask_wtf import FlaskForm
from flask_wtf.file import FileAllowed, FileField
from wtforms import (
    BooleanField,
    DateField,
    IntegerField,
    PasswordField,
    StringField,
    SelectField,
    SubmitField,
    TextAreaField,
)
from wtforms.validators import DataRequired, EqualTo, Length, NumberRange, Optional, Regexp, ValidationError

from .models import User
from .services.app_settings import QUICK_TASK_EFFORTS


EMAIL_LIKE = Regexp(r"^[^@\s]+@[^@\s]+\.[^@\s]+$", message="Bitte gib eine gültige E-Mail-Adresse ein.")


class LoginForm(FlaskForm):
    email = StringField("E-Mail", validators=[DataRequired(), EMAIL_LIKE, Length(max=255)])
    password = PasswordField("Passwort", validators=[DataRequired(), Length(min=6, max=128)])
    remember_me = BooleanField("Angemeldet bleiben")
    submit = SubmitField("Einloggen")


class RegisterForm(FlaskForm):
    name = StringField("Name", validators=[DataRequired(), Length(min=2, max=120)])
    email = StringField("E-Mail", validators=[DataRequired(), EMAIL_LIKE, Length(max=255)])
    password = PasswordField("Passwort", validators=[DataRequired(), Length(min=6, max=128)])
    password_confirm = PasswordField(
        "Passwort wiederholen",
        validators=[DataRequired(), EqualTo("password", message="Die Passwörter stimmen nicht überein.")],
    )
    submit = SubmitField("Konto erstellen")

    def validate_email(self, field) -> None:
        if User.query.filter_by(email=field.data.lower().strip()).first():
            raise ValidationError("Diese E-Mail-Adresse ist bereits vergeben.")


class TaskForm(FlaskForm):
    title = StringField("Titel", validators=[DataRequired(), Length(min=2, max=160)])
    description = TextAreaField("Beschreibung", validators=[Optional(), Length(max=2000)])
    default_points = IntegerField("Punkte", validators=[DataRequired(), NumberRange(min=1, max=500)], default=10)
    assigned_user_id = SelectField("Zugewiesen an", coerce=int, validators=[DataRequired()])
    assigned_user_secondary_id = SelectField("Zweite Person", coerce=int, validators=[Optional()], default=0)
    due_date = DateField("Fälligkeitsdatum", format="%Y-%m-%d", validators=[DataRequired()])
    recurrence_interval_value = IntegerField(
        "Intervallwert",
        validators=[Optional(), NumberRange(min=1, max=365)],
        default=1,
    )
    recurrence_interval_unit = SelectField(
        "Wiederholung",
        choices=[
            ("none", "Einmalig"),
            ("days", "Alle X Tage"),
            ("weeks", "Alle X Wochen"),
            ("months", "Alle X Monate"),
        ],
        validators=[DataRequired()],
    )
    active = BooleanField("Vorlage aktiv", default=True)
    submit = SubmitField("Speichern")

    def validate(self, extra_validators=None):
        valid = super().validate(extra_validators=extra_validators)
        if not valid:
            return False
        if self.recurrence_interval_unit.data != "none" and not self.recurrence_interval_value.data:
            self.recurrence_interval_value.errors.append("Bitte gib einen Intervallwert an.")
            return False
        if self.assigned_user_secondary_id.data and self.assigned_user_secondary_id.data == self.assigned_user_id.data:
            self.assigned_user_secondary_id.errors.append("Bitte wähle hier eine andere Person oder keine zweite Person.")
            return False
        return True


class SettingsProfileForm(FlaskForm):
    name = StringField("Name", validators=[DataRequired(), Length(min=2, max=120)])
    email = StringField("E-Mail", validators=[DataRequired(), EMAIL_LIKE, Length(max=255)])
    password = PasswordField("Neues Passwort", validators=[Optional(), Length(min=6, max=128)])
    avatar = FileField(
        "Avatar",
        validators=[Optional(), FileAllowed(["png", "jpg", "jpeg", "gif", "webp", "svg"], "Bitte ein Bild hochladen.")],
    )
    notification_task_due_enabled = BooleanField("Push bei heutigen offenen Aufgaben")
    notification_monthly_winner_enabled = BooleanField("Push zum Monatssieger")
    notification_badge_enabled = BooleanField("Push bei neuen Badges")
    submit = SubmitField("Einstellungen speichern")

    def __init__(self, original_email: str | None = None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.original_email = original_email

    def validate_email(self, field) -> None:
        value = field.data.lower().strip()
        if value == (self.original_email or "").lower().strip():
            return
        if User.query.filter_by(email=value).first():
            raise ValidationError("Diese E-Mail-Adresse wird bereits verwendet.")


class AdminUserForm(FlaskForm):
    name = StringField("Name", validators=[DataRequired(), Length(min=2, max=120)])
    email = StringField("E-Mail", validators=[DataRequired(), EMAIL_LIKE, Length(max=255)])
    password = PasswordField("Passwort", validators=[DataRequired(), Length(min=6, max=128)])
    is_admin = BooleanField("Admin-Rechte")
    submit = SubmitField("Nutzer anlegen")

    def validate_email(self, field) -> None:
        value = field.data.lower().strip()
        if User.query.filter_by(email=value).first():
            raise ValidationError("Diese E-Mail-Adresse wird bereits verwendet.")


class QuickTaskForm(FlaskForm):
    title = StringField("Titel", validators=[Optional(), Length(min=2, max=160)])
    effort = SelectField(
        "Aufwand",
        choices=[(key, key) for key, _, _ in QUICK_TASK_EFFORTS],
        validators=[Optional()],
    )
    submit = SubmitField("Quick-Win speichern")


class QuickTaskConfigForm(FlaskForm):
    fast_label = StringField("Bezeichnung", validators=[DataRequired(), Length(min=2, max=60)])
    fast_points = IntegerField("Schnell", validators=[DataRequired(), NumberRange(min=1, max=500)])
    normal_label = StringField("Bezeichnung", validators=[DataRequired(), Length(min=2, max=60)])
    normal_points = IntegerField("Normal", validators=[DataRequired(), NumberRange(min=1, max=500)])
    medium_label = StringField("Bezeichnung", validators=[DataRequired(), Length(min=2, max=60)])
    medium_points = IntegerField("Dauert etwas", validators=[DataRequired(), NumberRange(min=1, max=500)])
    heavy_label = StringField("Bezeichnung", validators=[DataRequired(), Length(min=2, max=60)])
    heavy_points = IntegerField("Aufwendig", validators=[DataRequired(), NumberRange(min=1, max=500)])
    super_heavy_label = StringField("Bezeichnung", validators=[DataRequired(), Length(min=2, max=60)])
    super_heavy_points = IntegerField("Super aufwendig", validators=[DataRequired(), NumberRange(min=1, max=500)])
    submit = SubmitField("Aufwand speichern")


class QuickWinForm(FlaskForm):
    title = StringField("Quick-Win", validators=[DataRequired(), Length(min=2, max=160)])
    effort = SelectField(
        "Aufwand",
        choices=[(key, key) for key, _, _ in QUICK_TASK_EFFORTS],
        validators=[DataRequired()],
    )
    submit = SubmitField("Quick-Win speichern")
