from datetime import date
from decimal import Decimal

from sqlalchemy import Date, ForeignKey, Integer, Numeric, String, Text
from sqlalchemy.orm import Mapped, mapped_column, relationship

from app.db.base import Base, SoftDeleteMixin, TimestampMixin
from app.db.types import str_enum
from app.models.enums import PaymentStatus, PolicyCoverageType, PolicyStatus


class Policy(Base, TimestampMixin, SoftDeleteMixin):
    __tablename__ = "policies"

    id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
    agency_id: Mapped[int] = mapped_column(ForeignKey("agencies.id"), nullable=False, index=True)
    customer_id: Mapped[int] = mapped_column(ForeignKey("customers.id"), nullable=False, index=True)
    vehicle_id: Mapped[int | None] = mapped_column(ForeignKey("vehicles.id"), index=True)
    insurance_company_id: Mapped[int | None] = mapped_column(ForeignKey("insurance_companies.id"), index=True)
    renewed_from_policy_id: Mapped[int | None] = mapped_column(ForeignKey("policies.id"))

    policy_number: Mapped[str | None] = mapped_column(String(100), index=True)
    policy_type: Mapped[str | None] = mapped_column(String(100))
    coverage_type: Mapped[PolicyCoverageType | None] = mapped_column(str_enum(PolicyCoverageType))
    policy_start_date: Mapped[date | None] = mapped_column(Date)
    policy_end_date: Mapped[date | None] = mapped_column(Date, index=True)
    premium_amount: Mapped[Decimal | None] = mapped_column(Numeric(12, 2))
    idv: Mapped[Decimal | None] = mapped_column(Numeric(12, 2))
    ncb: Mapped[str | None] = mapped_column(String(50))
    status: Mapped[PolicyStatus] = mapped_column(str_enum(PolicyStatus), default=PolicyStatus.DRAFT, index=True)

    total_commission: Mapped[Decimal] = mapped_column(Numeric(12, 2), default=Decimal("0.00"), nullable=False)
    total_paid: Mapped[Decimal] = mapped_column(Numeric(12, 2), default=Decimal("0.00"), nullable=False)
    pending_amount: Mapped[Decimal] = mapped_column(Numeric(12, 2), default=Decimal("0.00"), nullable=False)
    payment_status: Mapped[PaymentStatus] = mapped_column(
        str_enum(PaymentStatus), default=PaymentStatus.PENDING, nullable=False
    )

    notes: Mapped[str | None] = mapped_column(Text)
    created_by: Mapped[int | None] = mapped_column(ForeignKey("users.id"), index=True)

    agency: Mapped["Agency"] = relationship(back_populates="policies")
    customer: Mapped["Customer"] = relationship(back_populates="policies")
    vehicle: Mapped["Vehicle | None"] = relationship(back_populates="policies")
    insurance_company: Mapped["InsuranceCompany | None"] = relationship(back_populates="policies")
    renewed_from: Mapped["Policy | None"] = relationship(remote_side="Policy.id")
    documents: Mapped[list["PolicyDocument"]] = relationship(back_populates="policy")
    payments: Mapped[list["PolicyPayment"]] = relationship(back_populates="policy")
    extraction_results: Mapped[list["ExtractionResult"]] = relationship(back_populates="policy")
    whatsapp_logs: Mapped[list["WhatsAppLog"]] = relationship(back_populates="policy")
    reminder_logs: Mapped[list["ReminderLog"]] = relationship(back_populates="policy")


from app.models.agency import Agency  # noqa: E402
from app.models.customer import Customer  # noqa: E402
from app.models.extraction_result import ExtractionResult  # noqa: E402
from app.models.insurance_company import InsuranceCompany  # noqa: E402
from app.models.policy_document import PolicyDocument  # noqa: E402
from app.models.policy_payment import PolicyPayment  # noqa: E402
from app.models.reminder_log import ReminderLog  # noqa: E402
from app.models.user import User  # noqa: E402
from app.models.vehicle import Vehicle  # noqa: E402
from app.models.whatsapp_log import WhatsAppLog  # noqa: E402
