"""
Pydantic schemas for Phase 1.3.1 auth endpoints (signup, me, logout).
All schemas inherit from CamelCaseModel for automatic snake_case <-> camelCase translation.

Validation rules:
- email: valid email format (EmailStr)
- password: 8-72 chars (72 = bcrypt limit used by Supabase)
- firstname/lastname: 1-50 chars, whitespace stripped
- phone: Moroccan mobile, 3 accepted formats — +2126XXXXXXXX / +21206XXXXXXXX
  (E.164 with the leading 0 kept) / 06XXXXXXXX (local, no country code) —
  mirrors src/utils/phoneValidation.ts on the frontend
- profession: 2-80 chars
- city: 2-50 chars (enum validation delegated to frontend via cities.ts)
"""
from typing import Optional

from pydantic import EmailStr, Field

from app.schemas.base import CamelCaseModel


# Moroccan mobile phone — 3 accepted formats (mirrors phoneValidation.ts):
#   +212[67]XXXXXXXX   (E.164, no leading 0 after the country code)
#   +2120[67]XXXXXXXX  (E.164 with the leading 0 kept after +212)
#   0[67]XXXXXXXX      (local, no country code)
PHONE_REGEX = r"^(\+212[67]\d{8}|\+2120[67]\d{8}|0[67]\d{8})$"


# ----------------------------------------------------------------------------
# POST /auth/signup
# ----------------------------------------------------------------------------

class SignupRequest(CamelCaseModel):
    """
    Payload received from the frontend for classic email/password signup.
    All 7 fields are required and validated.
    """
    email: EmailStr
    password: str = Field(min_length=8, max_length=72)
    firstname: str = Field(min_length=1, max_length=50)
    lastname: str = Field(min_length=1, max_length=50)
    phone: str = Field(pattern=PHONE_REGEX)
    profession: str = Field(min_length=2, max_length=80)
    city: str = Field(min_length=2, max_length=50)


class SignupResponse(CamelCaseModel):
    """
    Response after a successful signup.
    No JWT issued yet — user must confirm email first (Scenario A, Strategy 1).
    """
    user_id: str
    email: EmailStr
    email_sent: bool


# ----------------------------------------------------------------------------
# GET /auth/me
# ----------------------------------------------------------------------------

class MeResponse(CamelCaseModel):
    """
    Current authenticated user info, returned by GET /auth/me.
    Combines auth.users (email) + public.profiles (firstname, lastname, phone, profession, city, role).
    Nullable fields (phone, profession, city) reflect users who signed up via Google OAuth
    and haven't completed CompleteProfile yet.
    """
    user_id: str
    email: EmailStr
    role: str  # 'candidate' or 'admin'
    firstname: str
    lastname: str
    phone: Optional[str] = None
    profession: Optional[str] = None
    city: Optional[str] = None


# ----------------------------------------------------------------------------
# POST /auth/login
# ----------------------------------------------------------------------------

class LoginRequest(CamelCaseModel):
    """
    Login payload: email + password.
    No password validation here (we don't leak password format hints to attackers).
    Supabase validates server-side and returns generic 401 on bad credentials.
    """
    email: EmailStr
    password: str


class LoginResponse(CamelCaseModel):
    """
    Successful login response: tokens + user info in a single payload.
    The frontend stores accessToken + refreshToken in Keychain, and uses user
    data to render the home screen without a second round-trip.
    """
    access_token: str
    refresh_token: str
    expires_in: int   # seconds until access_token expires (~3600 default Supabase)
    token_type: str   # always "bearer"
    user: MeResponse  # reuses existing schema for consistency with GET /auth/me


# ----------------------------------------------------------------------------
# POST /auth/refresh
# ----------------------------------------------------------------------------

class RefreshRequest(CamelCaseModel):
    """
    Refresh payload: just the refreshToken.
    Used by the frontend when an accessToken expires.
    """
    refresh_token: str


class RefreshResponse(CamelCaseModel):
    """
    Refresh response: new access + refresh tokens.
    Supabase rotates the refreshToken on every refresh call (the old one is invalidated).
    No user info needed since the user identity hasn't changed.
    """
    access_token: str
    refresh_token: str
    expires_in: int
    token_type: str


# ----------------------------------------------------------------------------
# POST /auth/confirm
# ----------------------------------------------------------------------------

class ConfirmRequest(CamelCaseModel):
    """
    Payload for email confirmation via token_hash extracted from email deep link.
    The frontend extracts token_hash and type from talk2cv://confirm?token_hash=XXX&type=signup
    and POSTs them here.
    """
    token_hash: str
    type: str = "signup"  # 'signup' or 'email_change'


class ConfirmResponse(CamelCaseModel):
    """
    Successful confirmation auto-logs the user in (same structure as LoginResponse).
    Eliminates the friction of asking the user to re-type credentials right after
    clicking the confirmation link.
    """
    access_token: str
    refresh_token: str
    expires_in: int
    token_type: str
    user: MeResponse


# ----------------------------------------------------------------------------
# POST /auth/resend-confirmation
# ----------------------------------------------------------------------------

class ResendConfirmationRequest(CamelCaseModel):
    """Payload to request a new confirmation email."""
    email: EmailStr


class ResendConfirmationResponse(CamelCaseModel):
    """
    Always returns emailSent=true to prevent email enumeration attacks.
    If the email doesn't exist or is already confirmed, Supabase silently skips
    the send, but the API response remains identical.
    """
    email_sent: bool


# ----------------------------------------------------------------------------
# POST /auth/forgot-password
# ----------------------------------------------------------------------------

class ForgotPasswordRequest(CamelCaseModel):
    """Payload to request a password reset email."""
    email: EmailStr


class ForgotPasswordResponse(CamelCaseModel):
    """
    Response to a forgot-password request.

    Behavior matrix:
    - email/password user      -> {"emailSent": true}                  (reset email sent)
    - google OAuth user        -> {"emailSent": false, "code": "GOOGLE_USER"}
    - non-existent email       -> {"emailSent": true}                  (anti-enumeration silent)

    The `code` field is only present for the GOOGLE_USER case (frontend can render
    a hint "use Google sign-in"). All other cases return identical JSON to prevent
    enumeration of non-existent vs registered emails.
    """
    email_sent: bool
    code: str | None = None


# ----------------------------------------------------------------------------
# POST /auth/reset-password
# ----------------------------------------------------------------------------

class ResetPasswordRequest(CamelCaseModel):
    """
    Payload for the reset-password endpoint.
    tokenHash is extracted by the frontend from the deep link talk2cv://reset-password?token_hash=XXX
    """
    token_hash: str
    new_password: str = Field(min_length=8, max_length=72)


class ResetPasswordResponse(CamelCaseModel):
    """
    Auto-login response after a successful password reset.
    Same structure as LoginResponse: tokens + user data in a single payload,
    so the app can navigate to home screen without asking the user to re-login.
    """
    access_token: str
    refresh_token: str
    expires_in: int
    token_type: str
    user: MeResponse


# ----------------------------------------------------------------------------
# POST /auth/google
# ----------------------------------------------------------------------------

class GoogleSignInRequest(CamelCaseModel):
    """
    Payload for Google OAuth sign-in.

    The frontend uses the native Google Sign-In SDK to obtain an idToken (JWT signed
    by Google). It then POSTs this idToken to our backend. The backend delegates token
    validation to Supabase via auth.sign_in_with_id_token().

    On first sign-in, a row in public.profiles is created with firstname/lastname from
    Google (phone/profession/city remain NULL until the user completes CompleteProfileScreen).
    """
    id_token: str


class GoogleSignInResponse(CamelCaseModel):
    """
    Auto-login response after a successful Google sign-in.
    Same structure as LoginResponse: tokens + user data in a single payload.

    For first-time Google users, the response will have:
    - phone: None
    - profession: None
    - city: None
    The frontend detects these nulls and routes to CompleteProfileScreen.
    """
    access_token: str
    refresh_token: str
    expires_in: int
    token_type: str
    user: MeResponse


# ----------------------------------------------------------------------------
# PATCH /auth/change-password
# ----------------------------------------------------------------------------

class ChangePasswordRequest(CamelCaseModel):
    """
    Payload for changing the password of an already-authenticated user.
    current_password is re-verified via sign_in_with_password before the update.
    """
    current_password: str = Field(min_length=1)
    new_password: str = Field(min_length=8, max_length=72)


class ChangePasswordResponse(CamelCaseModel):
    """Response after a successful password change."""
    success: bool
