import uuid
from datetime import datetime, timezone
from sqlalchemy import String, Integer, Boolean, DateTime, ForeignKey
from typing import List, Optional
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.core.database import Base


class PayrollRun(Base):
    __tablename__ = "payroll_runs"

    id: Mapped[str] = mapped_column(
        String, primary_key=True, default=lambda: str(uuid.uuid4())
    )
    run_date: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False
    )
    month: Mapped[int] = mapped_column(Integer, nullable=False)
    year: Mapped[int] = mapped_column(Integer, nullable=False)
    export_type: Mapped[str] = mapped_column(String, nullable=False)  # "regular" | "thr"
    company_id: Mapped[Optional[str]] = mapped_column(
        String, ForeignKey("companies.id", ondelete="SET NULL"), nullable=True
    )
    company_name: Mapped[Optional[str]] = mapped_column(String, nullable=True)
    total_amount: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    employee_count: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    recorded_transactions: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
    )

    items: Mapped[List["PayrollRunItem"]] = relationship(
        "PayrollRunItem", back_populates="run", cascade="all, delete-orphan"
    )
    company: Mapped["Company"] = relationship("Company")  # type: ignore[name-defined]


class PayrollRunItem(Base):
    __tablename__ = "payroll_run_items"

    id: Mapped[str] = mapped_column(
        String, primary_key=True, default=lambda: str(uuid.uuid4())
    )
    run_id: Mapped[str] = mapped_column(
        String, ForeignKey("payroll_runs.id", ondelete="CASCADE"), nullable=False
    )
    employee_id: Mapped[Optional[str]] = mapped_column(
        String, ForeignKey("employees.id", ondelete="SET NULL"), nullable=True
    )
    employee_name: Mapped[str] = mapped_column(String, nullable=False)
    account_name: Mapped[Optional[str]] = mapped_column(String, nullable=True)
    account_number: Mapped[Optional[str]] = mapped_column(String, nullable=True)
    base_salary: Mapped[int] = mapped_column(Integer, nullable=False)
    benefit: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    loan_deduction: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    cash_advance: Mapped[int] = mapped_column(Integer, default=0, nullable=False)
    net_amount: Mapped[int] = mapped_column(Integer, nullable=False)
    has_override: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    created_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
    )

    run: Mapped[PayrollRun] = relationship("PayrollRun", back_populates="items")
    employee: Mapped["Employee"] = relationship("Employee")  # type: ignore[name-defined]
