import uuid
from datetime import date, time
from pydantic import BaseModel


# ── Employee Dashboard ─────────────────────────────────────────────────────────

class EmployeeDashboard(BaseModel):
    today_open: bool
    today_start: time | None
    today_hours_so_far: float | None
    week_hours_worked: float
    week_hours_expected: float
    week_overtime: float
    vacation_remaining_days: int | None
    vacation_used_days: int
    vacation_entitled_days: int
    pending_absences: int
    overtime_balance_hours: float | None  # verfügbares Überstundenguthaben
    schedule_name: str | None             # zugewiesener Arbeitsplan


# ── Team Dashboard ─────────────────────────────────────────────────────────────

class TeamMemberStatus(BaseModel):
    user_id: uuid.UUID
    user_name: str
    department: str | None
    status: str  # "present" | "on_leave" | "absent"
    absence_type: str | None
    time_in: time | None
    hours_today: float | None


class TeamDashboard(BaseModel):
    present_count: int
    on_leave_count: int
    absent_count: int
    pending_time_approvals: int
    pending_absence_approvals: int
    members: list[TeamMemberStatus]


# ── Company Dashboard ──────────────────────────────────────────────────────────

class UpcomingAbsence(BaseModel):
    user_id: uuid.UUID
    user_name: str
    absence_type: str
    start_date: date
    end_date: date
    working_days: float


class CompanyDashboard(BaseModel):
    total_employees: int
    active_today: int
    attendance_rate: float
    month_hours_worked: float
    month_hours_expected: float
    month_overtime: float
    pending_time_approvals: int
    pending_absence_approvals: int
    upcoming_absences: list[UpcomingAbsence]


# ── Time Report ────────────────────────────────────────────────────────────────

class HoursBreakdown(BaseModel):
    """Stunden-Aufteilung nach §3b EStG für den Steuerberater."""
    normal_hours: float        # Mo–Fr, 06–20 Uhr, kein Feiertag
    night_25_hours: float      # 20–24 + 04–06 Uhr (25% Zuschlag)
    night_40_hours: float      # 00–04 Uhr (40% Zuschlag)
    sunday_hours: float        # Sonntag 00–24 Uhr (50% Zuschlag)
    holiday_125_hours: float   # gesetzl. Feiertag (125% Zuschlag)
    holiday_150_hours: float   # besondere Feiertage 25.12, 26.12, 01.05 etc. (150%)
    holiday_name: str | None   # Name des Feiertags falls zutreffend


class TimeReportRow(BaseModel):
    date: date
    user_id: uuid.UUID
    user_name: str
    personnel_number: str | None = None
    department: str | None
    start_time: time
    end_time: time | None
    break_minutes: int
    worked_hours: float | None
    status: str
    source: str
    note: str | None
    breakdown: HoursBreakdown | None = None  # None wenn kein Bundesland konfiguriert


class TimeReport(BaseModel):
    date_from: date
    date_to: date
    total_rows: int
    total_hours: float
    rows: list[TimeReportRow]


# ── Absence Report ─────────────────────────────────────────────────────────────

class AbsenceReportRow(BaseModel):
    user_id: uuid.UUID
    user_name: str
    personnel_number: str | None = None
    department: str | None
    absence_type: str
    start_date: date
    end_date: date
    working_days: float
    status: str
    note: str | None


class AbsenceReport(BaseModel):
    date_from: date
    date_to: date
    total_rows: int
    total_days: float
    rows: list[AbsenceReportRow]


# ── Overtime Report ────────────────────────────────────────────────────────────

class OvertimeReportRow(BaseModel):
    user_id: uuid.UUID
    user_name: str
    personnel_number: str | None = None
    department: str | None
    hours_worked: float
    hours_expected: float
    overtime_hours: float


class OvertimeReport(BaseModel):
    date_from: date
    date_to: date
    total_employees: int
    total_overtime: float
    rows: list[OvertimeReportRow]


# ── Overtime Detail Report (Option A: Inline-Expand) ──────────────────────────

class DayEntry(BaseModel):
    """Einzelner Zeiteintrag innerhalb eines Tages (mehrere möglich)."""
    start_time: time
    end_time: time
    break_minutes: int
    hours_worked: float
    status: str
    arbzg_warnings: list[str] = []
    breakdown: HoursBreakdown | None = None


class OvertimeDay(BaseModel):
    date: date
    weekday: str           # "Mo", "Di", …
    hours_worked: float    # Summe aller Einträge des Tages
    hours_expected: float
    overtime: float
    entries: list[DayEntry] = []   # leer = kein Eintrag an dem Tag


class OvertimeWeek(BaseModel):
    week_nr: int
    week_start: date
    week_end: date
    hours_worked: float
    hours_expected: float
    overtime: float
    days: list[OvertimeDay]


class OvertimeReportRowDetailed(OvertimeReportRow):
    weeks: list[OvertimeWeek] = []
    arbzg_violation_days: int = 0   # Tage > 10h
    special_hours_total: HoursBreakdown | None = None


class OvertimeReportDetailed(BaseModel):
    date_from: date
    date_to: date
    total_employees: int
    total_overtime: float
    rows: list[OvertimeReportRowDetailed]


# ── DATEV-Monatsblatt ──────────────────────────────────────────────────────────
# Layout entspricht "Stundenaufzeichnungen Muster blanko DATEV ab 2015":
# ein Blatt pro Mitarbeiter/Monat, Zeile pro Kalendertag.

class DatevDayRow(BaseModel):
    day: int                              # Kalendertag 1-31
    weekday_label: str                    # "Mo".."So" für Anzeige
    start_time: time | None = None
    break_minutes: int | None = None
    end_time: time | None = None
    duration_hours: float | None = None
    code: str | None = None               # K/U/UU/F/SA/SU – siehe DATEV_CODES
    recorded_on: date | None = None       # "aufgezeichnet am" (created_at des Eintrags)
    note: str | None = None               # Bemerkungen (Absence-Typ-Name o.ä.)


class DatevMonthlySheet(BaseModel):
    company_name: str
    user_name: str
    personnel_number: str | None
    year: int
    month: int
    rows: list[DatevDayRow]
    total_hours: float
