"""Clinic management aggregates — Phase 13.3."""
from __future__ import annotations

import uuid

from sqlalchemy import Boolean, Index, Integer, String, Text, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy.types import JSON

from app.core.database import Base
from app.models.base import (
    ActorAuditMixin,
    OptimisticLockMixin,
    SoftDeleteMixin,
    TenantMixin,
    TimestampMixin,
    UUIDPrimaryKeyMixin,
)
from app.models.types import ClinicPolicyKind, GUID, LifecycleStatus


class ClinicService(
    Base,
    UUIDPrimaryKeyMixin,
    TenantMixin,
    TimestampMixin,
    SoftDeleteMixin,
    ActorAuditMixin,
    OptimisticLockMixin,
):
    __tablename__ = "clinic_services"

    clinic_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    department_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    code: Mapped[str] = mapped_column(String(50), nullable=False)
    name: Mapped[str] = mapped_column(String(255), nullable=False)
    description: Mapped[str | None] = mapped_column(Text, nullable=True)
    duration_minutes: Mapped[int] = mapped_column(Integer, default=30, nullable=False)
    pricing_ref: Mapped[str | None] = mapped_column(String(100), nullable=True)
    status: Mapped[LifecycleStatus] = mapped_column(
        default=LifecycleStatus.ACTIVE, nullable=False
    )
    metadata_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)

    __table_args__ = (
        UniqueConstraint("tenant_id", "code", name="uq_clinic_services_tenant_code"),
        Index("ix_clinic_services_clinic", "tenant_id", "clinic_id"),
    )


class StaffAssignment(
    Base,
    UUIDPrimaryKeyMixin,
    TenantMixin,
    TimestampMixin,
    SoftDeleteMixin,
    ActorAuditMixin,
):
    __tablename__ = "staff_assignments"

    clinic_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    department_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    doctor_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    code: Mapped[str] = mapped_column(String(50), nullable=False)
    role_code: Mapped[str] = mapped_column(String(50), nullable=False)
    is_primary: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False)
    metadata_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)

    __table_args__ = (
        UniqueConstraint("tenant_id", "code", name="uq_staff_assignments_tenant_code"),
        Index("ix_staff_assignments_clinic", "tenant_id", "clinic_id"),
        Index("ix_staff_assignments_doctor", "tenant_id", "doctor_id"),
    )


class ClinicPolicy(
    Base,
    UUIDPrimaryKeyMixin,
    TenantMixin,
    TimestampMixin,
    SoftDeleteMixin,
    ActorAuditMixin,
    OptimisticLockMixin,
):
    __tablename__ = "clinic_policies"

    clinic_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    code: Mapped[str] = mapped_column(String(50), nullable=False)
    name: Mapped[str] = mapped_column(String(255), nullable=False)
    kind: Mapped[ClinicPolicyKind] = mapped_column(nullable=False)
    booking_lead_time_hours: Mapped[int] = mapped_column(Integer, default=24, nullable=False)
    cancellation_window_hours: Mapped[int] = mapped_column(Integer, default=12, nullable=False)
    privacy_flags: Mapped[dict | None] = mapped_column(JSON, nullable=True)
    rules: Mapped[dict | None] = mapped_column(JSON, nullable=True)
    status: Mapped[LifecycleStatus] = mapped_column(
        default=LifecycleStatus.ACTIVE, nullable=False
    )

    __table_args__ = (
        UniqueConstraint("tenant_id", "code", name="uq_clinic_policies_tenant_code"),
        Index("ix_clinic_policies_clinic", "tenant_id", "clinic_id"),
    )


class OperatingHoursPolicy(
    Base,
    UUIDPrimaryKeyMixin,
    TenantMixin,
    TimestampMixin,
    SoftDeleteMixin,
    ActorAuditMixin,
):
    __tablename__ = "operating_hours_policies"

    clinic_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    branch_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    code: Mapped[str] = mapped_column(String(50), nullable=False)
    name: Mapped[str] = mapped_column(String(255), nullable=False)
    weekly_hours: Mapped[dict] = mapped_column(JSON, nullable=False)
    exceptions: Mapped[dict | None] = mapped_column(JSON, nullable=True)
    timezone: Mapped[str] = mapped_column(String(64), default="Asia/Tehran", nullable=False)

    __table_args__ = (
        UniqueConstraint("tenant_id", "code", name="uq_operating_hours_policies_tenant_code"),
        Index("ix_operating_hours_clinic", "tenant_id", "clinic_id"),
    )
