"""Worker Fleet domain — SQLAlchemy models."""
from __future__ import annotations

import enum
from datetime import datetime
from typing import Optional
from uuid import UUID, uuid4

from sqlalchemy import Boolean, ForeignKey, Integer, String, Text, UniqueConstraint
from sqlalchemy.dialects.postgresql import JSONB, UUID as PGUUID
from sqlalchemy.orm import Mapped, mapped_column
from sqlalchemy.sql import func
from sqlalchemy.types import DateTime

from src.core.database import Base


class WorkerType(str, enum.Enum):
    cf_worker = "cf_worker"
    cf_queue_consumer = "cf_queue_consumer"


class WorkerStatus(str, enum.Enum):
    active = "active"
    deploying = "deploying"
    degraded = "degraded"
    unhealthy = "unhealthy"
    unknown = "unknown"


class FleetEventType(str, enum.Enum):
    deployed = "deployed"
    scaled_up = "scaled_up"
    scaled_down = "scaled_down"
    health_failed = "health_failed"
    recovered = "recovered"
    deploy_triggered = "deploy_triggered"
    deploy_failed = "deploy_failed"


class WorkerFleetRegistry(Base):
    """One row per worker instance. Multiple instances per worker_name allowed.

    CF Workers (pc-gateway, pc-realtime etc.) are serverless — fleet tracks health/version only.
    CF Queue consumers (pc-processor) have concurrency levers that Core adjusts via CF API.
    """

    __tablename__ = "worker_fleet_registry"

    id: Mapped[UUID] = mapped_column(PGUUID(as_uuid=True), primary_key=True, default=uuid4)
    worker_name: Mapped[str] = mapped_column(String(64), nullable=False)
    instance_id: Mapped[str] = mapped_column(String(64), nullable=False)
    worker_type: Mapped[str] = mapped_column(String(20), nullable=False)
    current_version: Mapped[Optional[str]] = mapped_column(String(64), nullable=True)
    target_version: Mapped[Optional[str]] = mapped_column(String(64), nullable=True)
    status: Mapped[str] = mapped_column(String(20), nullable=False, default="unknown")
    cf_script_id: Mapped[Optional[str]] = mapped_column(String(128), nullable=True)
    cf_queue_consumer_id: Mapped[Optional[str]] = mapped_column(String(128), nullable=True)
    cf_queue_id: Mapped[Optional[str]] = mapped_column(String(128), nullable=True)
    current_concurrency: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
    max_concurrency: Mapped[Optional[int]] = mapped_column(Integer, nullable=True, default=20)
    min_concurrency: Mapped[Optional[int]] = mapped_column(Integer, nullable=True, default=1)
    scale_up_threshold: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
    scale_down_threshold: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
    auto_deploy_enabled: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
    health_url: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    last_health_check_at: Mapped[Optional[datetime]] = mapped_column(
        DateTime(timezone=True), nullable=True
    )
    last_health_check_ok: Mapped[Optional[bool]] = mapped_column(Boolean, nullable=True)
    last_deployed_at: Mapped[Optional[datetime]] = mapped_column(
        DateTime(timezone=True), nullable=True
    )
    updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
    )

    __table_args__ = (
        UniqueConstraint("worker_name", "instance_id", name="uq_fleet_worker_instance"),
    )


class WorkerFleetEvent(Base):
    """Audit log for all fleet scaling, health, and deployment events."""

    __tablename__ = "worker_fleet_events"

    id: Mapped[UUID] = mapped_column(PGUUID(as_uuid=True), primary_key=True, default=uuid4)
    worker_name: Mapped[str] = mapped_column(String(64), nullable=False)
    instance_id: Mapped[str] = mapped_column(String(64), nullable=False)
    event_type: Mapped[str] = mapped_column(String(32), nullable=False)
    from_value: Mapped[Optional[str]] = mapped_column(String(128), nullable=True)
    to_value: Mapped[Optional[str]] = mapped_column(String(128), nullable=True)
    # auto_scaler | admin | ci_webhook
    triggered_by: Mapped[str] = mapped_column(String(32), nullable=False, default="auto_scaler")
    occurred_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), server_default=func.now()
    )
    metadata_json: Mapped[Optional[dict]] = mapped_column(JSONB, nullable=True)


class WorkerScalingConfig(Base):
    """Platform-level auto-scaling configuration. Single row (singleton pattern)."""

    __tablename__ = "worker_scaling_config"

    id: Mapped[UUID] = mapped_column(PGUUID(as_uuid=True), primary_key=True, default=uuid4)
    monitor_interval_seconds: Mapped[int] = mapped_column(Integer, nullable=False, default=60)
    auto_scale_enabled: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
    deployment_webhook_url: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    deployment_webhook_secret_enc: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
    updated_at: Mapped[datetime] = mapped_column(
        DateTime(timezone=True), server_default=func.now(), onupdate=func.now()
    )
