import { useState } from 'react';
import { Grid2x2 } from 'lucide-react';
import { extractApiError } from '@/api/client';
import type { MitreTechnique, MitreTacticRef } from '@/api/types';
import { useUpdateSimulation } from '@/hooks/useSimulations';
import { useToast } from '@/hooks/useToast';
import { MitreTechniqueTag, MitreTacticTag } from './MitreTechniqueTag';
import { MitreTechniquePicker } from './MitreTechniquePicker';
import { MitreMatrixModal } from './MitreMatrixModal';
import type { MatrixSelection } from './MitreMatrixModal';

interface MitreTechniquesFieldProps {
  value: MitreTechnique[];
  tactics: MitreTacticRef[];
  simulationId: number;
  engagementId: number;
  disabled?: boolean;
}

export function MitreTechniquesField({
  value,
  tactics,
  simulationId,
  engagementId,
  disabled = false,
}: MitreTechniquesFieldProps): JSX.Element {
  const [showMatrix, setShowMatrix] = useState(false);
  const [showPicker, setShowPicker] = useState(false);

  const { push } = useToast();
  const updateMutation = useUpdateSimulation(simulationId, engagementId);

  const save = async (techniques: MitreTechnique[], nextTactics: MitreTacticRef[]) => {
    try {
      await updateMutation.mutateAsync({
        technique_ids: techniques.map((t) => t.id),
        tactic_ids: nextTactics.map((t) => t.id),
      });
      push('Techniques updated', 'success');
    } catch (err) {
      push(extractApiError(err, 'Could not update techniques'), 'error');
    }
  };

  const handleRemoveTechnique = (id: string) => {
    void save(value.filter((t) => t.id !== id), tactics);
  };

  const handleRemoveTactic = (id: string) => {
    void save(value, tactics.filter((t) => t.id !== id));
  };

  const handleSelect = (technique: MitreTechnique) => {
    if (value.some((t) => t.id === technique.id)) return;
    void save([...value, technique], tactics);
    setShowPicker(false);
  };

  const handleMatrixApply = ({ techniques, tactics: newTactics }: MatrixSelection) => {
    setShowMatrix(false);
    const merged = techniques.map((s) => {
      const existing = value.find((v) => v.id === s.id);
      return existing ?? s;
    });
    void save(merged, newTactics);
  };

  const isPending = updateMutation.isPending;
  const isEmpty = value.length === 0 && tactics.length === 0;

  return (
    <div className="flex flex-col gap-sm">
      {/* Chips area */}
      {isEmpty ? (
        <p className="text-[13px] text-graphite">No techniques selected</p>
      ) : (
        <div className="flex flex-wrap gap-xs" data-testid="techniques-tag-list">
          {tactics.map((t) => (
            <MitreTacticTag
              key={t.id}
              tactic={t}
              onRemove={() => handleRemoveTactic(t.id)}
              disabled={disabled || isPending}
            />
          ))}
          {value.map((t) => (
            <MitreTechniqueTag
              key={t.id}
              technique={t}
              onRemove={() => handleRemoveTechnique(t.id)}
              disabled={disabled || isPending}
            />
          ))}
        </div>
      )}

      {/* Input row — hidden in read-only mode */}
      {!disabled && (
        <div className="flex items-center gap-xs">
          <div className="flex-1 max-w-sm">
            {showPicker ? (
              <MitreTechniquePicker onSelect={handleSelect} disabled={isPending} />
            ) : (
              <button
                type="button"
                className="text-input h-9 text-[13px] text-graphite text-left cursor-text w-full"
                onClick={() => setShowPicker(true)}
                disabled={isPending}
              >
                Search technique (e.g. T1059)…
              </button>
            )}
          </div>
          <button
            type="button"
            aria-label="Open MITRE matrix"
            onClick={() => { setShowPicker(false); setShowMatrix(true); }}
            disabled={isPending}
            className="flex-shrink-0 flex items-center justify-center w-9 h-9 rounded-md border border-steel text-graphite hover:text-ink hover:border-ink transition-colors"
          >
            <Grid2x2 size={16} />
          </button>
          {isPending && <span className="text-[12px] text-graphite">Saving…</span>}
        </div>
      )}

      <MitreMatrixModal
        isOpen={showMatrix}
        initialTechniques={value}
        initialTactics={tactics}
        onApply={handleMatrixApply}
        onCancel={() => setShowMatrix(false)}
      />
    </div>
  );
}
