# #region LlmModels [C:3] [TYPE Module] [SEMANTICS sqlalchemy, llm, model, schema, validate, provider]
# @BRIEF SQLAlchemy models for LLM provider configuration and validation results.
# @LAYER Domain
# @RELATION INHERITS -> [MappingModels]

from datetime import UTC, datetime
import uuid

from sqlalchemy import JSON, Boolean, Column, DateTime, ForeignKey, Integer, String, Text, Time
from sqlalchemy.orm import relationship

from .mapping import Base


def generate_uuid():
    return str(uuid.uuid4())


# #region ValidationPolicy [TYPE Class]
# @BRIEF Defines a scheduled rule for validating a group of dashboards within an execution window.
# @RELATION DEPENDS_ON -> [LLMProvider]
class ValidationPolicy(Base):
    __tablename__ = "validation_policies"

    id = Column(String, primary_key=True, default=generate_uuid)
    name = Column(String, nullable=False)
    description = Column(Text, nullable=True)
    environment_id = Column(String, nullable=False)
    is_active = Column(Boolean, default=True)
    dashboard_ids = Column(JSON, nullable=False)  # Array of dashboard IDs (v1, deprecated in favor of ValidationSource)
    provider_id = Column(String, nullable=True)  # Reference to LLMProvider.id
    schedule_days = Column(JSON, nullable=False)  # Array of integers (0-6)
    window_start = Column(Time, nullable=False)
    window_end = Column(Time, nullable=False)
    notify_owners = Column(Boolean, default=True)
    custom_channels = Column(JSON, nullable=True)  # List of external channels
    alert_condition = Column(String, default="FAIL_ONLY")  # FAIL_ONLY, WARN_AND_FAIL, ALWAYS
    created_at = Column(DateTime, default=lambda: datetime.now(UTC))
    updated_at = Column(DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC))

    # v2 columns
    prompt_template = Column(Text, nullable=True)
    screenshot_enabled = Column(Boolean, default=True)
    logs_enabled = Column(Boolean, default=True)
    execute_chart_data = Column(Boolean, default=False)
    llm_batch_size = Column(Integer, default=1)
    policy_dashboard_concurrency_limit = Column(Integer, default=3)
    source_snapshot = Column(JSON, nullable=True)

    # v2 relationships
    sources = relationship("ValidationSource", back_populates="policy", cascade="all, delete-orphan")
# #endregion ValidationPolicy


# #region LLMProvider [TYPE Class]
# @BRIEF SQLAlchemy model for LLM provider configuration.
class LLMProvider(Base):
    __tablename__ = "llm_providers"

    id = Column(String, primary_key=True, default=generate_uuid)
    provider_type = Column(String, nullable=False)  # openai, openrouter, kilo
    name = Column(String, nullable=False)
    base_url = Column(String, nullable=False)
    api_key = Column(String, nullable=False)  # Should be encrypted
    default_model = Column(String, nullable=False)
    is_active = Column(Boolean, default=True)
    is_multimodal = Column(Boolean, default=False)
    max_images = Column(Integer, nullable=True, default=None)
    created_at = Column(DateTime, default=lambda: datetime.now(UTC))
# #endregion LLMProvider


# #region ValidationSource [TYPE Class]
# @BRIEF Relational source mapping for validation policies (v2).
class ValidationSource(Base):
    __tablename__ = "validation_sources"

    id = Column(String, primary_key=True, default=generate_uuid)
    policy_id = Column(String, ForeignKey("validation_policies.id"), nullable=False, index=True)
    type = Column(String, nullable=False)  # "dashboard_id" or "dashboard_url"
    value = Column(String, nullable=False)  # numeric ID or full URL
    parsed_context = Column(JSON, nullable=True)  # SupersetContextExtractor result
    status = Column(String, nullable=False, default="valid")  # valid | partial_recovery | stale | invalid | permission_denied | parse_failed
    resolved_dashboard_id = Column(String, nullable=True)
    title = Column(String, nullable=True)
    last_error = Column(String, nullable=True)
    last_checked_at = Column(DateTime, nullable=True)
    created_at = Column(DateTime, default=lambda: datetime.now(UTC))

    policy = relationship("ValidationPolicy", back_populates="sources")
# #endregion ValidationSource


# #region ValidationRecord [TYPE Class]
# @BRIEF SQLAlchemy model for dashboard validation history.
class ValidationRecord(Base):
    __tablename__ = "llm_validation_results"

    id = Column(String, primary_key=True, default=generate_uuid)
    task_id = Column(String, nullable=True, index=True)  # Reference to TaskRecord
    policy_id = Column(String, nullable=True, index=True)  # Reference to ValidationPolicy.id
    dashboard_id = Column(String, nullable=False, index=True)
    environment_id = Column(String, nullable=True, index=True)
    timestamp = Column(DateTime, default=lambda: datetime.now(UTC))
    status = Column(String, nullable=False)  # PASS, WARN, FAIL, UNKNOWN
    screenshot_path = Column(String, nullable=True)
    issues = Column(JSON, nullable=False)
    summary = Column(Text, nullable=False)
    raw_response = Column(Text, nullable=True)

    # v2 columns
    run_id = Column(String, ForeignKey("validation_runs.id"), nullable=True, index=True)
    source_id = Column(String, ForeignKey("validation_sources.id"), nullable=True)
    execution_path = Column(String, nullable=True)  # "screenshot" or "text_only"
    dataset_health = Column(JSON, nullable=True)
    chart_data_results = Column(JSON, nullable=True)
    tab_screenshots = Column(JSON, nullable=True)
    logs_sent_to_llm = Column(JSON, nullable=True)
    token_usage = Column(JSON, nullable=True)
    timings = Column(JSON, nullable=True)
    screenshot_paths = Column(JSON, nullable=True)  # List of WebP paths
# #endregion ValidationRecord


# #region ValidationRun [TYPE Class]
# @BRIEF Tracks a single validation execution run (v2).
class ValidationRun(Base):
    __tablename__ = "validation_runs"

    id = Column(String, primary_key=True, default=generate_uuid)
    policy_id = Column(String, ForeignKey("validation_policies.id"), nullable=False, index=True)
    task_id = Column(String, nullable=True)  # Task Manager task ID
    started_at = Column(DateTime, default=lambda: datetime.now(UTC))
    finished_at = Column(DateTime, nullable=True)
    trigger = Column(String, nullable=False, default="manual")  # "manual" or "scheduled"
    status = Column(String, nullable=False, default="running")  # running | completed | partial | failed
    dashboard_count = Column(Integer, default=0)
    pass_count = Column(Integer, default=0)
    warn_count = Column(Integer, default=0)
    fail_count = Column(Integer, default=0)
    unknown_count = Column(Integer, default=0)
    created_at = Column(DateTime, default=lambda: datetime.now(UTC))

    records = relationship("ValidationRecord", backref="run", foreign_keys=[ValidationRecord.run_id])
# #endregion ValidationRun


# #endregion LlmModels
