import uuid
from datetime import datetime
from typing import Literal

from pydantic import BaseModel, ConfigDict, Field


PersonnelNumberModeT = Literal["manual", "auto"]


class CompanySettingsUpdate(BaseModel):
    """Validiertes Sub-Schema für das company.settings JSONB-Feld.

    Nur bekannte Top-Level-Keys sind erlaubt (extra="forbid").
    Derzeit genutzte Keys: carryover_expires_month, carryover_expires_day
    (gelesen in absences.py für Resturlaub-Verfall-Berechnung), retention_lohn_years
    (gelesen in retention_service.py für Aufbewahrungsfrist Zeiterfassung/Auszahlungen).
    """
    model_config = ConfigDict(extra="forbid")

    carryover_expires_month: int | None = Field(None, ge=1, le=12)
    carryover_expires_day: int | None = Field(None, ge=1, le=31)
    retention_lohn_years: int | None = Field(None, ge=1, le=30)


class CompanyOut(BaseModel):
    model_config = {"from_attributes": True}

    id: uuid.UUID
    name: str
    slug: str
    plan: str
    logo_url: str | None
    country: str
    state: str | None
    settings: dict
    personnel_number_required: bool = False
    personnel_number_mode: PersonnelNumberModeT = "manual"
    personnel_number_next: int = 1
    mobile_stamping_enabled: bool = True
    overtime_overdraft_allowed: bool = True
    overtime_warning_threshold_hours: int = 0
    overtime_cap_hours: int | None = None
    overtime_expiry_enabled: bool = False
    overtime_expiry_month: int = 3
    overtime_expiry_day: int = 31
    overtime_max_carryover_hours: int | None = None
    payout_request_enabled: bool = False
    kiosk_require_approval: bool = True
    kiosk_track_current_user: bool = True
    kiosk_heartbeat_interval_sec: int = 30
    public_stamp_enabled: bool = False
    vacation_default_days: int = 30
    vacation_prorate_first_year: bool = True
    vacation_from_schedule: bool = False
    two_stage_approval_enabled: bool = False
    two_stage_min_days: int = 0


class PublicStampTokenStatus(BaseModel):
    """Status des öffentlichen QR-Stempel-Tokens (kein Klartext)."""
    enabled: bool
    configured: bool
    created_at: datetime | None = None


class PublicStampTokenRotated(BaseModel):
    """Antwort beim Rotieren – enthält Klartext-Token + fertige URL (nur einmalig)."""
    token: str = Field(..., description="Klartext-Token, wird nur einmal angezeigt.")
    public_url: str
    created_at: datetime


class CompanyUpdate(BaseModel):
    name: str | None = Field(None, min_length=2, max_length=255)
    state: str | None = Field(None, max_length=10)
    settings: CompanySettingsUpdate | None = None
    personnel_number_required: bool | None = None
    personnel_number_mode: PersonnelNumberModeT | None = None
    personnel_number_next: int | None = Field(None, ge=1)
    mobile_stamping_enabled: bool | None = None
    overtime_overdraft_allowed: bool | None = None
    overtime_warning_threshold_hours: int | None = Field(None, ge=0)
    overtime_cap_hours: int | None = Field(None, ge=1, le=9999)
    overtime_expiry_enabled: bool | None = None
    overtime_expiry_month: int | None = Field(None, ge=1, le=12)
    overtime_expiry_day: int | None = Field(None, ge=1, le=31)
    overtime_max_carryover_hours: int | None = Field(None, ge=0, le=9999)
    payout_request_enabled: bool | None = None
    kiosk_require_approval: bool | None = None
    kiosk_track_current_user: bool | None = None
    kiosk_heartbeat_interval_sec: int | None = Field(None, ge=10, le=120)
    public_stamp_enabled: bool | None = None
    vacation_default_days: int | None = Field(None, ge=0, le=365)
    vacation_prorate_first_year: bool | None = None
    vacation_from_schedule: bool | None = None
    two_stage_approval_enabled: bool | None = None
    two_stage_min_days: int | None = Field(None, ge=0, le=365)


class DepartmentOut(BaseModel):
    model_config = {"from_attributes": True}

    id: uuid.UUID
    company_id: uuid.UUID
    name: str
    manager_id: uuid.UUID | None


class DepartmentCreate(BaseModel):
    name: str = Field(min_length=1, max_length=255)
    manager_id: uuid.UUID | None = None


class DepartmentUpdate(BaseModel):
    name: str | None = Field(None, min_length=1, max_length=255)
    manager_id: uuid.UUID | None = None
