'use client';

import { useEffect, useState, useCallback } from 'react';
import Link from 'next/link';
import { PageHeader } from '@bytelyst/dashboard-components';
import { useAuth } from '@/lib/auth-context';
import {
  listFactories,
  listJobs,
  getFleetMetrics,
  operatorAction,
  type FleetFactory,
  type FleetJob,
  type FleetMetrics,
} from '@/lib/fleet-client';

const POLL_INTERVAL = 30_000;

function HealthBadge({ health }: { health: string }) {
  const colors: Record<string, string> = {
    ok: 'bg-green-500/20 text-green-700 dark:text-green-400',
    degraded: 'bg-yellow-500/20 text-yellow-700 dark:text-yellow-400',
    down: 'bg-red-500/20 text-red-700 dark:text-red-400',
  };
  return (
    <span
      className={`inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${colors[health] ?? colors.ok}`}
    >
      {health}
    </span>
  );
}

function MetricCard({ label, value }: { label: string; value: number | string }) {
  return (
    <div className="rounded-lg border p-3">
      <p className="text-xs text-muted-foreground">{label}</p>
      <p className="text-2xl font-semibold tabular-nums">{value}</p>
    </div>
  );
}

function StageBadge({ stage }: { stage: string }) {
  const colors: Record<string, string> = {
    queued: 'bg-blue-500/20 text-blue-700 dark:text-blue-400',
    assigned: 'bg-purple-500/20 text-purple-700 dark:text-purple-400',
    building: 'bg-orange-500/20 text-orange-700 dark:text-orange-400',
    shipped: 'bg-green-500/20 text-green-700 dark:text-green-400',
    failed: 'bg-red-500/20 text-red-700 dark:text-red-400',
  };
  return (
    <span
      className={`inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${colors[stage] ?? 'bg-muted text-muted-foreground'}`}
    >
      {stage}
    </span>
  );
}

const usd = (n: number) => `$${n.toFixed(2)}`;

/** Budget guardrail: spend vs ceiling + projected end-of-window burn (§3). */
function BudgetGuardrail({ budget }: { budget: NonNullable<FleetMetrics['budget']> }) {
  const pct =
    budget.ceilingUsd > 0 ? Math.min(100, (budget.spentUsd / budget.ceilingUsd) * 100) : 0;
  const overProjected = budget.projectedUsd !== null && budget.projectedUsd > budget.ceilingUsd;
  const exhausted = budget.spentUsd >= budget.ceilingUsd;
  return (
    <section aria-label="Budget guardrail" data-testid="fleet-budget">
      <h2 className="text-lg font-semibold mb-3">Budget</h2>
      <div className="rounded-lg border p-4 space-y-3">
        <div className="flex items-center justify-between text-sm">
          <span>
            {usd(budget.spentUsd)} / {usd(budget.ceilingUsd)}{' '}
            <span className="text-muted-foreground">({budget.window})</span>
          </span>
          <span className="text-xs text-muted-foreground capitalize">{budget.status}</span>
        </div>
        <div className="h-2 w-full overflow-hidden rounded-full bg-muted">
          <div
            className={`h-full ${exhausted ? 'bg-red-500' : overProjected ? 'bg-yellow-500' : 'bg-green-500'}`}
            style={{ width: `${pct}%` }}
          />
        </div>
        {budget.projectedUsd !== null && (
          <p
            className={`text-xs ${overProjected ? 'text-yellow-700 dark:text-yellow-400' : 'text-muted-foreground'}`}
          >
            Projected {budget.window}: {usd(budget.projectedUsd)}
            {overProjected && ' — over ceiling at current burn'}
          </p>
        )}
        {budget.engines.length > 0 && (
          <ul className="text-xs text-muted-foreground space-y-1">
            {budget.engines.map(e => (
              <li key={e.engine} className="flex justify-between">
                <span className="font-mono">{e.engine}</span>
                <span className={e.exhausted ? 'text-red-600 dark:text-red-400' : ''}>
                  {usd(e.spentUsd)} / {usd(e.ceilingUsd)}
                  {e.exhausted && ' (capped)'}
                </span>
              </li>
            ))}
          </ul>
        )}
      </div>
    </section>
  );
}

/** Circuit-breaker panel: (factory, engine) pairs currently being routed around (§2). */
function BreakerPanel({ breakers }: { breakers: NonNullable<FleetMetrics['engineBreakers']> }) {
  const tripped = breakers.filter(b => b.state !== 'CLOSED');
  if (tripped.length === 0) return null;
  return (
    <section aria-label="Engine circuit breakers" data-testid="fleet-breakers">
      <h2 className="text-lg font-semibold mb-3">Engine circuit breakers</h2>
      <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
        {tripped.map(b => (
          <div
            key={`${b.factoryId}:${b.engine}`}
            className="rounded-lg border border-red-500/30 bg-red-500/5 p-3 text-sm"
          >
            <div className="flex items-center justify-between">
              <span className="font-mono truncate">
                {b.factoryId} · {b.engine}
              </span>
              <span
                className={`rounded-full px-2 py-0.5 text-xs font-medium ${b.state === 'OPEN' ? 'bg-red-500/20 text-red-700 dark:text-red-400' : 'bg-yellow-500/20 text-yellow-700 dark:text-yellow-400'}`}
              >
                {b.state}
              </span>
            </div>
            <p className="mt-1 text-xs text-muted-foreground">
              {b.failureCount} failure(s)
              {b.lastFailureAt && ` · last ${new Date(b.lastFailureAt).toLocaleTimeString()}`}
            </p>
          </div>
        ))}
      </div>
    </section>
  );
}

export default function FleetOverviewPage() {
  const { token } = useAuth();
  const [factories, setFactories] = useState<FleetFactory[]>([]);
  const [jobs, setJobs] = useState<FleetJob[]>([]);
  const [metrics, setMetrics] = useState<FleetMetrics | null>(null);
  const [deadLetters, setDeadLetters] = useState<FleetJob[]>([]);
  const [redriving, setRedriving] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);

  const refresh = useCallback(async () => {
    try {
      const [facRes, jobRes, metricsRes, dlRes] = await Promise.all([
        listFactories(),
        listJobs({ limit: 10 }),
        getFleetMetrics().catch(() => null),
        listJobs({ stage: 'dead_letter', limit: 50 }).catch(() => ({ jobs: [] as FleetJob[] })),
      ]);
      setFactories(facRes.factories);
      setJobs(jobRes.jobs);
      setMetrics(metricsRes);
      // Filter client-side too, so the triage list is correct even if the server
      // ignores the stage filter.
      setDeadLetters(dlRes.jobs.filter(j => j.stage === 'dead_letter'));
    } catch {
      /* degrade gracefully */
    } finally {
      setLoading(false);
    }
  }, []);

  const handleRedrive = useCallback(
    async (id: string) => {
      setRedriving(id);
      try {
        await operatorAction(id, 'redrive');
        await refresh();
      } catch {
        /* surfaced on next poll */
      } finally {
        setRedriving(null);
      }
    },
    [refresh]
  );

  useEffect(() => {
    if (!token) return;
    refresh();
    const id = setInterval(refresh, POLL_INTERVAL);
    return () => clearInterval(id);
  }, [token, refresh]);

  if (loading) {
    return (
      <div className="p-6">
        <PageHeader title="Fleet" />
        <p className="text-muted-foreground mt-4">Loading fleet data...</p>
      </div>
    );
  }

  return (
    <div className="p-6 space-y-8">
      <PageHeader title="Fleet Control Plane" />

      {/* Metrics + alerts */}
      {metrics && (
        <section aria-label="Fleet metrics" data-testid="fleet-metrics">
          {metrics.alerts.length > 0 && (
            <div className="space-y-2 mb-4" data-testid="fleet-alerts">
              {metrics.alerts.map(a => (
                <div
                  key={a.code}
                  role="alert"
                  className={`rounded-md border px-3 py-2 text-sm ${
                    a.level === 'critical'
                      ? 'border-red-500/40 bg-red-500/10 text-red-700 dark:text-red-400'
                      : 'border-yellow-500/40 bg-yellow-500/10 text-yellow-700 dark:text-yellow-400'
                  }`}
                >
                  <span className="font-medium uppercase mr-2">{a.level}</span>
                  {a.message}
                </div>
              ))}
            </div>
          )}
          <div className="grid gap-4 grid-cols-2 sm:grid-cols-3 lg:grid-cols-5">
            <MetricCard label="Queue depth" value={metrics.jobs.queueDepth} />
            <MetricCard label="Active" value={metrics.jobs.active} />
            <MetricCard label="Blocked" value={metrics.jobs.blocked} />
            <MetricCard
              label="Live factories"
              value={`${metrics.factories.live}/${metrics.factories.total}`}
            />
            <MetricCard label="Utilization" value={`${metrics.factories.utilizationPct}%`} />
          </div>
        </section>
      )}

      {/* Budget guardrail */}
      {metrics?.budget && <BudgetGuardrail budget={metrics.budget} />}

      {/* Engine circuit breakers */}
      {metrics?.engineBreakers && metrics.engineBreakers.length > 0 && (
        <BreakerPanel breakers={metrics.engineBreakers} />
      )}

      {/* Dead-letter triage */}
      {deadLetters.length > 0 && (
        <section aria-label="Dead-letter triage" data-testid="fleet-dead-letter">
          <h2 className="text-lg font-semibold mb-3">
            Dead-letter triage{' '}
            <span className="text-sm font-normal text-muted-foreground">
              ({deadLetters.length})
            </span>
          </h2>
          <div className="overflow-x-auto">
            <table className="w-full text-sm" aria-label="Dead-letter jobs">
              <thead>
                <tr className="border-b text-left text-muted-foreground">
                  <th className="pb-2 pr-4">Key</th>
                  <th className="pb-2 pr-4">Engine</th>
                  <th className="pb-2 pr-4">Attempts</th>
                  <th className="pb-2">Action</th>
                </tr>
              </thead>
              <tbody>
                {deadLetters.map(j => (
                  <tr key={j.id} className="border-b last:border-0 hover:bg-muted/50">
                    <td className="py-2 pr-4">
                      <Link
                        href={`/dashboard/fleet/jobs/${j.id}`}
                        className="hover:underline font-mono text-xs"
                      >
                        {j.idempotencyKey}
                      </Link>
                    </td>
                    <td className="py-2 pr-4 font-mono text-xs">
                      {j.engine ?? j.engineClass ?? '—'}
                    </td>
                    <td className="py-2 pr-4 tabular-nums">{j.attempts}</td>
                    <td className="py-2">
                      <button
                        type="button"
                        onClick={() => handleRedrive(j.id)}
                        disabled={redriving === j.id}
                        aria-label={`Re-drive job ${j.idempotencyKey}`}
                        className="rounded-md border px-2 py-1 text-xs font-medium hover:bg-muted disabled:opacity-50"
                      >
                        {redriving === j.id ? 'Re-driving…' : 'Re-drive'}
                      </button>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </section>
      )}

      {/* Factory cards */}
      <section>
        <h2 className="text-lg font-semibold mb-3">Factories</h2>
        {factories.length === 0 ? (
          <p className="text-muted-foreground text-sm">
            No factories registered. Factories appear after their first heartbeat.
          </p>
        ) : (
          <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
            {factories.map(f => (
              <div
                key={f.id}
                className="rounded-lg border p-4 space-y-2"
                aria-label={`Factory ${f.factoryId}`}
              >
                <div className="flex items-center justify-between">
                  <span className="font-mono text-sm truncate">{f.factoryId}</span>
                  <HealthBadge health={f.health} />
                </div>
                <div className="text-xs text-muted-foreground space-y-1">
                  <p>Capabilities: {f.capabilities.length > 0 ? f.capabilities.join(', ') : '—'}</p>
                  <p>
                    Load: {f.load} / {f.seatLimit} seats
                  </p>
                  <p>Last heartbeat: {new Date(f.lastHeartbeatAt).toLocaleTimeString()}</p>
                </div>
              </div>
            ))}
          </div>
        )}
      </section>

      {/* Recent jobs summary */}
      <section>
        <div className="flex items-center justify-between mb-3">
          <h2 className="text-lg font-semibold">Recent Jobs</h2>
          <Link
            href="/dashboard/fleet/jobs"
            className="text-sm text-blue-600 hover:underline"
            aria-label="View all jobs"
          >
            View all →
          </Link>
        </div>
        {jobs.length === 0 ? (
          <p className="text-muted-foreground text-sm">No jobs found.</p>
        ) : (
          <div className="overflow-x-auto">
            <table className="w-full text-sm" aria-label="Recent fleet jobs">
              <thead>
                <tr className="border-b text-left text-muted-foreground">
                  <th className="pb-2 pr-4">Key</th>
                  <th className="pb-2 pr-4">Stage</th>
                  <th className="pb-2 pr-4">Priority</th>
                  <th className="pb-2">Created</th>
                </tr>
              </thead>
              <tbody>
                {jobs.map(j => (
                  <tr key={j.id} className="border-b last:border-0 hover:bg-muted/50">
                    <td className="py-2 pr-4">
                      <Link
                        href={`/dashboard/fleet/jobs/${j.id}`}
                        className="hover:underline font-mono text-xs"
                      >
                        {j.idempotencyKey}
                      </Link>
                    </td>
                    <td className="py-2 pr-4">
                      <StageBadge stage={j.stage} />
                    </td>
                    <td className="py-2 pr-4 capitalize">{j.priority}</td>
                    <td className="py-2 text-muted-foreground text-xs">
                      {new Date(j.createdAt).toLocaleDateString()}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </section>

      {/* Quick links */}
      <nav className="flex gap-4" aria-label="Fleet navigation">
        <Link href="/dashboard/fleet/jobs" className="text-sm underline" aria-label="All jobs page">
          All Jobs
        </Link>
        <Link href="/dashboard/fleet/budget" className="text-sm underline" aria-label="Budget page">
          Budgets
        </Link>
      </nav>
    </div>
  );
}
