# FILE: src/apps/sales/models/contract.py
from __future__ import annotations

from datetime import datetime
from decimal import Decimal
from typing import TYPE_CHECKING, Any, Dict, List, Optional
from uuid import UUID

from sqlalchemy import ForeignKey, Numeric, String, Text, UniqueConstraint
from sqlalchemy import DateTime
from sqlalchemy.dialects.postgresql import JSONB, UUID as PG_UUID
from sqlalchemy.orm import Mapped, mapped_column, relationship

from src.database.base import TenantSoftDeleteModel

if TYPE_CHECKING:
    from src.apps.sales.models.contract_line_item import ContractLineItem
    from src.apps.billing.models.invoice import Invoice


class Contract(TenantSoftDeleteModel):
    __tablename__ = "contracts"

    __table_args__ = (
        UniqueConstraint("tenant_id", "contract_number", name="uq_contracts_tenant_number"),
    )

    # Override tenant_id with explicit FK
    tenant_id: Mapped[UUID] = mapped_column(
        PG_UUID(as_uuid=True),
        ForeignKey("accounts.id", ondelete="CASCADE"),
        nullable=False,
        index=True,
    )

    opportunity_id: Mapped[Optional[UUID]] = mapped_column(
        PG_UUID(as_uuid=True),
        ForeignKey("opportunities.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
    )
    purchaser_id: Mapped[Optional[UUID]] = mapped_column(
        PG_UUID(as_uuid=True),
        ForeignKey("family_contacts.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
    )
    plot_id: Mapped[Optional[UUID]] = mapped_column(
        PG_UUID(as_uuid=True),
        ForeignKey("plots.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
    )
    section_id: Mapped[Optional[UUID]] = mapped_column(
        PG_UUID(as_uuid=True),
        ForeignKey("sections.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
    )
    created_by: Mapped[Optional[UUID]] = mapped_column(
        PG_UUID(as_uuid=True),
        ForeignKey("users.id", ondelete="SET NULL"),
        nullable=True,
        index=True,
    )

    contract_number: Mapped[str] = mapped_column(String(50), nullable=False)
    contract_type: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
    status: Mapped[str] = mapped_column(String(50), nullable=False, default="draft", index=True)
    total_amount: Mapped[Decimal] = mapped_column(
        Numeric(12, 2), nullable=False, default=Decimal("0"), server_default="0"
    )
    purchaser_name: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
    purchaser_email: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
    purchaser_phone: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
    purchaser_address: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    purchaser_signature_b64: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    witness_name: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
    signed_at: Mapped[Optional[datetime]] = mapped_column(
        DateTime(timezone=True), nullable=True
    )
    pdf_s3_key: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    payment_plan_type: Mapped[Optional[str]] = mapped_column(
        String(50), nullable=True, server_default="'full'"
    )
    deposit_amount: Mapped[Optional[Decimal]] = mapped_column(
        Numeric(10, 2), nullable=True
    )
    payment_schedule: Mapped[Optional[Dict[str, Any]]] = mapped_column(
        JSONB, nullable=True
    )

    # Relationships
    line_items: Mapped[List["ContractLineItem"]] = relationship(
        "ContractLineItem", back_populates="contract"
    )
    invoices: Mapped[List["Invoice"]] = relationship(
        "Invoice", back_populates="contract"
    )
