import {
  useEffect,
  useId,
  useMemo,
  useRef,
  useState,
  type FormEvent,
  type KeyboardEvent,
  type ReactNode,
  type Ref,
} from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { Button } from '@/components/ui/Button';
import { ApiClientError } from '@/lib/api';
import type { ApiError, C2Type, PydanticErrorItem } from '@/types/api';
import { createEngagement, ENGAGEMENTS_QUERY_KEY } from './engagementsApi';

interface EngagementCreateDialogProps {
  onClose: () => void;
}

type FieldKey = 'client_name' | 'description' | 'c2_type';
type FieldErrors = Partial<Record<FieldKey, string>>;

const C2_OPTIONS: ReadonlyArray<{ value: C2Type; label: string }> = [
  { value: 'mythic', label: 'Mythic' },
  { value: 'home', label: 'Home (RT-internal)' },
];

/**
 * "Arm engagement" dialog.
 *
 * Visual grammar:
 *   - Backdrop: graphite dim + faint scanline texture, no blur. Reads as
 *     "the cockpit is paused while you issue a command", not a sleek
 *     SaaS overlay.
 *   - Surface: --surface-3 (one level above panels), corner-mark utility
 *     at the four corners, hairline divider beneath the masthead.
 *   - Inputs: label-system uppercase + underline that lights amber on
 *     focus. No rounded boxes; the form should read as a console.
 *   - Submit: primary amber Button — the same accent used for RT-only
 *     actions throughout the app, so the action lineage is obvious.
 *
 * Contract (api.md):
 *   POST /api/v1/engagements/ with { client_name (required), description?,
 *   c2_type? (default mythic), start_date?, end_date? }. Backend returns
 *   the created Engagement on 201, the uniform { error, message, details? }
 *   envelope on 422 / 4xx. Per-field details on 422 are matched via the
 *   last segment of `loc`.
 */
export function EngagementCreateDialog({ onClose }: EngagementCreateDialogProps) {
  const titleId = useId();
  const surfaceRef = useRef<HTMLDivElement>(null);
  const firstFieldRef = useRef<HTMLInputElement>(null);

  const [clientName, setClientName] = useState('');
  const [description, setDescription] = useState('');
  const [c2Type, setC2Type] = useState<C2Type>('mythic');
  const [fieldErrors, setFieldErrors] = useState<FieldErrors>({});
  const [topError, setTopError] = useState<string | null>(null);

  const queryClient = useQueryClient();

  const mutation = useMutation({
    mutationFn: createEngagement,
    onSuccess: async () => {
      await queryClient.invalidateQueries({ queryKey: ENGAGEMENTS_QUERY_KEY });
      onClose();
    },
    onError: (err) => {
      if (err instanceof ApiClientError) {
        if (err.status === 422 && err.body?.details) {
          setFieldErrors(mapValidationErrors(err.body.details));
          setTopError(null);
          return;
        }
        if (err.status === 401) {
          setTopError('Session expirée. Reconnectez-vous.');
          return;
        }
        if (err.status === 403) {
          setTopError('Action interdite pour ce rôle.');
          return;
        }
        if (err.body?.message) {
          setTopError(genericMessage(err.body));
          return;
        }
      }
      setTopError('Création impossible. Réessayez dans un instant.');
    },
  });

  const isPending = mutation.isPending;

  useEffect(() => {
    firstFieldRef.current?.focus();
    const onKeyDown = (e: globalThis.KeyboardEvent) => {
      if (e.key === 'Escape' && !isPending) {
        e.preventDefault();
        onClose();
      }
    };
    window.addEventListener('keydown', onKeyDown);
    return () => window.removeEventListener('keydown', onKeyDown);
  }, [isPending, onClose]);

  const handleSurfaceKeyDown = (e: KeyboardEvent<HTMLDivElement>) => {
    if (e.key !== 'Tab' || !surfaceRef.current) return;
    const focusables = surfaceRef.current.querySelectorAll<HTMLElement>(
      'input, textarea, select, button, [tabindex]:not([tabindex="-1"])',
    );
    if (focusables.length === 0) return;
    const first = focusables[0];
    const last = focusables[focusables.length - 1];
    if (!first || !last) return;
    const active = document.activeElement;
    if (e.shiftKey && active === first) {
      e.preventDefault();
      last.focus();
    } else if (!e.shiftKey && active === last) {
      e.preventDefault();
      first.focus();
    }
  };

  const handleSubmit = (e: FormEvent) => {
    e.preventDefault();
    setFieldErrors({});
    setTopError(null);
    if (!clientName.trim()) {
      setFieldErrors({ client_name: 'Client requis.' });
      return;
    }
    mutation.mutate({
      client_name: clientName.trim(),
      description: description.trim() || null,
      c2_type: c2Type,
    });
  };

  const draftId = useMemo(() => generateDraftId(), []);

  return (
    <div
      role="presentation"
      onMouseDown={(e) => {
        if (e.target === e.currentTarget && !isPending) onClose();
      }}
      style={{
        position: 'fixed',
        inset: 0,
        zIndex: 50,
        background:
          'radial-gradient(circle at 50% 35%, oklch(7.4% 0.012 247 / 0.55), oklch(5.8% 0.012 247 / 0.82) 60%)',
        backgroundColor: 'oklch(5.8% 0.012 247 / 0.78)',
      }}
    >
      <div
        aria-hidden="true"
        style={{
          position: 'absolute',
          inset: 0,
          backgroundImage:
            'repeating-linear-gradient(0deg, transparent 0, transparent 2px, oklch(100% 0 0 / 0.012) 2px, oklch(100% 0 0 / 0.012) 3px)',
          pointerEvents: 'none',
        }}
      />

      <div
        role="dialog"
        aria-modal="true"
        aria-labelledby={titleId}
        ref={surfaceRef}
        onKeyDown={handleSurfaceKeyDown}
        className="corner-mark"
        style={{
          position: 'absolute',
          top: '14%',
          left: '50%',
          transform: 'translateX(-50%)',
          width: 'min(520px, calc(100vw - 32px))',
          backgroundColor: 'var(--surface-3)',
          border: '1px solid var(--line-strong)',
          borderRadius: 'var(--radius-md)',
          boxShadow: 'var(--shadow-pop)',
          animation: 'dialog-in 140ms var(--ease-mech) both',
        }}
      >
        <div
          className="flex items-center justify-between gap-3 px-5 py-3 border-b"
          style={{ borderColor: 'var(--line-default)' }}
        >
          <div className="flex items-center gap-3">
            <span
              aria-hidden="true"
              className="status-dot pulsing"
              style={{ color: 'var(--accent-rt)' }}
            />
            <h2
              id={titleId}
              className="label-system"
              style={{ color: 'var(--accent-rt)', letterSpacing: '0.18em' }}
            >
              ARM · NEW ENGAGEMENT
            </h2>
          </div>
          <span
            className="font-mono tabular text-fg-faint"
            style={{ fontSize: '10.5px' }}
          >
            {draftId}
          </span>
        </div>

        <div
          aria-hidden="true"
          style={{
            height: 1,
            background:
              'linear-gradient(90deg, transparent 0%, var(--accent-rt) 50%, transparent 100%)',
            opacity: 0.55,
          }}
        />

        <form onSubmit={handleSubmit} className="px-5 py-4 space-y-4" noValidate>
          {topError && (
            <div
              role="alert"
              className="label-system"
              style={{
                color: 'var(--state-failed)',
                border: '1px solid var(--state-failed)',
                padding: '6px 10px',
                borderRadius: 'var(--radius-sm)',
              }}
            >
              {topError}
            </div>
          )}

          <ConsoleField
            label="Client name"
            required
            value={clientName}
            onChange={setClientName}
            error={fieldErrors.client_name}
            disabled={isPending}
            placeholder="Démo Client X"
            ref={firstFieldRef}
          />

          <ConsoleSelect
            label="C2 backend"
            value={c2Type}
            onChange={(v) => setC2Type(v)}
            error={fieldErrors.c2_type}
            disabled={isPending}
            options={C2_OPTIONS}
          />

          <ConsoleTextarea
            label="Brief"
            value={description}
            onChange={setDescription}
            error={fieldErrors.description}
            disabled={isPending}
            placeholder="Scope notes, ROE pointers, post-mission expectations."
          />

          <div
            className="flex items-center justify-between gap-3 pt-3 border-t"
            style={{ borderColor: 'var(--line-default)' }}
          >
            <span className="label-system text-fg-faint">
              {isPending ? '// transmitting …' : '// awaiting confirmation'}
            </span>
            <div className="flex items-center gap-2">
              <Button
                type="button"
                variant="ghost"
                size="sm"
                onClick={onClose}
                disabled={isPending}
              >
                Cancel
              </Button>
              <Button type="submit" variant="primary" size="sm" disabled={isPending}>
                {isPending ? 'Arming …' : 'Arm engagement →'}
              </Button>
            </div>
          </div>
        </form>
      </div>

      <style>{`
        @keyframes dialog-in {
          0%   { opacity: 0; transform: translate(-50%, calc(-50% + 4px)) translateY(8px); }
          100% { opacity: 1; transform: translateX(-50%) translateY(0); }
        }
      `}</style>
    </div>
  );
}

function mapValidationErrors(details: PydanticErrorItem[]): FieldErrors {
  const out: FieldErrors = {};
  for (const item of details) {
    const last = item.loc[item.loc.length - 1];
    if (last === 'client_name' || last === 'description' || last === 'c2_type') {
      out[last] = item.msg;
    }
  }
  return out;
}

function genericMessage(body: ApiError): string {
  // Capitalize first letter for display while keeping the message verbatim.
  const msg = body.message.trim();
  if (!msg) return 'Création impossible.';
  return msg.charAt(0).toUpperCase() + msg.slice(1);
}

function generateDraftId(): string {
  const t = new Date();
  const pad = (n: number) => String(n).padStart(2, '0');
  return `DRAFT-${t.getUTCFullYear().toString().slice(-2)}${pad(t.getUTCMonth() + 1)}${pad(t.getUTCDate())}-${pad(t.getUTCHours())}${pad(t.getUTCMinutes())}`;
}

interface ConsoleFieldProps {
  label: string;
  value: string;
  onChange: (next: string) => void;
  required?: boolean;
  disabled?: boolean;
  placeholder?: string;
  error?: string;
  mono?: boolean;
}

function ConsoleField({
  label,
  value,
  onChange,
  required,
  disabled,
  placeholder,
  error,
  mono,
  ref,
}: ConsoleFieldProps & { ref?: Ref<HTMLInputElement> }): ReactNode {
  const id = useId();
  return (
    <div className="space-y-1.5">
      <label htmlFor={id} className="block label-system flex items-center justify-between">
        <span>{label}</span>
        {required && (
          <span style={{ color: 'var(--accent-rt)' }} aria-hidden="true">
            · required
          </span>
        )}
      </label>
      <input
        id={id}
        ref={ref}
        type="text"
        value={value}
        onChange={(e) => onChange(e.target.value)}
        disabled={disabled}
        placeholder={placeholder}
        aria-invalid={error ? 'true' : undefined}
        aria-describedby={error ? `${id}-err` : undefined}
        className={mono ? 'font-mono tabular' : 'font-sans'}
        style={{
          width: '100%',
          height: 30,
          padding: '0 0 4px 0',
          backgroundColor: 'transparent',
          color: 'var(--fg-default)',
          border: 'none',
          borderBottom: `1px solid ${error ? 'var(--state-failed)' : 'var(--line-strong)'}`,
          borderRadius: 0,
          fontSize: 13,
          outline: 'none',
        }}
        onFocus={(e) => {
          if (!error) {
            e.currentTarget.style.borderBottomColor = 'var(--accent-rt)';
          }
        }}
        onBlur={(e) => {
          if (!error) {
            e.currentTarget.style.borderBottomColor = 'var(--line-strong)';
          }
        }}
      />
      {error && (
        <p id={`${id}-err`} className="label-system" style={{ color: 'var(--state-failed)' }}>
          {error}
        </p>
      )}
    </div>
  );
}

interface ConsoleSelectProps<T extends string> {
  label: string;
  value: T;
  onChange: (next: T) => void;
  options: ReadonlyArray<{ value: T; label: string }>;
  disabled?: boolean;
  error?: string;
}

function ConsoleSelect<T extends string>({
  label,
  value,
  onChange,
  options,
  disabled,
  error,
}: ConsoleSelectProps<T>): ReactNode {
  const id = useId();
  return (
    <div className="space-y-1.5">
      <label htmlFor={id} className="block label-system">
        {label}
      </label>
      <select
        id={id}
        value={value}
        onChange={(e) => onChange(e.target.value as T)}
        disabled={disabled}
        aria-invalid={error ? 'true' : undefined}
        aria-describedby={error ? `${id}-err` : undefined}
        className="font-sans"
        style={{
          width: '100%',
          height: 30,
          padding: '0 8px',
          backgroundColor: 'var(--surface-inset)',
          color: 'var(--fg-default)',
          border: `1px solid ${error ? 'var(--state-failed)' : 'var(--line-strong)'}`,
          borderRadius: 'var(--radius-sm)',
          fontSize: 12.5,
          outline: 'none',
        }}
      >
        {options.map((opt) => (
          <option key={opt.value} value={opt.value}>
            {opt.label}
          </option>
        ))}
      </select>
      {error && (
        <p id={`${id}-err`} className="label-system" style={{ color: 'var(--state-failed)' }}>
          {error}
        </p>
      )}
    </div>
  );
}

interface ConsoleTextareaProps {
  label: string;
  value: string;
  onChange: (next: string) => void;
  disabled?: boolean;
  placeholder?: string;
  error?: string;
}

function ConsoleTextarea({
  label,
  value,
  onChange,
  disabled,
  placeholder,
  error,
}: ConsoleTextareaProps): ReactNode {
  const id = useId();
  return (
    <div className="space-y-1.5">
      <label htmlFor={id} className="block label-system">
        {label}
      </label>
      <textarea
        id={id}
        value={value}
        onChange={(e) => onChange(e.target.value)}
        disabled={disabled}
        placeholder={placeholder}
        rows={4}
        aria-invalid={error ? 'true' : undefined}
        aria-describedby={error ? `${id}-err` : undefined}
        className="font-sans"
        style={{
          width: '100%',
          padding: '8px 10px',
          backgroundColor: 'var(--surface-inset)',
          color: 'var(--fg-default)',
          border: `1px solid ${error ? 'var(--state-failed)' : 'var(--line-default)'}`,
          borderRadius: 'var(--radius-sm)',
          fontSize: 12.5,
          lineHeight: 1.55,
          resize: 'vertical',
          outline: 'none',
        }}
      />
      {error && (
        <p id={`${id}-err`} className="label-system" style={{ color: 'var(--state-failed)' }}>
          {error}
        </p>
      )}
    </div>
  );
}
