from datetime import date
from decimal import Decimal
from uuid import UUID

from pydantic import BaseModel, Field, model_validator

from app.models.special_assignment import AssignmentMode


class SpecialAssignmentCreate(BaseModel):
    date_from: date
    date_to: date
    factor: Decimal = Field(gt=0, le=10, decimal_places=3)
    mode: AssignmentMode = AssignmentMode.both
    description: str | None = None
    label: str | None = Field(None, max_length=100)

    @model_validator(mode="after")
    def dates_valid(self) -> "SpecialAssignmentCreate":
        if self.date_from > self.date_to:
            raise ValueError("date_from darf nicht nach date_to liegen")
        return self


class SpecialAssignmentUpdate(BaseModel):
    date_from: date | None = None
    date_to: date | None = None
    factor: Decimal | None = Field(None, gt=0, le=10)
    mode: AssignmentMode | None = None
    description: str | None = None
    label: str | None = Field(None, max_length=100)


class SpecialAssignmentOut(BaseModel):
    id: UUID
    user_id: UUID
    company_id: UUID
    date_from: date
    date_to: date
    factor: Decimal
    mode: AssignmentMode
    description: str | None = None
    label: str | None = None

    model_config = {"from_attributes": True}


# ── Payroll-Report-Schemas ────────────────────────────────────────────────────

class PayrollAssignmentEntry(BaseModel):
    """Einzelner Zeitraum mit Faktor für den Payroll-Report."""
    assignment_id: UUID
    label: str | None
    date_from: date
    date_to: date
    factor: Decimal
    normal_hours: float   # Stunden ohne Faktor
    factor_hours: float   # Stunden * Faktor (effektiv für Abrechnung)
    extra_hours: float    # factor_hours - normal_hours (Mehrwert)


class PayrollAssignmentRow(BaseModel):
    """Zusammenfassung pro Mitarbeiter."""
    user_id: UUID
    user_name: str
    personnel_number: str | None
    assignments: list[PayrollAssignmentEntry]
    total_normal_hours: float
    total_factor_hours: float
    total_extra_hours: float


class PayrollAssignmentReport(BaseModel):
    year: int
    month: int
    rows: list[PayrollAssignmentRow]
