import { useEffect, useState, type FormEvent } from 'react';
import { Link, useNavigate, useParams } from 'react-router-dom';
import { extractApiError } from '@/api/client';
import type { SimulationPatchInput } from '@/api/types';
import { useAuth } from '@/hooks/useAuth';
import { useToast } from '@/hooks/useToast';
import {
  useCreateSimulation,
  useDeleteSimulation,
  useSimulation,
  useTransitionSimulation,
  useUpdateSimulation,
} from '@/hooks/useSimulations';
import { FormField, TextArea, TextInput } from '@/components/FormField';
import { LoadingState } from '@/components/LoadingState';
import { ErrorState } from '@/components/ErrorState';
import { SimulationStatusBadge } from '@/components/SimulationStatusBadge';
import { ConfirmDialog } from '@/components/ConfirmDialog';
import { MitreTechniquePicker } from '@/components/MitreTechniquePicker';

interface RedteamFormState {
  name: string;
  mitre_technique_id: string | null;
  mitre_technique_name: string | null;
  description: string;
  commands: string;
  prerequisites: string;
  executed_at: string;
  execution_result: string;
}

interface SocFormState {
  log_source: string;
  logs: string;
  soc_comment: string;
  incident_number: string;
}

const EMPTY_RT: RedteamFormState = {
  name: '',
  mitre_technique_id: null,
  mitre_technique_name: null,
  description: '',
  commands: '',
  prerequisites: '',
  executed_at: '',
  execution_result: '',
};

const EMPTY_SOC: SocFormState = {
  log_source: '',
  logs: '',
  soc_comment: '',
  incident_number: '',
};

export function SimulationFormPage(): JSX.Element {
  const { eid, sid } = useParams<{ eid: string; sid: string }>();
  const engagementId = eid ? Number(eid) : undefined;
  const simulationId = sid ? Number(sid) : undefined;
  const isNew = !simulationId;

  const navigate = useNavigate();
  const { push } = useToast();
  const { isAdmin, isRedteam, isSoc, canEditEngagements } = useAuth();

  const detail = useSimulation(isNew ? undefined : simulationId);
  const createMutation = useCreateSimulation(engagementId ?? 0);
  const updateMutation = useUpdateSimulation(simulationId ?? 0, engagementId ?? 0);
  const deleteMutation = useDeleteSimulation(engagementId ?? 0);
  const transitionMutation = useTransitionSimulation(simulationId ?? 0, engagementId ?? 0);

  const [rt, setRt] = useState<RedteamFormState>(EMPTY_RT);
  const [soc, setSoc] = useState<SocFormState>(EMPTY_SOC);
  const [nameError, setNameError] = useState<string | null>(null);
  const [submitError, setSubmitError] = useState<string | null>(null);
  const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);

  useEffect(() => {
    if (!isNew && detail.data) {
      const s = detail.data;
      setRt({
        name: s.name,
        mitre_technique_id: s.mitre_technique_id,
        mitre_technique_name: s.mitre_technique_name,
        description: s.description ?? '',
        commands: s.commands ?? '',
        prerequisites: s.prerequisites ?? '',
        executed_at: s.executed_at ? s.executed_at.slice(0, 16) : '',
        execution_result: s.execution_result ?? '',
      });
      setSoc({
        log_source: s.log_source ?? '',
        logs: s.logs ?? '',
        soc_comment: s.soc_comment ?? '',
        incident_number: s.incident_number ?? '',
      });
    }
  }, [isNew, detail.data]);

  if (!isNew && detail.isLoading) return <LoadingState label="Loading simulation…" />;
  if (!isNew && detail.isError) {
    return (
      <ErrorState
        message={extractApiError(detail.error, 'Could not load simulation')}
        onRetry={() => detail.refetch()}
      />
    );
  }

  const simulation = detail.data;
  const status = simulation?.status;

  // Role-based field locking
  const canEditRT = isAdmin || isRedteam;
  // SOC can only edit when status is review_required or done
  const socCanEdit = isSoc && (status === 'review_required' || status === 'done');
  const socBlocked = isSoc && (status === 'pending' || status === 'in_progress');

  const canSaveSoc = socCanEdit || canEditEngagements;
  const rtDisabled = !canEditRT;
  const socDisabled = !canEditEngagements && !socCanEdit;

  // Transition buttons visibility
  const showMarkReview =
    canEditEngagements && (status === 'pending' || status === 'in_progress');
  const showClose =
    (canEditEngagements || isSoc) && status === 'review_required';

  const onSubmitNew = async (e: FormEvent) => {
    e.preventDefault();
    setNameError(null);
    setSubmitError(null);
    if (!rt.name.trim()) {
      setNameError('Name is required');
      return;
    }
    try {
      const created = await createMutation.mutateAsync({ name: rt.name.trim() });
      push('Simulation créée', 'success');
      navigate(`/engagements/${engagementId}/simulations/${created.id}/edit`);
    } catch (err) {
      setSubmitError(extractApiError(err, 'Could not create simulation'));
    }
  };

  const onSaveRT = async (e: FormEvent) => {
    e.preventDefault();
    setNameError(null);
    setSubmitError(null);
    if (!rt.name.trim()) {
      setNameError('Name is required');
      return;
    }
    const patch: SimulationPatchInput = {
      name: rt.name.trim(),
      mitre_technique_id: rt.mitre_technique_id ?? null,
      mitre_technique_name: rt.mitre_technique_name ?? null,
      description: rt.description.trim() || null,
      commands: rt.commands.trim() || null,
      prerequisites: rt.prerequisites.trim() || null,
      executed_at: rt.executed_at || null,
      execution_result: rt.execution_result.trim() || null,
    };
    try {
      await updateMutation.mutateAsync(patch);
      push('Simulation mise à jour', 'success');
    } catch (err) {
      setSubmitError(extractApiError(err, 'Could not update simulation'));
    }
  };

  const onSaveSOC = async (e: FormEvent) => {
    e.preventDefault();
    setSubmitError(null);
    const patch: SimulationPatchInput = {
      log_source: soc.log_source.trim() || null,
      logs: soc.logs.trim() || null,
      soc_comment: soc.soc_comment.trim() || null,
      incident_number: soc.incident_number.trim() || null,
    };
    try {
      await updateMutation.mutateAsync(patch);
      push('Rapport SOC mis à jour', 'success');
    } catch (err) {
      setSubmitError(extractApiError(err, 'Could not update SOC fields'));
    }
  };

  const onMarkReview = async () => {
    try {
      await transitionMutation.mutateAsync('review_required');
      push('Simulation marquée en revue', 'success');
    } catch (err) {
      push(extractApiError(err, 'Transition impossible'), 'error');
    }
  };

  const onClose = async () => {
    try {
      await transitionMutation.mutateAsync('done');
      push('Simulation clôturée', 'success');
    } catch (err) {
      push(extractApiError(err, 'Transition impossible'), 'error');
    }
  };

  const onDelete = async () => {
    setShowDeleteConfirm(false);
    try {
      await deleteMutation.mutateAsync(simulationId as number);
      push('Simulation supprimée', 'success');
      navigate(`/engagements/${engagementId}`);
    } catch (err) {
      push(extractApiError(err, 'Suppression impossible'), 'error');
    }
  };

  // New simulation form (minimal)
  if (isNew) {
    const submitting = createMutation.isPending;
    return (
      <div className="flex flex-col gap-xl max-w-2xl">
        <header>
          <Link to={`/engagements/${engagementId}`} className="btn-text-link text-[14px]">
            ← Back to engagement
          </Link>
          <h1 className="text-[44px] font-medium leading-none mt-sm">Nouvelle simulation</h1>
        </header>

        <form onSubmit={onSubmitNew} noValidate className="card-product flex flex-col gap-md">
          <FormField label="Name" htmlFor="sim-name" required error={nameError}>
            <TextInput
              id="sim-name"
              name="name"
              value={rt.name}
              onChange={(e) => setRt({ ...rt, name: e.target.value })}
              required
            />
          </FormField>

          {submitError ? (
            <div role="alert" className="text-[14px] text-bloom-deep">
              {submitError}
            </div>
          ) : null}

          <div className="flex items-center gap-md pt-sm">
            <button type="submit" className="btn-primary" disabled={submitting}>
              {submitting ? 'Creating…' : 'Create simulation'}
            </button>
            <Link to={`/engagements/${engagementId}`} className="btn-outline-ink">
              Cancel
            </Link>
          </div>
        </form>
      </div>
    );
  }

  // Edit form
  const submitting =
    updateMutation.isPending || transitionMutation.isPending || deleteMutation.isPending;

  return (
    <div className="flex flex-col gap-xl max-w-3xl">
      <header className="flex items-start justify-between gap-md">
        <div className="flex flex-col gap-sm">
          <Link to={`/engagements/${engagementId}`} className="btn-text-link text-[14px]">
            ← Back to engagement
          </Link>
          <h1 className="text-[44px] font-medium leading-none">{rt.name || simulation?.name}</h1>
          {status ? (
            <div className="flex items-center gap-md">
              <SimulationStatusBadge status={status} />
              {simulation?.created_by && (
                <span className="text-[14px] text-graphite">
                  Created by <span className="text-ink">{simulation.created_by.username}</span>
                </span>
              )}
            </div>
          ) : null}
        </div>
      </header>

      {/* SOC banner — shown when soc user visits pending/in_progress */}
      {socBlocked && (
        <div
          role="alert"
          data-testid="soc-blocked-banner"
          className="rounded-xl px-xl py-md bg-fog border border-hairline text-[14px] text-charcoal"
        >
          Simulation pas encore en revue — la redteam doit la marquer comme &quot;Review required&quot; avant
          que vous puissiez intervenir.
        </div>
      )}

      {/* Red Team card */}
      <form
        id="rt-form"
        onSubmit={canEditRT ? onSaveRT : (e) => e.preventDefault()}
        noValidate
        className="card-product flex flex-col gap-md"
      >
        <h2 className="text-[20px] font-medium text-ink">Red Team</h2>

        <FormField label="Name" htmlFor="sim-name" required error={nameError}>
          <TextInput
            id="sim-name"
            name="name"
            value={rt.name}
            onChange={(e) => setRt({ ...rt, name: e.target.value })}
            disabled={rtDisabled}
            required
          />
        </FormField>

        <FormField label="MITRE Technique" htmlFor="sim-mitre">
          <MitreTechniquePicker
            techniqueId={rt.mitre_technique_id}
            techniqueName={rt.mitre_technique_name}
            onChange={(id, name) =>
              setRt({ ...rt, mitre_technique_id: id, mitre_technique_name: name })
            }
            disabled={rtDisabled}
          />
        </FormField>

        <FormField label="Description" htmlFor="sim-description">
          <TextArea
            id="sim-description"
            name="description"
            value={rt.description}
            onChange={(e) => setRt({ ...rt, description: e.target.value })}
            disabled={rtDisabled}
          />
        </FormField>

        <FormField
          label="Commands"
          htmlFor="sim-commands"
          hint="One command per line"
        >
          <TextArea
            id="sim-commands"
            name="commands"
            value={rt.commands}
            onChange={(e) => setRt({ ...rt, commands: e.target.value })}
            disabled={rtDisabled}
            className="min-h-[160px] font-mono text-[14px]"
          />
        </FormField>

        <FormField label="Prerequisites" htmlFor="sim-prerequisites">
          <TextArea
            id="sim-prerequisites"
            name="prerequisites"
            value={rt.prerequisites}
            onChange={(e) => setRt({ ...rt, prerequisites: e.target.value })}
            disabled={rtDisabled}
          />
        </FormField>

        <div className="grid grid-cols-1 md:grid-cols-2 gap-md">
          <FormField label="Executed at" htmlFor="sim-executed-at">
            <TextInput
              id="sim-executed-at"
              type="datetime-local"
              name="executed_at"
              value={rt.executed_at}
              onChange={(e) => setRt({ ...rt, executed_at: e.target.value })}
              disabled={rtDisabled}
            />
          </FormField>

          <FormField label="Execution result" htmlFor="sim-exec-result">
            <TextInput
              id="sim-exec-result"
              name="execution_result"
              value={rt.execution_result}
              onChange={(e) => setRt({ ...rt, execution_result: e.target.value })}
              disabled={rtDisabled}
            />
          </FormField>
        </div>

        {canEditRT && (
          <div className="flex items-center gap-md pt-sm border-t border-hairline">
            <button type="submit" form="rt-form" className="btn-primary" disabled={submitting}>
              {updateMutation.isPending ? 'Saving…' : 'Save Red Team'}
            </button>
          </div>
        )}
      </form>

      {/* SOC card */}
      <form
        id="soc-form"
        onSubmit={canSaveSoc ? onSaveSOC : (e) => e.preventDefault()}
        noValidate
        className="card-product flex flex-col gap-md"
      >
        <h2 className="text-[20px] font-medium text-ink">SOC</h2>

        <FormField label="Log source" htmlFor="sim-log-source">
          <TextInput
            id="sim-log-source"
            name="log_source"
            value={soc.log_source}
            onChange={(e) => setSoc({ ...soc, log_source: e.target.value })}
            disabled={socDisabled}
          />
        </FormField>

        <FormField label="Logs" htmlFor="sim-logs">
          <TextArea
            id="sim-logs"
            name="logs"
            value={soc.logs}
            onChange={(e) => setSoc({ ...soc, logs: e.target.value })}
            disabled={socDisabled}
          />
        </FormField>

        <FormField label="SOC comment" htmlFor="sim-soc-comment">
          <TextArea
            id="sim-soc-comment"
            name="soc_comment"
            value={soc.soc_comment}
            onChange={(e) => setSoc({ ...soc, soc_comment: e.target.value })}
            disabled={socDisabled}
          />
        </FormField>

        <FormField label="Incident number" htmlFor="sim-incident">
          <TextInput
            id="sim-incident"
            name="incident_number"
            value={soc.incident_number}
            onChange={(e) => setSoc({ ...soc, incident_number: e.target.value })}
            disabled={socDisabled}
          />
        </FormField>

        {canSaveSoc && (
          <div className="flex items-center gap-md pt-sm border-t border-hairline">
            <button type="submit" form="soc-form" className="btn-primary" disabled={submitting}>
              {updateMutation.isPending ? 'Saving…' : 'Save SOC'}
            </button>
          </div>
        )}
      </form>

      {submitError ? (
        <div role="alert" className="text-[14px] text-bloom-deep">
          {submitError}
        </div>
      ) : null}

      {/* Workflow + delete footer */}
      <div className="flex items-center gap-md flex-wrap">
        {showMarkReview && (
          <button
            type="button"
            className="btn-outline"
            onClick={onMarkReview}
            disabled={transitionMutation.isPending}
          >
            Marquer en revue
          </button>
        )}
        {showClose && (
          <button
            type="button"
            className="btn-outline"
            onClick={onClose}
            disabled={transitionMutation.isPending}
          >
            Clôturer
          </button>
        )}
        {canEditEngagements && simulationId && (
          <button
            type="button"
            className="btn-text-link text-bloom-deep"
            onClick={() => setShowDeleteConfirm(true)}
            disabled={submitting}
          >
            Supprimer
          </button>
        )}
      </div>

      {showDeleteConfirm && (
        <ConfirmDialog
          title="Supprimer la simulation"
          description="Cette action est irréversible. La simulation sera définitivement supprimée."
          confirmLabel="Supprimer"
          cancelLabel="Annuler"
          destructive
          onConfirm={onDelete}
          onCancel={() => setShowDeleteConfirm(false)}
        />
      )}
    </div>
  );
}
