"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import { getPhyloJobStatus } from "@/lib/api";

type JobStatus = "queued" | "running" | "completed" | "failed" | "unknown";

interface JobArtifact {
  name: string;
  url: string;
  mime?: string;
  bytes?: number;
}

interface Props {
  jobId: string;
  toolName?: string;
  /** Called when job completes with output artifacts. */
  onComplete?: (artifacts: JobArtifact[]) => void;
}

const STATUS_COLORS: Record<JobStatus, { bg: string; text: string; ring: string }> = {
  queued: { bg: "bg-amber-50", text: "text-amber-700", ring: "ring-amber-200" },
  running: { bg: "bg-blue-50", text: "text-blue-700", ring: "ring-blue-200" },
  completed: { bg: "bg-emerald-50", text: "text-emerald-700", ring: "ring-emerald-200" },
  failed: { bg: "bg-red-50", text: "text-red-700", ring: "ring-red-200" },
  unknown: { bg: "bg-gray-50", text: "text-gray-500", ring: "ring-gray-200" },
};

const STATUS_LABELS: Record<JobStatus, string> = {
  queued: "Queued",
  running: "Running",
  completed: "Completed",
  failed: "Failed",
  unknown: "Unknown",
};

function normalizeStatus(raw: string | undefined): JobStatus {
  if (!raw) return "unknown";
  const s = raw.toLowerCase();
  if (s === "completed" || s === "success" || s === "done") return "completed";
  if (s === "failed" || s === "error" || s === "cancelled") return "failed";
  if (s === "running" || s === "processing" || s === "in_progress") return "running";
  if (s === "queued" || s === "pending" || s === "submitted") return "queued";
  return "unknown";
}

function formatElapsed(ms: number): string {
  const sec = Math.floor(ms / 1000);
  if (sec < 60) return `${sec}s`;
  const min = Math.floor(sec / 60);
  const rem = sec % 60;
  return `${min}m ${rem}s`;
}

export default function JobStatusCard({ jobId, toolName, onComplete }: Props) {
  const [status, setStatus] = useState<JobStatus>("queued");
  const [error, setError] = useState<string | null>(null);
  const [artifacts, setArtifacts] = useState<JobArtifact[]>([]);
  const [costEstimate, setCostEstimate] = useState<number | null>(null);
  const [elapsed, setElapsed] = useState(0);
  const [expanded, setExpanded] = useState(false);

  const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);
  const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);
  const startTimeRef = useRef(Date.now());
  const completedRef = useRef(false);

  const stopPolling = useCallback(() => {
    if (pollRef.current) {
      clearInterval(pollRef.current);
      pollRef.current = null;
    }
    if (timerRef.current) {
      clearInterval(timerRef.current);
      timerRef.current = null;
    }
  }, []);

  useEffect(() => {
    if (!jobId) return;

    // Start elapsed timer
    startTimeRef.current = Date.now();
    timerRef.current = setInterval(() => {
      setElapsed(Date.now() - startTimeRef.current);
    }, 1000);

    // Start polling
    const poll = async () => {
      try {
        const data = await getPhyloJobStatus(jobId);
        const hubStatus = data.hub?.status;
        const normalized = normalizeStatus(hubStatus as string | undefined);
        setStatus(normalized);

        if (data.hub?.cost_estimate != null) {
          setCostEstimate(data.hub.cost_estimate as number);
        }

        if (normalized === "completed" && !completedRef.current) {
          completedRef.current = true;
          stopPolling();
          const arts = (data.artifacts ?? []) as JobArtifact[];
          setArtifacts(arts);
          onComplete?.(arts);
        } else if (normalized === "failed") {
          stopPolling();
          const errMsg =
            (data.hub?.error as string) ??
            (data.hub?.message as string) ??
            "Job failed";
          setError(String(errMsg));
        }
      } catch {
        // Transient error, keep polling
      }
    };

    // Poll immediately, then every 5s
    poll();
    pollRef.current = setInterval(poll, 5000);

    return stopPolling;
  }, [jobId, onComplete, stopPolling]);

  const isActive = status === "queued" || status === "running";
  const colors = STATUS_COLORS[status];

  return (
    <div
      data-testid="job-status-card"
      className="my-2 rounded-xl border border-border bg-white overflow-hidden shadow-sm animate-fade-in"
    >
      {/* Header row */}
      <button
        onClick={() => setExpanded(!expanded)}
        className="w-full flex items-center gap-3 px-4 py-3 text-left hover:bg-muted/20 transition-colors"
      >
        {/* Status indicator */}
        {isActive ? (
          <div className="w-5 h-5 rounded-full border-2 border-accent border-t-transparent animate-spin shrink-0" />
        ) : status === "completed" ? (
          <div className="w-5 h-5 rounded-full bg-emerald-100 flex items-center justify-center shrink-0">
            <svg
              className="w-3 h-3 text-emerald-600"
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              strokeWidth={3}
            >
              <polyline points="20 6 9 17 4 12" />
            </svg>
          </div>
        ) : (
          <div className="w-5 h-5 rounded-full bg-red-100 flex items-center justify-center shrink-0">
            <svg
              className="w-3 h-3 text-red-600"
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              strokeWidth={3}
            >
              <line x1="18" y1="6" x2="6" y2="18" />
              <line x1="6" y1="6" x2="18" y2="18" />
            </svg>
          </div>
        )}

        <div className="flex-1 min-w-0">
          <div className="flex items-center gap-2">
            <span className="text-xs font-medium text-foreground">
              {toolName ? toolName.replace(/_/g, " ") : "Job"}{" "}
            </span>
            <span
              className={`inline-flex items-center px-1.5 py-0.5 rounded-full text-[10px] font-medium ring-1 ${colors.bg} ${colors.text} ${colors.ring}`}
            >
              {STATUS_LABELS[status]}
            </span>
          </div>
          <span className="text-[10px] text-muted-fg font-mono">{jobId}</span>
        </div>

        {/* Right side: elapsed + cost */}
        <div className="text-right shrink-0">
          <p className="text-[11px] text-foreground tabular-nums">
            {formatElapsed(elapsed)}
          </p>
          {costEstimate != null && (
            <p className="text-[10px] text-muted-fg">
              ~${costEstimate.toFixed(2)}
            </p>
          )}
        </div>

        <svg
          className={`w-3.5 h-3.5 text-muted-fg transition-transform shrink-0 ${
            expanded ? "rotate-180" : ""
          }`}
          viewBox="0 0 24 24"
          fill="none"
          stroke="currentColor"
          strokeWidth={2}
        >
          <polyline points="6 9 12 15 18 9" />
        </svg>
      </button>

      {/* Expanded detail */}
      {expanded && (
        <div className="border-t border-border-subtle px-4 py-3 space-y-2">
          <div className="grid grid-cols-2 gap-2 text-[11px]">
            <div>
              <p className="text-[10px] text-muted-fg uppercase tracking-wider font-semibold">
                Status
              </p>
              <p className="text-foreground">{STATUS_LABELS[status]}</p>
            </div>
            <div>
              <p className="text-[10px] text-muted-fg uppercase tracking-wider font-semibold">
                Elapsed
              </p>
              <p className="text-foreground tabular-nums">
                {formatElapsed(elapsed)}
              </p>
            </div>
            {costEstimate != null && (
              <div>
                <p className="text-[10px] text-muted-fg uppercase tracking-wider font-semibold">
                  Cost
                </p>
                <p className="text-foreground">${costEstimate.toFixed(2)}</p>
              </div>
            )}
            {toolName && (
              <div>
                <p className="text-[10px] text-muted-fg uppercase tracking-wider font-semibold">
                  Tool
                </p>
                <p className="text-foreground">{toolName}</p>
              </div>
            )}
          </div>
        </div>
      )}

      {/* Completed: artifacts */}
      {status === "completed" && artifacts.length > 0 && (
        <div className="border-t border-border-subtle px-4 py-2">
          <p className="text-[10px] text-muted-fg uppercase tracking-wider font-semibold mb-1">
            Results
          </p>
          <ul className="space-y-1">
            {artifacts.map((a, i) => (
              <li key={i} className="flex items-center gap-2">
                <svg
                  className="w-3 h-3 text-muted-fg shrink-0"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  strokeWidth={2}
                >
                  <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
                  <polyline points="14 2 14 8 20 8" />
                </svg>
                <a
                  href={a.url}
                  target="_blank"
                  rel="noopener noreferrer"
                  className="text-[11px] text-accent hover:text-accent-hover hover:underline truncate"
                >
                  {a.name}
                </a>
                {a.bytes != null && a.bytes > 0 && (
                  <span className="text-[10px] text-muted-fg shrink-0">
                    {(a.bytes / 1024).toFixed(1)}KB
                  </span>
                )}
              </li>
            ))}
          </ul>
        </div>
      )}

      {/* Failed: error message */}
      {error && (
        <div className="border-t border-red-200 bg-red-50 px-4 py-2">
          <p className="text-[11px] text-red-700">{error}</p>
        </div>
      )}
    </div>
  );
}
