from __future__ import annotations

from datetime import UTC, datetime
from typing import Any

from sqlalchemy import select
from sqlalchemy.orm import Session

from app.core.agent_enums import AgentRunStatus
from app.models.agent_run import AgentRun
from app.services.knowledge_constants import (
    KNOWLEDGE_INGEST_STATUS_META,
    KNOWLEDGE_INGEST_STATUS_PUBLISHED,
    KNOWLEDGE_INGEST_SYNC_STALE_SECONDS,
)


def normalize_ingest_status_code(value: Any) -> int:
    try:
        status_code = int(value)
    except (TypeError, ValueError):
        return KNOWLEDGE_INGEST_STATUS_PUBLISHED
    if status_code not in KNOWLEDGE_INGEST_STATUS_META:
        return KNOWLEDGE_INGEST_STATUS_PUBLISHED
    return status_code


def is_syncing_status_stale(entry: dict[str, Any]) -> bool:
    raw_value = str(entry.get("ingest_status_updated_at") or "").strip()
    if not raw_value:
        return True
    try:
        updated_at = datetime.fromisoformat(raw_value)
    except ValueError:
        return True
    if updated_at.tzinfo is None:
        updated_at = updated_at.replace(tzinfo=UTC)
    age_seconds = (datetime.now(UTC) - updated_at.astimezone(UTC)).total_seconds()
    return age_seconds >= KNOWLEDGE_INGEST_SYNC_STALE_SECONDS


def should_preserve_syncing_status(entry: dict[str, Any], *, db: Session | None) -> bool:
    agent_run_id = str(entry.get("ingest_agent_run_id") or "").strip()
    if not agent_run_id or db is None:
        return not is_syncing_status_stale(entry)

    run = db.scalar(select(AgentRun).where(AgentRun.run_id == agent_run_id))
    if run is None:
        return not is_syncing_status_stale(entry)
    if run.status != AgentRunStatus.RUNNING.value:
        return False

    heartbeat_at = str((run.route_json or {}).get("heartbeat_at") or "").strip()
    if heartbeat_at:
        probe_entry = {"ingest_status_updated_at": heartbeat_at}
        return not is_syncing_status_stale(probe_entry)

    return not is_syncing_status_stale(entry)


def resolve_linked_ingest_run_status(entry: dict[str, Any], *, db: Session | None) -> str:
    agent_run_id = str(entry.get("ingest_agent_run_id") or "").strip()
    if not agent_run_id or db is None:
        return ""

    run = db.scalar(select(AgentRun).where(AgentRun.run_id == agent_run_id))
    if run is None:
        return ""
    return str(run.status or "").strip()
