import { useState } from 'react';
import { ShieldAlert, MessageCircleQuestion } from 'lucide-react';
import type { PermissionPrompt } from '@/api/types';
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';

interface Props {
  prompt: PermissionPrompt;
  onRespond: (optionId: string | null, updatedInput?: Record<string, unknown>) => void;
  busy?: boolean;
}

// ---------------------------------------------------------------------------
// Question detection — ACP's RequestPermissionRequest carries the tool input
// in `input`. Claude Code's AskUserQuestion puts { questions: [...] } there.
// ---------------------------------------------------------------------------

interface Question {
  question: string;
  header?: string;
  options: string[];
  multiSelect: boolean;
}

function parseQuestions(input: Record<string, unknown> | undefined): Question[] | null {
  if (!input) return null;
  const raw = input.questions;
  if (!Array.isArray(raw)) return null;
  const out: Question[] = [];
  for (const item of raw) {
    if (!item || typeof item !== 'object') continue;
    const q = item as { question?: unknown; header?: unknown; options?: unknown; multiSelect?: unknown };
    if (typeof q.question !== 'string') continue;
    const opts = Array.isArray(q.options)
      ? q.options.filter((o): o is string => typeof o === 'string')
      : [];
    out.push({
      question: q.question,
      header: typeof q.header === 'string' ? q.header : undefined,
      options: opts,
      multiSelect: q.multiSelect === true,
    });
  }
  return out.length > 0 ? out : null;
}

// ---------------------------------------------------------------------------
// Elicitation detection — ACP's createElicitation carries a JSON Schema in
// `input.requestedSchema`. For now, render each property as a text input.
// ---------------------------------------------------------------------------

interface ElicitationField {
  key: string;
  title: string;
  description?: string;
  type: string;
  enumValues?: string[];
}

function parseElicitation(input: Record<string, unknown> | undefined): { message: string; fields: ElicitationField[] } | null {
  if (!input) return null;
  const schema = input.requestedSchema;
  if (!schema || typeof schema !== 'object') return null;
  const s = schema as Record<string, unknown>;
  const props = s.properties;
  if (!props || typeof props !== 'object') return null;
  const fields: ElicitationField[] = [];
  for (const [key, val] of Object.entries(props as Record<string, unknown>)) {
    if (!val || typeof val !== 'object') continue;
    const p = val as Record<string, unknown>;
    fields.push({
      key,
      title: typeof p.title === 'string' ? p.title : key,
      description: typeof p.description === 'string' ? p.description : undefined,
      type: typeof p.type === 'string' ? p.type : 'string',
      enumValues: Array.isArray(p.enum) ? p.enum.filter((e): e is string => typeof e === 'string') : undefined,
    });
  }
  if (fields.length === 0) return null;
  return { message: typeof input.message === 'string' ? input.message : '', fields };
}

export function PermissionCard({ prompt, onRespond, busy }: Props) {
  const isQuestion = prompt.kind === 'question';
  const isElicitation = prompt.kind === 'elicitation';

  if (isQuestion) {
    const questions = parseQuestions(prompt.input);
    if (questions) {
      return <QuestionView questions={questions} prompt={prompt} onRespond={onRespond} busy={busy} />;
    }
  }

  if (isElicitation) {
    const elicitation = parseElicitation(prompt.input);
    if (elicitation) {
      return <ElicitationView elicitation={elicitation} prompt={prompt} onRespond={onRespond} busy={busy} />;
    }
  }

  // Standard tool permission — approve/deny buttons
  return (
    <div className="mx-3 my-2 rounded-md border border-amber-500/40 bg-amber-500/10 px-3 py-2 text-sm">
      <div className="flex items-start gap-2">
        <ShieldAlert className="size-4 text-amber-600 shrink-0 mt-0.5" />
        <div className="flex-1 min-w-0">
          <p className="font-medium text-foreground">Permission required</p>
          {prompt.toolTitle && (
            <p className="text-xs text-muted-foreground mt-0.5 truncate">{prompt.toolTitle}</p>
          )}
          <div className="flex flex-wrap gap-2 mt-2">
            {prompt.options.map((opt) => (
              <button
                key={opt.optionId}
                type="button"
                disabled={busy}
                onClick={() => onRespond(opt.optionId)}
                className={cn(
                  'rounded-md border border-input bg-background px-2.5 py-1 text-xs hover:bg-accent',
                  'max-md:min-h-[44px] disabled:opacity-40',
                )}
              >
                {opt.label}
              </button>
            ))}
            <button
              type="button"
              disabled={busy}
              onClick={() => onRespond(null)}
              className="rounded-md border border-destructive/40 px-2.5 py-1 text-xs text-destructive hover:bg-destructive/10 max-md:min-h-[44px] disabled:opacity-40"
            >
              Deny
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// QuestionView — renders Claude's AskUserQuestion as interactive radio/checkbox
// ---------------------------------------------------------------------------

function QuestionView({
  questions,
  prompt,
  onRespond,
  busy,
}: {
  questions: Question[];
  prompt: PermissionPrompt;
  onRespond: Props['onRespond'];
  busy?: boolean;
}) {
  const [selections, setSelections] = useState<string[][]>(() => questions.map(() => []));
  const [freeTexts, setFreeTexts] = useState<string[]>(() => questions.map(() => ''));
  const [submitting, setSubmitting] = useState(false);
  const disabled = busy || submitting;

  const allComplete = questions.every((_, i) =>
    selections[i]!.length > 0 || freeTexts[i]!.trim().length > 0,
  );

  function buildAnswers(): Record<string, string> {
    const answers: Record<string, string> = {};
    for (let i = 0; i < questions.length; i++) {
      const q = questions[i]!;
      const key = q.question;
      const selected = selections[i]!;
      const free = freeTexts[i]!.trim();
      if (free) {
        answers[key] = free;
      } else if (selected.length > 0) {
        answers[key] = selected.join(', ');
      }
    }
    return answers;
  }

  function handleSubmit() {
    if (!allComplete || submitting) return;
    setSubmitting(true);
    const answers = buildAnswers();
    const firstAllow = prompt.options.find((o) =>
      o.label.toLowerCase().includes('allow') || o.label.toLowerCase().includes('yes'),
    );
    onRespond(firstAllow?.optionId ?? prompt.options[0]?.optionId ?? null, {
      ...prompt.input,
      answers,
    });
  }

  function pickSingle(qIdx: number, option: string) {
    setSelections((prev) => prev.map((arr, i) => (i === qIdx ? [option] : arr)));
    if (questions.length === 1 && !freeTexts[0]!.trim()) {
      setSubmitting(true);
      const firstAllow = prompt.options.find((o) =>
        o.label.toLowerCase().includes('allow') || o.label.toLowerCase().includes('yes'),
      );
      onRespond(firstAllow?.optionId ?? prompt.options[0]?.optionId ?? null, {
        ...prompt.input,
        answers: { [questions[0]!.question]: option },
      });
    }
  }

  function toggleMulti(qIdx: number, option: string) {
    setSelections((prev) =>
      prev.map((arr, i) => {
        if (i !== qIdx) return arr;
        return arr.includes(option) ? arr.filter((o) => o !== option) : [...arr, option];
      }),
    );
  }

  return (
    <div className="mx-3 my-2 rounded-lg border bg-muted/20 text-sm">
      <div className="px-4 py-3 space-y-4">
        {questions.map((q, i) => (
          <div key={i} className="space-y-2">
            {questions.length > 1 && (
              <div className="text-[10px] uppercase tracking-wide text-muted-foreground/70">
                {q.header ?? `Question ${i + 1}`}
              </div>
            )}
            <div className="font-medium leading-snug">{q.question}</div>
            {q.options.length > 0 && !q.multiSelect && (
              <RadioGroup
                value={selections[i]![0] ?? ''}
                onValueChange={(v) => pickSingle(i, v)}
                disabled={disabled}
                className="gap-1.5"
              >
                {q.options.map((opt, j) => {
                  const id = `q${i}-opt${j}`;
                  return (
                    <label
                      key={j}
                      htmlFor={id}
                      className="flex items-start gap-2 text-sm leading-snug cursor-pointer rounded px-1 py-0.5 hover:bg-muted/40"
                    >
                      <RadioGroupItem id={id} value={opt} className="mt-0.5" />
                      <span>{opt}</span>
                    </label>
                  );
                })}
              </RadioGroup>
            )}
            {q.options.length > 0 && q.multiSelect && (
              <div className="grid gap-1.5">
                {q.options.map((opt, j) => {
                  const id = `q${i}-opt${j}`;
                  const checked = selections[i]!.includes(opt);
                  return (
                    <label
                      key={j}
                      htmlFor={id}
                      className="flex items-start gap-2 text-sm leading-snug cursor-pointer rounded px-1 py-0.5 hover:bg-muted/40"
                    >
                      <input
                        id={id}
                        type="checkbox"
                        checked={checked}
                        disabled={disabled}
                        onChange={() => toggleMulti(i, opt)}
                        className="mt-1 size-3.5 rounded border-input accent-primary"
                      />
                      <span>{opt}</span>
                    </label>
                  );
                })}
              </div>
            )}
            <div className="pt-1 space-y-1">
              <div className="text-[10px] uppercase tracking-wide text-muted-foreground/70">
                Or type a custom answer
              </div>
              <input
                type="text"
                value={freeTexts[i]}
                disabled={disabled}
                placeholder="Free text…"
                onChange={(e) =>
                  setFreeTexts((prev) => prev.map((t, idx) => (idx === i ? e.target.value : t)))
                }
                className="w-full rounded border border-input bg-background px-2 py-1 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring/40 disabled:opacity-60"
              />
            </div>
          </div>
        ))}
      </div>
      {(questions.length > 1 || freeTexts.some((t) => t.trim())) && (
        <div className="flex justify-between items-center border-t px-4 py-2">
          <button
            type="button"
            disabled={disabled}
            onClick={() => onRespond(null)}
            className="text-xs text-destructive hover:underline disabled:opacity-40"
          >
            Dismiss
          </button>
          <Button
            type="button"
            size="sm"
            disabled={!allComplete || disabled}
            onClick={handleSubmit}
          >
            {submitting ? 'Submitting…' : 'Submit'}
          </Button>
        </div>
      )}
    </div>
  );
}

// ---------------------------------------------------------------------------
// ElicitationView — renders ACP elicitation forms (JSON Schema-driven)
// ---------------------------------------------------------------------------

function ElicitationView({
  elicitation,
  prompt,
  onRespond,
  busy,
}: {
  elicitation: { message: string; fields: ElicitationField[] };
  prompt: PermissionPrompt;
  onRespond: Props['onRespond'];
  busy?: boolean;
}) {
  const [values, setValues] = useState<Record<string, string>>(() => {
    const init: Record<string, string> = {};
    for (const f of elicitation.fields) init[f.key] = '';
    return init;
  });
  const [submitting, setSubmitting] = useState(false);
  const disabled = busy || submitting;

  const allFilled = elicitation.fields.every((f) => (values[f.key] ?? '').trim().length > 0);

  function handleSubmit() {
    if (!allFilled || submitting) return;
    setSubmitting(true);
    const content: Record<string, unknown> = {};
    for (const f of elicitation.fields) {
      const raw = values[f.key]!.trim();
      if (f.type === 'number' || f.type === 'integer') {
        content[f.key] = Number(raw);
      } else if (f.type === 'boolean') {
        content[f.key] = raw === 'true' || raw === 'yes' || raw === '1';
      } else {
        content[f.key] = raw;
      }
    }
    const firstAllow = prompt.options[0];
    onRespond(firstAllow?.optionId ?? null, content);
  }

  return (
    <div className="mx-3 my-2 rounded-lg border bg-muted/20 text-sm">
      <div className="px-4 py-3 space-y-3">
        <div className="flex items-start gap-2">
          <MessageCircleQuestion className="size-4 text-blue-500 shrink-0 mt-0.5" />
          <p className="font-medium leading-snug">{elicitation.message}</p>
        </div>
        {elicitation.fields.map((f) => (
          <div key={f.key} className="space-y-1">
            <label className="text-xs font-medium text-muted-foreground">{f.title}</label>
            {f.description && (
              <p className="text-[11px] text-muted-foreground/70">{f.description}</p>
            )}
            {f.enumValues ? (
              <RadioGroup
                value={values[f.key] ?? ''}
                onValueChange={(v) => setValues((prev) => ({ ...prev, [f.key]: v }))}
                disabled={disabled}
                className="gap-1.5"
              >
                {f.enumValues.map((opt, j) => {
                  const id = `e-${f.key}-${j}`;
                  return (
                    <label key={j} htmlFor={id} className="flex items-start gap-2 text-sm cursor-pointer rounded px-1 py-0.5 hover:bg-muted/40">
                      <RadioGroupItem id={id} value={opt} className="mt-0.5" />
                      <span>{opt}</span>
                    </label>
                  );
                })}
              </RadioGroup>
            ) : (
              <input
                type={f.type === 'number' || f.type === 'integer' ? 'number' : 'text'}
                value={values[f.key] ?? ''}
                disabled={disabled}
                onChange={(e) => setValues((prev) => ({ ...prev, [f.key]: e.target.value }))}
                className="w-full rounded border border-input bg-background px-2 py-1 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring/40 disabled:opacity-60"
              />
            )}
          </div>
        ))}
      </div>
      <div className="flex justify-between items-center border-t px-4 py-2">
        <button
          type="button"
          disabled={disabled}
          onClick={() => onRespond(null)}
          className="text-xs text-destructive hover:underline disabled:opacity-40"
        >
          Dismiss
        </button>
        <Button
          type="button"
          size="sm"
          disabled={!allFilled || disabled}
          onClick={handleSubmit}
        >
          {submitting ? 'Submitting…' : 'Submit'}
        </Button>
      </div>
    </div>
  );
}
