# backend/forms/auth_forms.py (refactor)
from __future__ import annotations
import re
import unicodedata
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, BooleanField
from wtforms.validators import (
    DataRequired, Length, Email, EqualTo, ValidationError, Regexp
)
from backend.models.user import User

# ─────────────────────────────────────────────────────────────
# 공통 필터/유틸
def strip_filter(x: str | None) -> str | None:
    return x.strip() if isinstance(x, str) else x

def lower_strip(x: str | None) -> str | None:
    return x.strip().lower() if isinstance(x, str) else x

def nfc_korean(x: str | None) -> str | None:
    if not isinstance(x, str):
        return x
    # 한글 이름 등 유니코드 정규화 (NFC)
    return unicodedata.normalize("NFC", x.strip())

# 비밀번호 정책: 8~64자, 대문자/소문자/숫자/특수문자 각 1개 이상
password_policy_validators = [
    Length(min=8, max=64, message="비밀번호는 8~64자여야 합니다."),
    Regexp(r".*[A-Z].*", message="비밀번호에 대문자가 1자 이상 포함되어야 합니다."),
    Regexp(r".*[a-z].*", message="비밀번호에 소문자가 1자 이상 포함되어야 합니다."),
    Regexp(r".*\d.*", message="비밀번호에 숫자가 1자 이상 포함되어야 합니다."),
    Regexp(r".*[^A-Za-z0-9].*", message="비밀번호에 특수문자가 1자 이상 포함되어야 합니다."),
]

# ─────────────────────────────────────────────────────────────

class RegistrationForm(FlaskForm):
    username = StringField(
        "이름",
        filters=[nfc_korean],
        validators=[
            DataRequired(message="이름을 입력해주세요."),
            Length(min=2, max=20, message="이름은 2~20자 사이여야 합니다."),
        ],
        render_kw={
            "placeholder": "이름 (한글만 허용)",
            "autocomplete": "name",
            "autocapitalize": "off",
            "autocorrect": "off",
            "spellcheck": "false",
        },
    )

    email = StringField(
        "이메일",
        filters=[lower_strip],
        validators=[
            DataRequired(message="이메일을 입력해주세요."),
            Email(message="유효한 이메일을 입력하세요."),
        ],
        render_kw={
            "placeholder": "예: user@example.com",
            "autocomplete": "email",
            "inputmode": "email",
        },
    )

    password = PasswordField(
        "비밀번호",
        validators=[DataRequired(message="비밀번호를 입력해주세요."), *password_policy_validators],
        render_kw={"placeholder": "비밀번호", "autocomplete": "new-password"},
    )

    confirm_password = PasswordField(
        "비밀번호 확인",
        validators=[
            DataRequired(message="비밀번호 확인을 입력해주세요."),
            EqualTo("password", message="비밀번호가 일치하지 않습니다."),
        ],
        render_kw={"placeholder": "비밀번호 다시 입력", "autocomplete": "new-password"},
    )

    submit = SubmitField("회원가입")

    def validate_username(self, field):
        # 한글만 허용(2~20자) – 기존 로직 유지
        if not re.fullmatch(r"[가-힣]{2,20}", field.data or ""):
            raise ValidationError("이름은 한글로만 2~20자 입력 가능합니다.")
        # 중복 체크
        user = User.query.filter_by(username=field.data).first()
        if user:
            raise ValidationError("이미 사용 중인 이름입니다.")

    def validate_email(self, field):
        # 이메일은 소문자 비교(필터로 이미 소문자화)
        user = User.query.filter_by(email=field.data).first()
        if user:
            raise ValidationError("이미 등록된 이메일입니다.")


class LoginForm(FlaskForm):
    email = StringField(
        "이메일",
        filters=[lower_strip],
        validators=[DataRequired(message="이메일을 입력해주세요."), Email(message="유효한 이메일을 입력하세요.")],
        render_kw={"placeholder": "이메일 주소", "autocomplete": "username", "inputmode": "email"},
    )

    password = PasswordField(
        "비밀번호",
        validators=[DataRequired(message="비밀번호를 입력해주세요.")],
        render_kw={"placeholder": "비밀번호", "autocomplete": "current-password"},
    )

    remember = BooleanField("로그인 유지")
    submit = SubmitField("로그인")