from sqlalchemy import Integer, String, DateTime, Boolean, Column, ForeignKey
from sqlalchemy.sql import func
from sqlalchemy.orm import relationship, Mapped, mapped_column
from sqlalchemy.sql.schema import Table
from typing import Optional, List, TYPE_CHECKING
from datetime import datetime
from src.apps.base.models.base import Base
from sqlalchemy.ext.hybrid import hybrid_property

if TYPE_CHECKING:
    from typing import Any

customer_contact_address_map = Table(
    "contact_addresses",
    Base.metadata,
    Column("contact_id", ForeignKey("customer_contacts.id")),
    Column("address_id", ForeignKey("address.id")),
)


class CustomerContact(Base):
    """
    Customer Contacts Model: ORM class for Customer Contacts Entity
    """

    __tablename__ = "customer_contacts"

    id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True, autoincrement=True)
    contact_id: Mapped[str] = mapped_column(String(50), index=True, unique=True)
    first_name: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
    last_name: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
    designation: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)  # Keep for backward compatibility
    title: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
    dob: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    email: Mapped[str] = mapped_column(String(255))
    phone: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
    account_phone: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
    office_phone: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
    relation: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
    is_active: Mapped[bool] = mapped_column(Boolean, default=False)
    tilled_id: Mapped[Optional[str]] = mapped_column(String(50), nullable=True)
    created_at: Mapped[datetime] = mapped_column(DateTime, server_default=func.now())
    updated_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True, onupdate=func.now())
    deleted_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
    account_website: Mapped[Optional[str]] = mapped_column(String(255), nullable=True)
    timezone: Mapped[Optional[str]] = mapped_column(String(32), nullable=True)

    avatar_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("files.id"), nullable=True)
    avatar: Mapped[Optional["File"]] = relationship("File", lazy="joined")

    customer_id: Mapped[int] = mapped_column(Integer, ForeignKey("customers.id"))
    customer: Mapped["Customer"] = relationship("Customer")

    payment_methods: Mapped[List["PaymentMethod"]] = relationship("PaymentMethod", back_populates="payer")

    user_account_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("users.id"), nullable=True)
    user_account: Mapped[Optional["User"]] = relationship("User")

    payment_request_authorizations: Mapped[List["PaymentRequestAuthorizations"]] = relationship(
        "PaymentRequestAuthorizations", back_populates="payer"
    )

    addresses: Mapped[List["Address"]] = relationship("Address", secondary=customer_contact_address_map)
