import { useEffect, useRef, useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { ChevronDown, Plus } from 'lucide-react';
import { extractApiError } from '@/api/client';
import type { SimulationTemplate } from '@/api/types';
import { useAuth } from '@/hooks/useAuth';
import { useEngagementSimulations, useCreateSimulation } from '@/hooks/useSimulations';
import { useToast } from '@/hooks/useToast';
import { LoadingState } from './LoadingState';
import { ErrorState } from './ErrorState';
import { EmptyState } from './EmptyState';
import { SimulationStatusBadge } from './SimulationStatusBadge';
import { TemplatePickerModal } from './TemplatePickerModal';

interface SimulationListProps {
  engagementId: number;
}

function formatDate(value: string | null): string {
  if (!value) return '—';
  return value.replace('T', ' ').slice(0, 16);
}

function NewSimulationDropdown({ engagementId }: { engagementId: number }): JSX.Element {
  const navigate = useNavigate();
  const { push } = useToast();
  const [open, setOpen] = useState(false);
  const [showPicker, setShowPicker] = useState(false);
  const ref = useRef<HTMLDivElement>(null);
  const createMutation = useCreateSimulation(engagementId);

  useEffect(() => {
    if (!open) return;
    const onPointerDown = (e: PointerEvent) => {
      if (ref.current && !ref.current.contains(e.target as Node)) {
        setOpen(false);
      }
    };
    const onKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') setOpen(false);
    };
    document.addEventListener('pointerdown', onPointerDown);
    document.addEventListener('keydown', onKeyDown);
    return () => {
      document.removeEventListener('pointerdown', onPointerDown);
      document.removeEventListener('keydown', onKeyDown);
    };
  }, [open]);

  const handleBlank = () => {
    setOpen(false);
    navigate(`/engagements/${engagementId}/simulations/new`);
  };

  const handleFromTemplate = () => {
    setOpen(false);
    setShowPicker(true);
  };

  const handleSelectTemplate = async (template: SimulationTemplate) => {
    try {
      const sim = await createMutation.mutateAsync({ name: template.name, template_id: template.id });
      setShowPicker(false);
      push(`Created "${sim.name}" from template`, 'success');
      navigate(`/engagements/${engagementId}/simulations/${sim.id}/edit`);
    } catch (err) {
      push(extractApiError(err, 'Could not create simulation from template'), 'error');
    }
  };

  return (
    <div className="relative" ref={ref}>
      <div className="inline-flex">
        <button
          type="button"
          className="btn-primary rounded-r-none border-r border-primary-deep"
          onClick={handleBlank}
          data-testid="new-simulation-btn"
        >
          <Plus size={14} aria-hidden /> New
        </button>
        <button
          type="button"
          aria-label="More options"
          aria-expanded={open}
          className="btn-primary rounded-l-none px-sm"
          onClick={() => setOpen((v) => !v)}
          data-testid="new-simulation-dropdown-toggle"
        >
          <ChevronDown size={14} aria-hidden />
        </button>
      </div>

      {open ? (
        <div
          className="absolute right-0 top-full mt-xxs bg-canvas border border-hairline rounded-md shadow-floating dark:shadow-floating-dark z-20 min-w-[180px]"
          role="menu"
        >
          <button
            type="button"
            role="menuitem"
            className="w-full text-left px-md py-sm text-[14px] text-ink hover:bg-cloud dark:hover:bg-fog"
            onClick={handleBlank}
          >
            Blank
          </button>
          <button
            type="button"
            role="menuitem"
            className="w-full text-left px-md py-sm text-[14px] text-ink hover:bg-cloud dark:hover:bg-fog"
            onClick={handleFromTemplate}
            data-testid="from-template-btn"
          >
            From template…
          </button>
        </div>
      ) : null}

      {showPicker ? (
        <TemplatePickerModal
          engagementId={engagementId}
          onClose={() => setShowPicker(false)}
          onInstantiated={(simId) => {
            setShowPicker(false);
            navigate(`/engagements/${engagementId}/simulations/${simId}/edit`);
          }}
          onSelectTemplate={handleSelectTemplate}
          isPending={createMutation.isPending}
        />
      ) : null}
    </div>
  );
}

export function SimulationList({ engagementId }: SimulationListProps): JSX.Element {
  const { data, isLoading, isError, error, refetch } = useEngagementSimulations(engagementId);
  const { canEditEngagements } = useAuth();
  const navigate = useNavigate();

  if (isLoading) return <LoadingState label="Loading simulations…" />;

  if (isError) {
    return (
      <ErrorState
        message={extractApiError(error, 'Could not load simulations')}
        onRetry={() => refetch()}
      />
    );
  }

  if (!data || data.length === 0) {
    return (
      <EmptyState
        title="No simulations yet"
        description="Create the first simulation to start tracking red team tests."
        action={
          canEditEngagements ? (
            <NewSimulationDropdown engagementId={engagementId} />
          ) : undefined
        }
      />
    );
  }

  return (
    <div className="flex flex-col gap-md">
      <div className="flex items-center justify-between">
        <h2 className="text-[24px] font-medium text-ink">Simulations</h2>
        {canEditEngagements ? (
          <NewSimulationDropdown engagementId={engagementId} />
        ) : null}
      </div>

      <div className="card-product overflow-hidden p-0">
        <table className="w-full text-left">
          <thead className="bg-cloud border-b border-hairline">
            <tr className="text-[12px] uppercase tracking-[0.5px] text-graphite">
              <th className="px-xl py-md">Name</th>
              <th className="px-xl py-md">MITRE</th>
              <th className="px-xl py-md">Status</th>
              <th className="px-xl py-md">Executed at</th>
            </tr>
          </thead>
          <tbody>
            {data.map((sim) => (
              <tr
                key={sim.id}
                className="border-b border-hairline last:border-0 hover:bg-cloud cursor-pointer"
                onClick={() =>
                  navigate(`/engagements/${engagementId}/simulations/${sim.id}/edit`)
                }
              >
                <td className="px-xl py-md">
                  <Link
                    to={`/engagements/${engagementId}/simulations/${sim.id}/edit`}
                    className="text-ink font-medium hover:underline"
                    onClick={(e) => e.stopPropagation()}
                  >
                    {sim.name}
                  </Link>
                </td>
                <td className="px-xl py-md text-charcoal text-[14px]">
                  {(() => {
                    const items = [
                      ...(sim.tactics ?? []).map((t) => t.id),
                      ...sim.techniques.map((t) => t.id),
                    ];
                    if (items.length === 0) return '—';
                    if (items.length === 1) return items[0];
                    return `${items[0]} +${items.length - 1}`;
                  })()}
                </td>
                <td className="px-xl py-md">
                  <SimulationStatusBadge status={sim.status} />
                </td>
                <td className="px-xl py-md text-charcoal text-[14px]">
                  {formatDate(sim.executed_at)}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}
