import { useState, useMemo } from 'react';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import rehypeRaw from 'rehype-raw';
import { toast } from 'sonner';
import { ArrowLeft, Pencil, Play, Trash2 } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog';
import { useClient } from 'hooks/useClient';
import { usePanelChannel } from 'hooks/usePanelChannel';
import { Card } from '@/components/Card';
import { FrontmatterBlock } from '../CapabilityPage';
import type { CapabilityDetail } from '../CapabilityPage';
import type { AutomationSelection } from './AutomationRightPanel';
import { TaskRunnerModal } from 'officerdev';

type SelectOption = { value: string; label: string };

type TaskInput = {
  name: string;
  description: string;
  type: 'string' | 'number' | 'boolean' | 'select';
  required: boolean;
  default: string;
  options: SelectOption[];
};

function parseInputs(rawYaml: string): TaskInput[] {
  // Match the inputs block: everything indented after "inputs:" until next top-level key or end
  const inputsMatch = rawYaml.match(/^inputs:\s*\n((?:[ \t]+.*\n?)*)/m);
  if (!inputsMatch) return [];
  const block = inputsMatch[1]!;
  // Split on list items that have a "name:" field (e.g. "  - name: country")
  const items = block.split(/(?=[ \t]+-\s*name\s*:)/);
  return items
    .filter((item) => /name\s*:/.test(item))
    .map((item) => {
      const name = item.match(/name\s*:\s*(.+)/)?.[1]?.trim() ?? '';
      const description = item.match(/description\s*:\s*(.+)/)?.[1]?.trim() ?? '';
      const rawType = item.match(/type\s*:\s*(.+)/)?.[1]?.trim() ?? 'string';
      const type = (['string', 'number', 'boolean', 'select'] as const).includes(rawType as 'string')
        ? (rawType as TaskInput['type'])
        : 'string';
      const required = item.match(/required\s*:\s*(.+)/)?.[1]?.trim() === 'true';
      const defaultFromField = item.match(/default\s*:\s*(.+)/)?.[1]?.trim();
      const defaultFromDesc = description.match(/[Dd]efaults?\s+to\s+(\S+?)\.?\s*$/)?.[1];

      const options: SelectOption[] = [];
      const optionsMatch = item.match(/options\s*:\s*\n((?:[ \t]+.*\n?)*)/);
      if (optionsMatch) {
        const optionEntries = optionsMatch[1]!.split(/(?=[ \t]*- \s*value\s*:)/);
        for (const entry of optionEntries) {
          const value = entry.match(/value\s*:\s*(.+)/)?.[1]?.trim() ?? '';
          const label = entry.match(/label\s*:\s*(.+)/)?.[1]?.trim() ?? value;
          if (value) options.push({ value, label });
        }
      }

      return { name, description, type, required, default: defaultFromField ?? defaultFromDesc ?? '', options };
    });
}

type CapabilityDetailViewProps = {
  kind: string;
  endpoint: string;
  queryKey: string;
  dirName: string;
  isNew?: boolean;
  editing?: boolean;
};

export const CapabilityDetailView = ({ kind, endpoint, queryKey, dirName, editing }: CapabilityDetailViewProps) => {
  const client = useClient();
  const qc = useQueryClient();
  const [selection, setSelection] = usePanelChannel<AutomationSelection>('automation:selected-capability', null);
  const [deleteConfirm, setDeleteConfirm] = useState(false);
  const [showInputForm, setShowInputForm] = useState(false);
  const [runPrompt, setRunPrompt] = useState<string | null>(null);
  const [inputValues, setInputValues] = useState<Record<string, string>>({});

  const { data: detail } = useQuery<CapabilityDetail>({
    queryKey: [queryKey, dirName],
    queryFn: () => client.get<CapabilityDetail>(`${endpoint}/${dirName}`),
  });

  const taskInputs = useMemo(() => (detail?.rawFrontmatter ? parseInputs(detail.rawFrontmatter) : []), [detail?.rawFrontmatter]);

  const handleRunClick = () => {
    if (taskInputs.length > 0) {
      const defaults: Record<string, string> = {};
      for (const input of taskInputs) {
        if (input.type === 'boolean') {
          defaults[input.name] = input.default === 'true' ? 'true' : 'false';
        } else if (input.type === 'select') {
          defaults[input.name] = input.default || (input.options[0]?.value ?? '');
        } else {
          defaults[input.name] = input.default;
        }
      }
      setInputValues(defaults);
      setShowInputForm(true);
    } else {
      setRunPrompt(`Read the task instructions at ${detail!.filePath} and execute them`);
    }
  };

  const handleInputSubmit = () => {
    const parts = Object.entries(inputValues)
      .filter(([, v]) => v !== '')
      .map(([k, v]) => `- ${k}: ${v}`);
    const suffix = parts.length > 0 ? `\n\nInputs:\n${parts.join('\n')}` : '';
    setRunPrompt(`Read the task instructions at ${detail!.filePath} and execute them${suffix}`);
    setShowInputForm(false);
  };

  const toggleEditing = () => {
    if (!selection) return;
    setSelection({ ...selection, editing: !editing });
  };

  const handleDelete = async () => {
    try {
      await client.delete(`${endpoint}/${dirName}`);
      setDeleteConfirm(false);
      await qc.invalidateQueries({ queryKey: [queryKey] });
      setSelection(null);
    } catch {
      toast.error(`Failed to delete ${kind}`);
    }
  };

  return (
    <>
      <Card className="h-full overflow-hidden flex flex-col min-h-0">
        <div className="shrink-0 px-4 py-2 border-b border-duck-dark/10 dark:border-foreground/10 bg-background/60 flex items-center gap-2">
          <button onClick={() => setSelection({ kind, endpoint, queryKey, dirName: '' })} className="p-1 -ml-1 rounded hover:bg-duck-dark/10 dark:hover:bg-foreground/10 cursor-pointer">
            <ArrowLeft className="h-4 w-4 text-duck-dark/60 dark:text-foreground/60" />
          </button>
          <span className="text-sm font-medium text-duck-dark/70 dark:text-foreground/70 flex-1">{detail?.name ?? `Loading...`}</span>
          {detail && (
            <>
              {kind === 'Task' && (
                <button
                  onClick={handleRunClick}
                  className="p-1 rounded hover:bg-duck-dark/10 dark:hover:bg-foreground/10 cursor-pointer transition-colors"
                  title="Run task"
                >
                  <Play className="h-3.5 w-3.5 text-duck-teal" />
                </button>
              )}
              <button
                onClick={toggleEditing}
                className={`p-1 rounded hover:bg-duck-dark/10 dark:hover:bg-foreground/10 cursor-pointer transition-colors ${editing ? 'bg-duck-teal/10' : ''}`}
              >
                <Pencil className={`h-3.5 w-3.5 ${editing ? 'text-duck-teal' : 'text-duck-dark/50 dark:text-foreground/50'}`} />
              </button>
              <button
                onClick={() => setDeleteConfirm(true)}
                className="p-1 rounded hover:bg-red-50 cursor-pointer transition-colors"
              >
                <Trash2 className="h-3.5 w-3.5 text-duck-dark/50 dark:text-foreground/50 hover:text-red-500" />
              </button>
            </>
          )}
        </div>
        <div className="overflow-y-auto flex-1 p-6">
          {detail?.rawFrontmatter && <FrontmatterBlock yaml={detail.rawFrontmatter} />}
          {detail?.body ? (
            <article className="skill-md">
              <ReactMarkdown remarkPlugins={[remarkGfm]} rehypePlugins={[rehypeRaw]}>
                {detail.body}
              </ReactMarkdown>
            </article>
          ) : detail ? (
            <p className="text-sm text-duck-dark/40 dark:text-foreground/40 text-center mt-12">Empty file</p>
          ) : null}
        </div>
      </Card>

      <Dialog open={deleteConfirm} onOpenChange={setDeleteConfirm}>
        <DialogContent className="sm:max-w-md z-[700]">
          <DialogHeader>
            <DialogTitle>Delete {kind}</DialogTitle>
            <DialogDescription>
              Are you sure you want to delete &quot;{detail?.name}&quot;? This action cannot be undone.
            </DialogDescription>
          </DialogHeader>
          <div className="flex justify-end gap-2 mt-2">
            <Button variant="outline" onClick={() => setDeleteConfirm(false)} className="cursor-pointer">
              Cancel
            </Button>
            <Button variant="destructive" onClick={handleDelete} className="cursor-pointer">
              Delete
            </Button>
          </div>
        </DialogContent>
      </Dialog>

      <Dialog open={showInputForm} onOpenChange={setShowInputForm}>
        <DialogContent className="sm:max-w-lg z-[700]">
          <DialogHeader>
            <DialogTitle>Run {detail?.name}</DialogTitle>
            <DialogDescription>Configure inputs before running.</DialogDescription>
          </DialogHeader>
          <form
            onSubmit={(ev) => {
              ev.preventDefault();
              handleInputSubmit();
            }}
            className="flex flex-col gap-3 mt-1"
          >
            {taskInputs.map((input) => (
              <div key={input.name} className="flex flex-col gap-1">
                {input.type === 'boolean' ? (
                  <label className="flex items-center gap-2 text-sm font-medium text-foreground/70 cursor-pointer">
                    <input
                      type="checkbox"
                      checked={inputValues[input.name] === 'true'}
                      onChange={(ev) => setInputValues((prev) => ({ ...prev, [input.name]: ev.target.checked ? 'true' : 'false' }))}
                      className="h-4 w-4 rounded border-foreground/20 accent-duck-teal"
                    />
                    {input.name}
                    {input.required && <span className="text-destructive ml-0.5">*</span>}
                  </label>
                ) : (
                  <>
                    <label className="text-sm font-medium text-foreground/70">
                      {input.name}
                      {input.required && <span className="text-destructive ml-0.5">*</span>}
                    </label>
                    {input.type === 'select' ? (
                      <select
                        value={inputValues[input.name] ?? ''}
                        onChange={(ev) => setInputValues((prev) => ({ ...prev, [input.name]: ev.target.value }))}
                        required={input.required}
                        className="rounded border border-foreground/20 bg-background px-3 py-2 text-sm text-foreground focus:outline-none focus:ring-1 focus:ring-duck-teal/30"
                      >
                        {input.options.map((opt) => (
                          <option key={opt.value} value={opt.value}>{opt.label}</option>
                        ))}
                      </select>
                    ) : (
                      <input
                        type={input.type === 'number' ? 'number' : 'text'}
                        value={inputValues[input.name] ?? ''}
                        onChange={(ev) => setInputValues((prev) => ({ ...prev, [input.name]: ev.target.value }))}
                        placeholder={input.default || undefined}
                        required={input.required}
                        className="rounded border border-foreground/20 bg-background px-3 py-2 text-sm text-foreground placeholder:text-foreground/30 focus:outline-none focus:ring-1 focus:ring-duck-teal/30"
                      />
                    )}
                  </>
                )}
                {input.description && (
                  <span className="text-xs text-foreground/40">{input.description}</span>
                )}
              </div>
            ))}
            <div className="flex justify-end gap-2 mt-2">
              <Button type="button" variant="outline" onClick={() => setShowInputForm(false)} className="cursor-pointer">
                Cancel
              </Button>
              <Button type="submit" className="bg-duck-teal text-duck-yellow hover:bg-duck-teal/90 cursor-pointer">
                Run
              </Button>
            </div>
          </form>
        </DialogContent>
      </Dialog>

      {runPrompt !== null && detail && (
        <TaskRunnerModal
          open
          onOpenChange={(open) => {
            if (!open) setRunPrompt(null);
          }}
          task={{ dirName, name: detail.name, description: detail.description ?? '', scope: detail.scope ?? 'user', triggers: [], filePath: detail.filePath }}
          promptOverride={runPrompt}
        />
      )}
    </>
  );
};
