"""Serialization helpers for manager-facing worker API responses."""

from __future__ import annotations

import json
from datetime import UTC, datetime, timedelta
from typing import Any

from hive_compute.coordinator.api_timestamps import latest_api_timestamp, parse_api_timestamp
from hive_compute.coordinator.worker_api_models import WorkerListItemResponse


def serialize_worker_rows(rows: list[Any], *, stale_minutes: int) -> list[WorkerListItemResponse]:
    workers = [serialize_worker_row(row, stale_minutes=stale_minutes) for row in rows]
    workers.sort(key=_worker_sort_key)
    return workers


def serialize_worker_row(row, *, stale_minutes: int) -> WorkerListItemResponse:
    available_handlers = json.loads(row["available_handlers"]) if row["available_handlers"] else []
    available_models = json.loads(row["available_models"]) if row["available_models"] else []
    has_model_capabilities = "model_capabilities" in row.keys() and row["model_capabilities"]
    model_capabilities = json.loads(row["model_capabilities"]) if has_model_capabilities else []
    credential_state = "revoked" if row["worker_token_revoked_at"] else "active"
    observed_state, observed_reason = _derive_observed_state(row, stale_minutes=stale_minutes)
    capability_state, capability_reason = _derive_capability_state(
        row,
        available_models=available_models,
        stale_minutes=stale_minutes,
    )
    last_seen_at = latest_api_timestamp(
        row["last_poll_at"],
        row["last_heartbeat"],
        row["last_claimed_at"],
        row["registered_at"],
    )

    return WorkerListItemResponse(
        worker_id=row["worker_id"],
        status=row["status"],
        chip=row["chip"],
        memory_gb=row["memory_gb"],
        gpu_cores=row["gpu_cores"],
        available_handlers=available_handlers,
        available_models=available_models,
        model_capabilities=model_capabilities,
        capabilities_advertised_at=row["capabilities_advertised_at"],
        capabilities_confirmed_at=row["capabilities_confirmed_at"],
        capability_state=capability_state,
        capability_state_reason=capability_reason,
        last_poll_at=row["last_poll_at"],
        last_heartbeat=row["last_heartbeat"],
        last_claimed_at=row["last_claimed_at"],
        last_claimed_job_id=row["last_claimed_job_id"],
        last_job_failure_at=row["last_job_failure_at"],
        last_job_failure_detail=row["last_job_failure_detail"],
        last_failed_job_id=row["last_failed_job_id"],
        last_seen_at=last_seen_at,
        jobs_completed=row["jobs_completed"],
        registered_at=row["registered_at"],
        token_last_four=row["worker_token_last_four"],
        token_issued_at=row["worker_token_issued_at"],
        token_revoked_at=row["worker_token_revoked_at"],
        credential_state=credential_state,
        observed_state=observed_state,
        observed_state_reason=observed_reason,
    )


def _derive_capability_state(
    row,
    *,
    available_models: list[str],
    stale_minutes: int,
) -> tuple[str, str]:
    if not available_models:
        return "missing", "Worker has not advertised any supported transcription models"

    stale_before = datetime.now(UTC) - timedelta(minutes=stale_minutes)
    advertised_at = parse_api_timestamp(row["capabilities_advertised_at"])
    confirmed_at = parse_api_timestamp(row["capabilities_confirmed_at"])
    freshest = max((value for value in (advertised_at, confirmed_at) if value is not None), default=None)

    if freshest and freshest >= stale_before:
        if confirmed_at and confirmed_at >= stale_before:
            return "fresh", f"Capabilities confirmed at {row['capabilities_confirmed_at']}"
        return "fresh", f"Capabilities advertised at {row['capabilities_advertised_at']}"

    last_poll_at = parse_api_timestamp(row["last_poll_at"])
    last_heartbeat = parse_api_timestamp(row["last_heartbeat"])
    last_claimed_at = parse_api_timestamp(row["last_claimed_at"])
    recently_seen = any(
        value is not None and value >= stale_before
        for value in (last_poll_at, last_heartbeat, last_claimed_at)
    )

    if not recently_seen:
        if freshest:
            return "stale", (
                "Worker is offline; capability snapshot last refreshed at "
                f"{freshest.isoformat().replace('+00:00', 'Z')}"
            )
        return "stale", "Worker is offline and capability freshness is unknown"

    if freshest:
        return "stale", f"Capability snapshot is stale since {freshest.isoformat().replace('+00:00', 'Z')}"
    return "stale", "Capability freshness has not been confirmed yet"


def _derive_observed_state(row, *, stale_minutes: int) -> tuple[str, str]:
    stale_before = datetime.now(UTC) - timedelta(minutes=stale_minutes)

    last_poll_at = parse_api_timestamp(row["last_poll_at"])
    last_heartbeat = parse_api_timestamp(row["last_heartbeat"])
    last_claimed_at = parse_api_timestamp(row["last_claimed_at"])
    token_revoked_at = parse_api_timestamp(row["worker_token_revoked_at"])
    registered_at = parse_api_timestamp(row["registered_at"])

    if token_revoked_at is not None:
        return "auth_failed", f"Worker token revoked at {row['worker_token_revoked_at']}"

    if row["status"] == "busy":
        if last_heartbeat and last_heartbeat >= stale_before:
            if row["last_claimed_job_id"]:
                return "healthy", f"Processing {row['last_claimed_job_id']}"
            return "healthy", "Processing work and heartbeating"
        return "offline", "Worker is marked busy but the heartbeat is stale"

    if last_poll_at and last_poll_at >= stale_before:
        return "idle", "Polling successfully"

    if last_heartbeat and last_heartbeat >= stale_before:
        return "healthy", "Recent heartbeat received"

    if last_claimed_at and last_claimed_at >= stale_before:
        return "healthy", "Recently claimed work"

    if row["status"] == "idle" and registered_at and registered_at >= stale_before:
        return "idle", "Recently enrolled; waiting for the first poll"

    return "offline", "No recent poll or heartbeat"


def _worker_sort_key(worker: WorkerListItemResponse) -> tuple[int, float, str]:
    observed_rank = {
        "auth_failed": 0,
        "offline": 1,
        "healthy": 2,
        "idle": 3,
    }.get(worker.observed_state, 4)
    timestamp = parse_api_timestamp(worker.last_seen_at)
    sort_timestamp = -(timestamp.timestamp() if timestamp else 0.0)
    return observed_rank, sort_timestamp, worker.worker_id
