"""Job definition models for the Fliiq scheduler."""

import re
from datetime import datetime
from typing import Literal

from pydantic import BaseModel, field_validator, model_validator

_NAME_PATTERN = re.compile(r"^[a-z0-9][a-z0-9-]*[a-z0-9]$")


class TriggerConfig(BaseModel):
    """Trigger configuration for a job."""

    type: Literal["cron", "at", "every", "webhook"]
    schedule: str | None = None
    source: str | None = None
    match: dict[str, str] | None = None

    @model_validator(mode="after")
    def validate_trigger_fields(self) -> "TriggerConfig":
        if self.type in ("cron", "at", "every") and not self.schedule:
            raise ValueError(f"Trigger type '{self.type}' requires 'schedule'")
        if self.type == "webhook" and not self.source:
            raise ValueError("Trigger type 'webhook' requires 'source'")
        return self


class DeliveryConfig(BaseModel):
    """Delivery configuration for job results."""

    type: str
    to: str | None = None
    channel: str | None = None


class JobState(BaseModel):
    """Runtime state managed by the scheduler (not hand-edited)."""

    last_run_at: datetime | None = None
    last_status: Literal["success", "error", "running"] | None = None
    next_run_at: datetime | None = None
    run_count: int = 0


class JobDefinition(BaseModel):
    """A scheduled or webhook-triggered job definition."""

    name: str
    trigger: TriggerConfig
    prompt: str
    playbook: str | None = None
    skills: list[str] = []
    delivery: DeliveryConfig | None = None
    enabled: bool = True
    state: JobState = JobState()

    @field_validator("name")
    @classmethod
    def validate_name(cls, v: str) -> str:
        if len(v) < 2:
            raise ValueError("Job name must be at least 2 characters")
        if not _NAME_PATTERN.match(v):
            raise ValueError(
                f"Job name must be lowercase alphanumeric with hyphens (got '{v}')"
            )
        return v


class RunLogEntry(BaseModel):
    """A single run log entry for a job execution."""

    job_name: str
    started_at: datetime
    completed_at: datetime | None = None
    status: Literal["success", "error", "running"] = "running"
    duration_ms: int | None = None
    error: str | None = None
    iterations: int = 0
    stop_reason: str = ""
    response_text: str = ""
