"""Dispatch engine aggregates — Phase 10.5."""
from __future__ import annotations

import uuid
from datetime import datetime

from sqlalchemy import DateTime, Index, 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 DispatchJobStatus, GUID, JobAssignmentStatus


class DispatchJob(
    Base,
    UUIDPrimaryKeyMixin,
    TenantMixin,
    TimestampMixin,
    SoftDeleteMixin,
    ActorAuditMixin,
    OptimisticLockMixin,
):
    """Vertical job refs only — no deep order ownership."""

    __tablename__ = "dispatch_jobs"

    organization_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    hub_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    code: Mapped[str] = mapped_column(String(50), nullable=False)
    status: Mapped[DispatchJobStatus] = mapped_column(
        default=DispatchJobStatus.PENDING, nullable=False
    )
    external_order_ref: Mapped[str | None] = mapped_column(String(255), nullable=True)
    external_source: Mapped[str | None] = mapped_column(String(100), nullable=True)
    priority: Mapped[int] = mapped_column(default=0, nullable=False)
    pickup_address_ref: Mapped[str | None] = mapped_column(String(255), nullable=True)
    dropoff_address_ref: Mapped[str | None] = mapped_column(String(255), nullable=True)
    scheduled_at: Mapped[datetime | None] = mapped_column(
        DateTime(timezone=True), nullable=True
    )
    status_reason: Mapped[str | None] = mapped_column(String(500), nullable=True)
    metadata_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)

    __table_args__ = (
        UniqueConstraint("tenant_id", "code", name="uq_dispatch_jobs_tenant_code"),
        Index("ix_dispatch_jobs_tenant_status", "tenant_id", "status"),
        Index("ix_dispatch_jobs_external_ref", "tenant_id", "external_order_ref"),
        Index("ix_dispatch_jobs_tenant_deleted", "tenant_id", "is_deleted"),
    )


class JobAssignment(
    Base,
    UUIDPrimaryKeyMixin,
    TenantMixin,
    TimestampMixin,
    SoftDeleteMixin,
    ActorAuditMixin,
    OptimisticLockMixin,
):
    __tablename__ = "job_assignments"

    dispatch_job_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    driver_id: Mapped[uuid.UUID] = mapped_column(GUID(), nullable=False)
    vehicle_id: Mapped[uuid.UUID | None] = mapped_column(GUID(), nullable=True)
    status: Mapped[JobAssignmentStatus] = mapped_column(
        default=JobAssignmentStatus.PENDING, nullable=False
    )
    assigned_at: Mapped[datetime | None] = mapped_column(
        DateTime(timezone=True), nullable=True
    )
    notes: Mapped[str | None] = mapped_column(Text, nullable=True)
    metadata_json: Mapped[dict | None] = mapped_column(JSON, nullable=True)

    __table_args__ = (
        Index("ix_job_assignments_job", "tenant_id", "dispatch_job_id"),
        Index("ix_job_assignments_driver", "tenant_id", "driver_id"),
        Index("ix_job_assignments_tenant_status", "tenant_id", "status"),
        Index("ix_job_assignments_tenant_deleted", "tenant_id", "is_deleted"),
    )
