"""
PRD-HWONB-007 §1 — merchant_onboarding_owners

Field list, enum values, and the "exactly 1 individualWithControl" / role-cap
rules are pulled from PRD-HWONB-007 §1/§2. Cap enforcement itself (<=5 owners,
<=2 app_signer, <=2 personal_guarantor, <=4 beneficial_owner, exactly 1
individual_with_control) is the Developer's crud.py job — this schema
deliberately has no UniqueConstraint/CheckConstraint that would make those
counts impossible to enforce in application code.
"""
from typing import Optional, TYPE_CHECKING
from sqlalchemy import String, Boolean, Integer, Date, DateTime, JSON, ForeignKey, Text
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.sql import func
from src.apps.base.models.base import Base
from datetime import datetime, date

if TYPE_CHECKING:
    from src.apps.merchant_onboarding.models.application import MerchantOnboardingApplication


class MerchantOnboardingOwner(Base):
    __tablename__ = "merchant_onboarding_owners"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True, autoincrement=True)
    application_id: Mapped[int] = mapped_column(
        Integer, ForeignKey("merchant_onboarding_applications.id"), nullable=False, index=True
    )

    # --- Identity (always required, PRD-007 §1) ---
    first_name: Mapped[str] = mapped_column(String(11), nullable=False)
    last_name: Mapped[str] = mapped_column(String(15), nullable=False)
    contact_title: Mapped[str] = mapped_column(String(10), nullable=False)  # owners-specific enum, distinct from Addresses'
    phone_country_code: Mapped[str] = mapped_column(String(5), nullable=False)
    phone_number: Mapped[str] = mapped_column(String(20), nullable=False)
    email: Mapped[str] = mapped_column(String(255), nullable=False)
    dob: Mapped[date] = mapped_column(Date, nullable=False)

    # ownerPercent: must total 100 across all owners on the application (enforced in crud.py)
    owner_percent: Mapped[int] = mapped_column(Integer, nullable=False)

    non_us_citizen: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)

    # --- US-citizen branch (nonUsCitizen = false) ---
    # Fernet-encrypted (src/apps/payment_providers/helpers/credentials.py). Nullable/optional
    # only when ownershipType in {FI, GE, CPUB} per PRD-007 §1/§2.4 (create-table set).
    ssn_enc: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    credit_pull_waive: Mapped[Optional[bool]] = mapped_column(Boolean, nullable=True, default=False)
    street_number: Mapped[Optional[str]] = mapped_column(String(6), nullable=True)
    street_name: Mapped[Optional[str]] = mapped_column(String(19), nullable=True)
    street_direction: Mapped[Optional[str]] = mapped_column(String(2), nullable=True)  # N,S,E,W,NE,NW,SE,SW
    street_type: Mapped[Optional[str]] = mapped_column(String(10), nullable=True)  # ~130-value USPS suffix enum
    unit_number: Mapped[Optional[str]] = mapped_column(String(5), nullable=True)
    city: Mapped[Optional[str]] = mapped_column(String(16), nullable=True)
    state: Mapped[Optional[str]] = mapped_column(String(2), nullable=True)  # US 2-char + territories
    zip_code: Mapped[Optional[str]] = mapped_column(String(9), nullable=True)
    country: Mapped[Optional[str]] = mapped_column(String(3), nullable=True)  # ISO-3

    # --- Non-US-citizen branch (nonUsCitizen = true) ---
    passport_country: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
    passport_number: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
    address_line1: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)  # renamed from foreignAddressLine1
    address_line2: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
    foreign_city: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
    foreign_state: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
    foreign_zip_code: Mapped[Optional[str]] = mapped_column(String(20), nullable=True)
    foreign_country: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)

    # --- Role flags (all 4 always sent to GP; caps enforced in crud.py, not here) ---
    app_signer: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)  # max 2
    personal_guarantor: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)  # max 2
    beneficial_owner: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)  # max 4
    individual_with_control: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)  # exactly 1

    # --- GP sync bookkeeping ---
    tsys_owner_ref: Mapped[Optional[str]] = mapped_column(String(100), nullable=True)
    tsys_synced_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True)
    tsys_errors: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True)

    created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), nullable=False)
    updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True, onupdate=func.now())
    deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime(timezone=True), nullable=True)

    application: Mapped["MerchantOnboardingApplication"] = relationship(
        "MerchantOnboardingApplication", back_populates="owners"
    )
