import { useParams, useNavigate } from "react-router-dom";
import MarkdownText from "../components/MarkdownText";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { useState, useEffect, useCallback } from "react";
import { Loader2, AlertCircle, ArrowLeft, BookOpen, X, CheckCircle } from "lucide-react";

import {
  getTestById,
  updateTestRed,
  updateTestBlue,
  startExecution,
  submitRedEvidence,
  submitBlueEvidence,
  startBlueWork,
  validateAsRedLead,
  validateAsBlueLead,
  reopenTest,
  pauseTimer,
  resumeTimer,
  holdTest,
  resumeTest,
  getTestTimeline,
  getRetestChain,
} from "../api/tests";
import { uploadEvidence, getEvidence } from "../api/evidence";
import { useAuth } from "../context/AuthContext";
import type { TestResult, ContainmentResult, TeamSide, TestTimelineEntry } from "../types/models";

import TestDetailHeader from "../components/test-detail/TestDetailHeader";
import TeamTabs from "../components/test-detail/TeamTabs";
import ValidationModal from "../components/test-detail/ValidationModal";
import ConfirmDialog from "../components/ConfirmDialog";
import JiraLinkPanel from "../components/JiraLinkPanel";
import TestPhaseTimeline from "../components/TestPhaseTimeline";
import { createTemplate } from "../api/test-templates";

// ── Helpers ────────────────────────────────────────────────────────

function isoToDatetimeLocal(iso: string | null): string {
  if (!iso) return "";
  return iso.replace("Z", "").replace(/\.\d+$/, "").slice(0, 16);
}

// ── Page Component ─────────────────────────────────────────────────

export default function TestDetailPage() {
  const { testId } = useParams<{ testId: string }>();
  const navigate = useNavigate();
  const queryClient = useQueryClient();
  const { user } = useAuth();

  // ── State ──────────────────────────────────────────────────────

  const [validationModal, setValidationModal] = useState<{
    open: boolean;
    side: "red" | "blue";
  }>({ open: false, side: "red" });

  const [confirmReopen, setConfirmReopen] = useState(false);
  const [holdModal, setHoldModal] = useState(false);
  const [holdReason, setHoldReason] = useState("");

  const [redDraft, setRedDraft] = useState({
    procedure_text: "",
    tool_used: "",
    attack_success: false,
    red_summary: "",
    execution_start_time: "",
    execution_end_time: "",
  });

  const [blueDraft, setBlueDraft] = useState<{
    detection_result: TestResult | "";
    containment_result: ContainmentResult | "";
    detection_time: string;
    containment_time: string;
    blue_summary: string;
  }>({
    detection_result: "",
    containment_result: "",
    detection_time: "",
    containment_time: "",
    blue_summary: "",
  });

  const [toast, setToast] = useState<{ message: string; type: "success" | "error" } | null>(null);
  const [showTemplateModal, setShowTemplateModal] = useState(false);

  // ── Queries ────────────────────────────────────────────────────

  const {
    data: test,
    isLoading,
    error,
  } = useQuery({
    queryKey: ["test", testId],
    queryFn: () => getTestById(testId!),
    enabled: !!testId,
  });

  const {
    data: timeline = [],
    isLoading: isTimelineLoading,
  } = useQuery({
    queryKey: ["test-timeline", testId],
    queryFn: () => getTestTimeline(testId!),
    enabled: !!testId,
  });

  const { data: retestChain = [] } = useQuery({
    queryKey: ["retest-chain", testId],
    queryFn: () => getRetestChain(testId!),
    enabled: !!testId && !!test && (test.retest_of !== null || test.retest_count > 0),
  });

  // Hydrate drafts from test data
  useEffect(() => {
    if (test) {
      setRedDraft({
        procedure_text: test.procedure_text || "",
        tool_used: test.tool_used || "",
        attack_success: test.attack_success ?? false,
        red_summary: test.red_summary || "",
        execution_start_time: isoToDatetimeLocal(test.execution_start_time),
        execution_end_time: isoToDatetimeLocal(test.execution_end_time),
      });
      setBlueDraft({
        detection_result: test.detection_result || "",
        containment_result: test.containment_result || "",
        detection_time: isoToDatetimeLocal(test.detection_time),
        containment_time: isoToDatetimeLocal(test.containment_time),
        blue_summary: test.blue_summary || "",
      });
    }
  }, [test]);

  // ── Toast helper ───────────────────────────────────────────────

  const showToast = useCallback((message: string, type: "success" | "error") => {
    setToast({ message, type });
    setTimeout(() => setToast(null), 5000);
  }, []);

  /** Extract a user-friendly error message from Axios or generic errors. */
  const extractError = useCallback((err: unknown): string => {
    if (err && typeof err === "object" && "response" in err) {
      const resp = (err as { response?: { data?: { detail?: string | { message?: string } } } }).response;
      const detail = resp?.data?.detail;
      if (typeof detail === "string") return detail;
      if (detail && typeof detail === "object" && "message" in detail) return (detail as { message: string }).message;
    }
    if (err instanceof Error) return err.message;
    return "An unexpected error occurred";
  }, []);

  const invalidateAll = useCallback(() => {
    queryClient.invalidateQueries({ queryKey: ["test", testId] });
    queryClient.invalidateQueries({ queryKey: ["test-timeline", testId] });
    queryClient.invalidateQueries({ queryKey: ["techniques"] });
  }, [queryClient, testId]);

  // ── Mutations ──────────────────────────────────────────────────

  // Red field save (auto-save on blur would come later; for now Save button or transitions)
  const saveRedMutation = useMutation({
    mutationFn: () =>
      updateTestRed(testId!, {
        procedure_text: redDraft.procedure_text || undefined,
        tool_used: redDraft.tool_used || undefined,
        attack_success: redDraft.attack_success,
        red_summary: redDraft.red_summary || undefined,
        execution_start_time: redDraft.execution_start_time || undefined,
        execution_end_time: redDraft.execution_end_time || undefined,
      }),
    onSuccess: () => {
      invalidateAll();
      showToast("Red Team fields saved", "success");
    },
    onError: (err: unknown) => showToast(extractError(err), "error"),
  });

  const saveBlueMutation = useMutation({
    mutationFn: () =>
      updateTestBlue(testId!, {
        detection_result: (blueDraft.detection_result as TestResult) || undefined,
        containment_result: (blueDraft.containment_result as ContainmentResult) || undefined,
        detection_time: blueDraft.detection_time || undefined,
        containment_time: blueDraft.containment_time || undefined,
        blue_summary: blueDraft.blue_summary || undefined,
      }),
    onSuccess: () => {
      invalidateAll();
      showToast("Blue Team fields saved", "success");
    },
    onError: (err: unknown) => showToast(extractError(err), "error"),
  });

  // State transitions
  const startExecMutation = useMutation({
    mutationFn: () => startExecution(testId!),
    onSuccess: () => {
      invalidateAll();
      showToast("Test execution started", "success");
    },
    onError: (err: unknown) => showToast(extractError(err), "error"),
  });

  const submitRedMutation = useMutation({
    mutationFn: () => submitRedEvidence(testId!),
    onSuccess: () => {
      invalidateAll();
      showToast("Submitted to Blue Team", "success");
    },
    onError: (err: unknown) => showToast(extractError(err), "error"),
  });

  const submitBlueMutation = useMutation({
    mutationFn: () => submitBlueEvidence(testId!),
    onSuccess: () => {
      invalidateAll();
      showToast("Submitted for review", "success");
    },
    onError: (err: unknown) => showToast(extractError(err), "error"),
  });

  const startBlueWorkMutation = useMutation({
    mutationFn: () => startBlueWork(testId!),
    onSuccess: () => {
      invalidateAll();
      showToast("Blue evaluation started", "success");
    },
    onError: (err: unknown) => showToast(extractError(err), "error"),
  });

  const validateRedLeadMutation = useMutation({
    mutationFn: (payload: { red_validation_status: "approved" | "rejected"; red_validation_notes?: string }) =>
      validateAsRedLead(testId!, payload),
    onSuccess: () => {
      invalidateAll();
      setValidationModal({ open: false, side: "red" });
      showToast("Red Lead validation submitted", "success");
    },
    onError: (err: unknown) => showToast(extractError(err), "error"),
  });

  const validateBlueLeadMutation = useMutation({
    mutationFn: (payload: { blue_validation_status: "approved" | "rejected"; blue_validation_notes?: string }) =>
      validateAsBlueLead(testId!, payload),
    onSuccess: () => {
      invalidateAll();
      setValidationModal({ open: false, side: "blue" });
      showToast("Blue Lead validation submitted", "success");
    },
    onError: (err: unknown) => showToast(extractError(err), "error"),
  });

  const reopenMutation = useMutation({
    mutationFn: () => reopenTest(testId!),
    onSuccess: () => {
      invalidateAll();
      setConfirmReopen(false);
      showToast("Test returned to Draft — address the feedback and resubmit", "success");
    },
    onError: (err: unknown) => {
      setConfirmReopen(false);
      showToast(extractError(err), "error");
    },
  });

  // Timer pause/resume
  const pauseTimerMutation = useMutation({
    mutationFn: () => pauseTimer(testId!),
    onSuccess: () => {
      invalidateAll();
      showToast("Timer paused", "success");
    },
    onError: (err: unknown) => showToast(extractError(err), "error"),
  });

  const resumeTimerMutation = useMutation({
    mutationFn: () => resumeTimer(testId!),
    onSuccess: () => {
      invalidateAll();
      showToast("Timer resumed", "success");
    },
    onError: (err: unknown) => showToast(extractError(err), "error"),
  });

  const holdMutation = useMutation({
    mutationFn: (reason: string) => holdTest(testId!, reason),
    onSuccess: () => {
      invalidateAll();
      setHoldModal(false);
      setHoldReason("");
      showToast("Test placed on hold", "success");
    },
    onError: (err: unknown) => showToast(extractError(err), "error"),
  });

  const resumeHoldMutation = useMutation({
    mutationFn: () => resumeTest(testId!),
    onSuccess: () => {
      invalidateAll();
      showToast("Test resumed", "success");
    },
    onError: (err: unknown) => showToast(extractError(err), "error"),
  });

  // Evidence upload
  const uploadMutation = useMutation({
    mutationFn: ({ file, team }: { file: File; team: TeamSide }) =>
      uploadEvidence(testId!, file, team),
    onSuccess: () => {
      invalidateAll();
      showToast("Evidence uploaded", "success");
    },
    onError: (err: unknown) => showToast(extractError(err), "error"),
  });

  // ── Handlers ───────────────────────────────────────────────────

  const handleDownload = async (evidenceId: string) => {
    try {
      const ev = await getEvidence(evidenceId);
      if (ev.download_url) {
        window.open(ev.download_url, "_blank");
      }
    } catch (err) {
      console.error("Failed to get download URL:", err);
    }
  };

  const handleRedFieldChange = (field: string, value: string | boolean) => {
    setRedDraft((prev) => ({ ...prev, [field]: value }));
  };

  const handleBlueFieldChange = (field: string, value: string) => {
    setBlueDraft((prev) => ({ ...prev, [field]: value }));
  };

  const handleUploadEvidence = async (file: File, team: TeamSide) => {
    await uploadMutation.mutateAsync({ file, team });
  };

  const handleValidationSubmit = (
    side: "red" | "blue",
    status: "approved" | "rejected",
    notes: string,
  ) => {
    if (side === "red") {
      validateRedLeadMutation.mutate({
        red_validation_status: status,
        red_validation_notes: notes || undefined,
      });
    } else {
      validateBlueLeadMutation.mutate({
        blue_validation_status: status,
        blue_validation_notes: notes || undefined,
      });
    }
  };

  const isTransitioning =
    startExecMutation.isPending ||
    submitRedMutation.isPending ||
    submitBlueMutation.isPending ||
    startBlueWorkMutation.isPending ||
    reopenMutation.isPending;

  // ── Loading / Error states ─────────────────────────────────────

  if (isLoading) {
    return (
      <div className="flex h-64 items-center justify-center">
        <Loader2 className="h-8 w-8 animate-spin text-cyan-400" />
      </div>
    );
  }

  if (error || !test) {
    return (
      <div className="flex h-64 flex-col items-center justify-center gap-2">
        <AlertCircle className="h-10 w-10 text-red-400" />
        <p className="text-red-400">Failed to load test</p>
        <button
          onClick={() => navigate("/tests")}
          className="mt-2 flex items-center gap-1 text-sm text-cyan-400 hover:underline"
        >
          <ArrowLeft className="h-4 w-4" />
          Back to tests
        </button>
      </div>
    );
  }

  const formatDate = (dateStr: string | null) => {
    if (!dateStr) return "\u2014";
    return new Date(dateStr).toLocaleDateString("en-US", {
      year: "numeric",
      month: "short",
      day: "numeric",
      hour: "2-digit",
      minute: "2-digit",
    });
  };

  const role = user?.role ?? "";
  const canSaveRed =
    (test.state === "draft" || test.state === "red_executing") &&
    (role === "red_tech" || role === "red_lead" || role === "admin");
  const canSaveBlue =
    test.state === "blue_evaluating" &&
    (role === "blue_tech" || role === "blue_lead" || role === "admin");

  // Only leads and admins can create templates
  const canSaveAsTemplate =
    role === "red_lead" || role === "blue_lead" || role === "admin";

  // ── Render ─────────────────────────────────────────────────────

  return (
    <div className="space-y-6">
      {/* Back button */}
      <button
        onClick={() => navigate(-1)}
        className="flex items-center gap-1 text-sm text-gray-400 hover:text-cyan-400 transition-colors"
      >
        <ArrowLeft className="h-4 w-4" />
        Back
      </button>

      {/* Header with progress bar and actions */}
      <TestDetailHeader
        test={test}
        user={user}
        isTransitioning={isTransitioning}
        onStartExecution={() => startExecMutation.mutate()}
        onSubmitRed={() => submitRedMutation.mutate()}
        onSubmitBlue={() => submitBlueMutation.mutate()}
        onStartBlueWork={() => startBlueWorkMutation.mutate()}
        onOpenValidateModal={(side) => setValidationModal({ open: true, side })}
        onReopen={() => setConfirmReopen(true)}
        onPauseTimer={() => pauseTimerMutation.mutate()}
        onResumeTimer={() => resumeTimerMutation.mutate()}
        isTogglingTimer={pauseTimerMutation.isPending || resumeTimerMutation.isPending}
        onHold={() => setHoldModal(true)}
        onResume={() => resumeHoldMutation.mutate()}
        isTogglingHold={holdMutation.isPending || resumeHoldMutation.isPending}
      />

      {/* Content: Tabs + Sidebar */}
      <div className="grid gap-6 lg:grid-cols-3">
        {/* Main: Team Tabs */}
        <div className="lg:col-span-2 space-y-4">
          <TeamTabs
            test={test}
            user={user}
            timeline={timeline}
            isTimelineLoading={isTimelineLoading}
            onRedFieldChange={handleRedFieldChange}
            redDraft={redDraft}
            onBlueFieldChange={handleBlueFieldChange}
            blueDraft={blueDraft}
            onUploadEvidence={handleUploadEvidence}
            isUploading={uploadMutation.isPending}
            onDownloadEvidence={handleDownload}
          />

          {/* Save buttons */}
          {(canSaveRed || canSaveBlue) && (
            <div className="flex justify-end gap-3">
              {canSaveRed && (
                <button
                  onClick={() => {
                    if (!redDraft.execution_start_time) { showToast("Execution Start time is required", "error"); return; }
                    if (!redDraft.execution_end_time) { showToast("Execution End time is required", "error"); return; }
                    saveRedMutation.mutate();
                  }}
                  disabled={saveRedMutation.isPending}
                  className="flex items-center gap-1.5 rounded-lg bg-orange-600 px-4 py-2 text-sm font-medium text-white hover:bg-orange-500 disabled:opacity-50 transition-colors"
                >
                  {saveRedMutation.isPending && <Loader2 className="h-4 w-4 animate-spin" />}
                  Save Red Team Fields
                </button>
              )}
              {canSaveBlue && (
                <button
                  onClick={() => {
                    const isDetected = blueDraft.detection_result === "detected" || blueDraft.detection_result === "partially_detected";
                    if (isDetected && !blueDraft.detection_time) { showToast("Detection Time is required", "error"); return; }
                    if (isDetected && !blueDraft.containment_time) { showToast("Containment Time is required", "error"); return; }
                    saveBlueMutation.mutate();
                  }}
                  disabled={saveBlueMutation.isPending}
                  className="flex items-center gap-1.5 rounded-lg bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-500 disabled:opacity-50 transition-colors"
                >
                  {saveBlueMutation.isPending && <Loader2 className="h-4 w-4 animate-spin" />}
                  Save Blue Team Fields
                </button>
              )}
            </div>
          )}
        </div>

        {/* Sidebar: Metadata */}
        <div className="space-y-6">
          <div className="rounded-xl border border-gray-800 bg-gray-900 p-6">
            <h2 className="mb-4 text-lg font-semibold text-white">Details</h2>
            <dl className="space-y-4">
              {test.technique_mitre_id && (
                <div>
                  <dt className="text-xs font-medium uppercase text-gray-500">Technique</dt>
                  <dd className="mt-1">
                    <button
                      onClick={() => navigate(`/techniques/${test.technique_mitre_id}`)}
                      className="flex items-start gap-1.5 text-left group"
                    >
                      <span className="font-mono text-xs text-cyan-400 shrink-0 group-hover:underline">
                        {test.technique_mitre_id}
                      </span>
                      {test.technique_name && (
                        <span className="text-xs text-gray-400 group-hover:text-gray-300 transition-colors">
                          \u2014 {test.technique_name}
                        </span>
                      )}
                    </button>
                  </dd>
                </div>
              )}
              <div>
                <dt className="text-xs font-medium uppercase text-gray-500">Description</dt>
                <dd className="mt-1">
                  <MarkdownText content={test.description || "\u2014"} className="text-sm text-gray-300" />
                </dd>
              </div>
              <div>
                <dt className="text-xs font-medium uppercase text-gray-500">Platform</dt>
                <dd className="mt-1 text-sm text-gray-300 capitalize">
                  {test.platform || "\u2014"}
                </dd>
              </div>
              <div>
                <dt className="text-xs font-medium uppercase text-gray-500">Creator</dt>
                <dd className="mt-1 text-sm text-gray-300">
                  {test.created_by || "\u2014"}
                </dd>
              </div>
              <div>
                <dt className="text-xs font-medium uppercase text-gray-500">Created</dt>
                <dd className="mt-1 text-sm text-gray-300">
                  {formatDate(test.created_at)}
                </dd>
              </div>
              <div>
                <dt className="text-xs font-medium uppercase text-gray-500">Execution Date</dt>
                <dd className="mt-1 text-sm text-gray-300">
                  {formatDate(test.execution_date)}
                </dd>
              </div>
              {test.red_validated_at && (
                <div>
                  <dt className="text-xs font-medium uppercase text-gray-500">Red Validated</dt>
                  <dd className="mt-1 text-sm text-gray-300">
                    {formatDate(test.red_validated_at)}
                  </dd>
                </div>
              )}
              {test.blue_validated_at && (
                <div>
                  <dt className="text-xs font-medium uppercase text-gray-500">Blue Validated</dt>
                  <dd className="mt-1 text-sm text-gray-300">
                    {formatDate(test.blue_validated_at)}
                  </dd>
                </div>
              )}
            </dl>

            {canSaveAsTemplate && (
              <div className="mt-4 border-t border-gray-800 pt-4">
                <button
                  onClick={() => setShowTemplateModal(true)}
                  className="flex w-full items-center justify-center gap-2 rounded-lg border border-cyan-500/30 bg-cyan-500/10 px-3 py-2 text-xs font-medium text-cyan-400 hover:bg-cyan-500/20 transition-colors"
                >
                  <BookOpen className="h-3.5 w-3.5" />
                  Save as Template
                </button>
              </div>
            )}
          </div>

          {/* Retest Chain */}
          {(test.retest_of || test.retest_count > 0 || retestChain.length > 1) && (
            <div className="rounded-xl border border-gray-800 bg-gray-900 p-6">
              <h2 className="mb-4 text-lg font-semibold text-white">Retest Chain</h2>
              {test.retest_of && (
                <div className="mb-3">
                  <span className="text-xs font-medium uppercase text-gray-500">
                    Retest {test.retest_count} / 3
                  </span>
                  <div className="mt-1 h-2 w-full rounded-full bg-gray-800 overflow-hidden">
                    <div
                      className="h-full rounded-full bg-cyan-500 transition-all"
                      style={{ width: `${(test.retest_count / 3) * 100}%` }}
                    />
                  </div>
                </div>
              )}
              <div className="space-y-2">
                {retestChain.map((entry) => (
                  <button
                    key={entry.id}
                    onClick={() => entry.id !== testId && navigate(`/tests/${entry.id}`)}
                    className={`flex w-full items-center justify-between rounded-lg border px-3 py-2 text-left text-sm transition-colors ${
                      entry.id === testId
                        ? "border-cyan-500/30 bg-cyan-900/30 text-cyan-400"
                        : "border-gray-700 bg-gray-800/50 text-gray-300 hover:border-cyan-500/30 hover:text-cyan-400"
                    }`}
                  >
                    <div className="flex items-center gap-2 truncate">
                      <span className="truncate text-xs">
                        {entry.retest_of ? `#${entry.retest_count}` : "Original"}
                      </span>
                      <span className="truncate">{entry.name}</span>
                    </div>
                    <span className={`shrink-0 rounded-full px-2 py-0.5 text-xs ${
                      entry.state === "validated"
                        ? "bg-green-900/50 text-green-400"
                        : entry.state === "rejected"
                          ? "bg-red-900/50 text-red-400"
                          : "bg-gray-800/50 text-gray-500"
                    }`}>
                      {entry.state || "draft"}
                    </span>
                  </button>
                ))}
              </div>
            </div>
          )}

          {/* Jira Integration */}
          <JiraLinkPanel entityType="test" entityId={testId!} readOnly label={test.name} />

          {/* Phase Timeline (read-only, with Tempo sync) */}
          <TestPhaseTimeline test={test} testId={testId} />
        </div>
      </div>

      {/* On Hold Modal */}
      {holdModal && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm">
          <div className="w-full max-w-md rounded-xl border border-amber-500/30 bg-gray-900 p-6 shadow-2xl">
            <div className="mb-4 flex items-center justify-between">
              <h2 className="text-lg font-semibold text-amber-300">Place Test On Hold</h2>
              <button
                onClick={() => { setHoldModal(false); setHoldReason(""); }}
                className="text-gray-400 hover:text-white transition-colors"
              >
                <X className="h-5 w-5" />
              </button>
            </div>
            <p className="mb-4 text-sm text-gray-400">
              Provide a reason for placing this test on hold. This will be sent as a comment to the linked Jira ticket and the ticket will be transitioned to <span className="text-amber-400 font-medium">On Hold</span>.
            </p>
            <textarea
              value={holdReason}
              onChange={(e) => setHoldReason(e.target.value)}
              placeholder="e.g. Assigned to another project until next sprint..."
              rows={4}
              className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-gray-200 placeholder-gray-500 focus:border-amber-500 focus:outline-none resize-none"
            />
            <div className="mt-4 flex justify-end gap-3">
              <button
                onClick={() => { setHoldModal(false); setHoldReason(""); }}
                className="rounded-lg border border-gray-700 px-4 py-2 text-sm text-gray-300 hover:border-gray-600 transition-colors"
              >
                Cancel
              </button>
              <button
                onClick={() => holdMutation.mutate(holdReason)}
                disabled={!holdReason.trim() || holdMutation.isPending}
                className="flex items-center gap-1.5 rounded-lg bg-amber-600 px-4 py-2 text-sm font-medium text-white hover:bg-amber-500 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
              >
                {holdMutation.isPending ? <Loader2 className="h-4 w-4 animate-spin" /> : null}
                Confirm On Hold
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Confirm Reopen Dialog */}
      <ConfirmDialog
        open={confirmReopen}
        title="Continue Test"
        message="The test will return to Draft so you can address the rejection feedback. All content is preserved — procedure, summaries, evidences and rejection notes. Only the validation decisions are cleared so leads can re-validate the updated submission."
        confirmLabel="Continue"
        variant="warning"
        isLoading={reopenMutation.isPending}
        onConfirm={() => reopenMutation.mutate()}
        onCancel={() => setConfirmReopen(false)}
      />

      {/* Validation Modal */}
      {validationModal.open && (
        <ValidationModal
          side={validationModal.side}
          test={test}
          isSubmitting={
            validationModal.side === "red"
              ? validateRedLeadMutation.isPending
              : validateBlueLeadMutation.isPending
          }
          onSubmit={(status, notes) =>
            handleValidationSubmit(validationModal.side, status, notes)
          }
          onClose={() => setValidationModal({ open: false, side: "red" })}
        />
      )}

      {/* Save as Template Modal */}
      {showTemplateModal && (
        <SaveAsTemplateModal
          test={test}
          onClose={() => setShowTemplateModal(false)}
          onSaved={() => {
            setShowTemplateModal(false);
            showToast("Template created successfully", "success");
          }}
        />
      )}

      {/* Toast notification */}
      {toast && (
        <div
          className={`fixed bottom-6 right-6 z-50 rounded-lg border px-4 py-3 text-sm shadow-lg backdrop-blur transition-all ${
            toast.type === "success"
              ? "border-green-500/30 bg-green-900/90 text-green-300"
              : "border-red-500/30 bg-red-900/90 text-red-300"
          }`}
        >
          {toast.message}
        </div>
      )}
    </div>
  );
}

/* ── SaveAsTemplateModal ───────────────────────────────────────────────
   Pre-fills template fields from an existing test.
   Lets the user review / tweak before saving.
   ────────────────────────────────────────────────────────────────── */
function SaveAsTemplateModal({
  test,
  onClose,
  onSaved,
}: {
  test: { name: string; description: string | null; platform: string | null; procedure_text: string | null; tool_used: string | null; technique_mitre_id: string | null; technique_name?: string | null };
  onClose: () => void;
  onSaved: () => void;
}) {
  const [name, setName] = useState(test.name);
  const [description, setDescription] = useState(test.description ?? "");
  const [platform, setPlatform] = useState(test.platform ?? "");
  const [attackProcedure, setAttackProcedure] = useState(test.procedure_text ?? "");
  const [toolSuggested, setToolSuggested] = useState(test.tool_used ?? "");
  const [expectedDetection, setExpectedDetection] = useState("");
  const [severity, setSeverity] = useState("medium");

  const saveMutation = useMutation({
    mutationFn: () =>
      createTemplate({
        mitre_technique_id: test.technique_mitre_id ?? "",
        name: name.trim(),
        description: description.trim() || undefined,
        platform: platform.trim() || undefined,
        attack_procedure: attackProcedure.trim() || undefined,
        tool_suggested: toolSuggested.trim() || undefined,
        expected_detection: expectedDetection.trim() || undefined,
        severity: severity || undefined,
        source: "custom",
      }),
    onSuccess: () => onSaved(),
  });

  const canSubmit = name.trim().length > 0 && !!test.technique_mitre_id;

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm">
      <div className="max-h-[90vh] w-full max-w-2xl overflow-y-auto rounded-xl border border-gray-700 bg-gray-900 shadow-2xl">
        {/* Header */}
        <div className="sticky top-0 z-10 flex items-center justify-between border-b border-gray-800 bg-gray-900 px-6 py-4">
          <div className="flex items-center gap-2">
            <BookOpen className="h-5 w-5 text-cyan-400" />
            <h3 className="text-lg font-semibold text-white">Save as Template</h3>
          </div>
          <button onClick={onClose} className="rounded p-1 text-gray-400 hover:bg-gray-800 hover:text-white">
            <X className="h-5 w-5" />
          </button>
        </div>

        {/* Body */}
        <div className="space-y-4 px-6 py-5">
          {/* Technique info banner */}
          <div className="rounded-lg border border-cyan-500/20 bg-cyan-900/10 px-4 py-2.5 text-xs text-cyan-400">
            Technique:{" "}
            <span className="font-mono font-semibold">{test.technique_mitre_id}</span>
            {test.technique_name && (
              <span className="ml-2 text-gray-400">{test.technique_name}</span>
            )}
          </div>

          {/* Name */}
          <div>
            <label className="mb-1.5 block text-sm font-medium text-gray-300">
              Template Name <span className="text-red-400">*</span>
            </label>
            <input
              value={name}
              onChange={(e) => setName(e.target.value)}
              className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-gray-200 placeholder-gray-500 focus:border-cyan-500 focus:outline-none"
              placeholder="Template name"
            />
          </div>

          {/* Platform + Severity row */}
          <div className="grid gap-4 sm:grid-cols-2">
            <div>
              <label className="mb-1.5 block text-sm font-medium text-gray-300">Platform</label>
              <input
                value={platform}
                onChange={(e) => setPlatform(e.target.value)}
                className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-gray-200 placeholder-gray-500 focus:border-cyan-500 focus:outline-none"
                placeholder="windows, linux, macos…"
              />
            </div>
            <div>
              <label className="mb-1.5 block text-sm font-medium text-gray-300">Severity</label>
              <select
                value={severity}
                onChange={(e) => setSeverity(e.target.value)}
                className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-gray-200 focus:border-cyan-500 focus:outline-none"
              >
                <option value="low">Low</option>
                <option value="medium">Medium</option>
                <option value="high">High</option>
                <option value="critical">Critical</option>
              </select>
            </div>
          </div>

          {/* Description */}
          <div>
            <label className="mb-1.5 block text-sm font-medium text-gray-300">Description</label>
            <textarea
              value={description}
              onChange={(e) => setDescription(e.target.value)}
              rows={2}
              className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-gray-200 placeholder-gray-500 focus:border-cyan-500 focus:outline-none"
              placeholder="What does this template test?"
            />
          </div>

          {/* Attack Procedure */}
          <div>
            <label className="mb-1.5 block text-sm font-medium text-gray-300">Attack Procedure</label>
            <textarea
              value={attackProcedure}
              onChange={(e) => setAttackProcedure(e.target.value)}
              rows={5}
              className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 font-mono text-sm text-gray-200 placeholder-gray-500 focus:border-cyan-500 focus:outline-none"
              placeholder="Steps to execute the attack…"
            />
          </div>

          {/* Tool */}
          <div>
            <label className="mb-1.5 block text-sm font-medium text-gray-300">Suggested Tool</label>
            <input
              value={toolSuggested}
              onChange={(e) => setToolSuggested(e.target.value)}
              className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-gray-200 placeholder-gray-500 focus:border-cyan-500 focus:outline-none"
              placeholder="e.g. Atomic Red Team, Cobalt Strike"
            />
          </div>

          {/* Expected Detection (new — not in the test) */}
          <div>
            <label className="mb-1.5 block text-sm font-medium text-gray-300">
              Expected Detection
              <span className="ml-2 text-xs text-gray-500">(guidance for Blue Team)</span>
            </label>
            <textarea
              value={expectedDetection}
              onChange={(e) => setExpectedDetection(e.target.value)}
              rows={3}
              className="w-full rounded-lg border border-gray-700 bg-gray-800 px-3 py-2 text-sm text-gray-200 placeholder-gray-500 focus:border-cyan-500 focus:outline-none"
              placeholder="What alerts or logs should Blue Team look for?"
            />
          </div>

          {/* Error */}
          {saveMutation.isError && (
            <div className="rounded-lg border border-red-500/30 bg-red-900/20 p-3 text-sm text-red-400">
              {(saveMutation.error as Error)?.message || "Failed to create template"}
            </div>
          )}
        </div>

        {/* Footer */}
        <div className="sticky bottom-0 flex justify-end gap-3 border-t border-gray-800 bg-gray-900 px-6 py-4">
          <button
            onClick={onClose}
            className="rounded-lg border border-gray-700 px-4 py-2 text-sm text-gray-400 hover:bg-gray-800"
          >
            Cancel
          </button>
          <button
            onClick={() => saveMutation.mutate()}
            disabled={!canSubmit || saveMutation.isPending}
            className="flex items-center gap-1.5 rounded-lg bg-cyan-600 px-4 py-2 text-sm font-medium text-white hover:bg-cyan-500 disabled:opacity-50 transition-colors"
          >
            {saveMutation.isPending ? (
              <Loader2 className="h-4 w-4 animate-spin" />
            ) : (
              <CheckCircle className="h-4 w-4" />
            )}
            Save Template
          </button>
        </div>
      </div>
    </div>
  );
}
