"use client";

import { useEffect, useRef, useState } from "react";
import { createPortal } from "react-dom";
import { ChevronDown, Plus, X } from "lucide-react";
import type { ColumnConfig, ColumnFormat } from "../shared/types";
import { generateTabularColumnPrompt } from "@/app/lib/mikeApi";
import { FORMAT_OPTIONS, formatLabel, formatIcon } from "./columnFormat";
import { TAG_COLORS } from "./pillUtils";
import { getPresetConfig, PROMPT_PRESETS } from "./columnPresets";
import {
    DropdownMenu,
    DropdownMenuContent,
    DropdownMenuRadioGroup,
    DropdownMenuRadioItem,
    DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";

interface ColumnDraft {
    name: string;
    prompt: string;
    format: ColumnFormat;
    tags: string[];
    tagInput: string;
}

const EMPTY_DRAFT: ColumnDraft = {
    name: "",
    prompt: "",
    format: "text",
    tags: [],
    tagInput: "",
};

interface Props {
    open: boolean;
    existingCount: number;
    onClose: () => void;
    onAdd: (cols: ColumnConfig[]) => void;
    editingColumn?: ColumnConfig;
    onSave?: (col: ColumnConfig) => void;
    onDelete?: () => void;
}

export function AddColumnModal({ open, existingCount, onClose, onAdd, editingColumn, onSave, onDelete }: Props) {
    const isEditing = !!editingColumn;
    const [columns, setColumns] = useState<ColumnDraft[]>([{ ...EMPTY_DRAFT }]);
    const [generatingIndices, setGeneratingIndices] = useState<number[]>([]);
    const [presetsOpenIndex, setPresetsOpenIndex] = useState<number | null>(
        null,
    );
    const presetsRef = useRef<HTMLDivElement>(null);

    useEffect(() => {
        if (!open) return;
        if (editingColumn) {
            setColumns([{
                name: editingColumn.name,
                prompt: editingColumn.prompt,
                format: editingColumn.format ?? "text",
                tags: editingColumn.tags ?? [],
                tagInput: "",
            }]);
        } else {
            setColumns([{ ...EMPTY_DRAFT }]);
        }
    }, [open]); // eslint-disable-line react-hooks/exhaustive-deps

    useEffect(() => {
        if (presetsOpenIndex === null) return;
        function handleClickOutside(e: MouseEvent) {
            if (
                presetsRef.current &&
                !presetsRef.current.contains(e.target as Node)
            ) {
                setPresetsOpenIndex(null);
            }
        }
        document.addEventListener("mousedown", handleClickOutside);
        return () =>
            document.removeEventListener("mousedown", handleClickOutside);
    }, [presetsOpenIndex]);

    if (!open) return null;

    function resetForm() {
        setColumns([{ ...EMPTY_DRAFT }]);
        setGeneratingIndices([]);
    }

    function handleClose() {
        resetForm();
        onClose();
    }

    function updateColumn(index: number, patch: Partial<ColumnDraft>) {
        setColumns((prev) =>
            prev.map((col, i) => (i === index ? { ...col, ...patch } : col)),
        );
    }

    function addAnotherColumn() {
        setColumns((prev) => [...prev, { ...EMPTY_DRAFT }]);
    }

    function removeColumn(index: number) {
        setColumns((prev) =>
            prev.length === 1
                ? [{ ...EMPTY_DRAFT }]
                : prev.filter((_, i) => i !== index),
        );
    }

    function commitTag(index: number) {
        setColumns((prev) => {
            const col = prev[index]!;
            const tag = col.tagInput.trim();
            if (!tag || col.tags.includes(tag)) {
                return prev.map((c, i) =>
                    i === index ? { ...c, tagInput: "" } : c,
                );
            }
            return prev.map((c, i) =>
                i === index
                    ? { ...c, tags: [...c.tags, tag], tagInput: "" }
                    : c,
            );
        });
    }

    function handleTagKeyDown(
        e: React.KeyboardEvent<HTMLInputElement>,
        index: number,
    ) {
        if (e.key === "Enter" || e.key === ",") {
            e.preventDefault();
            commitTag(index);
        } else if (
            e.key === "Backspace" &&
            columns[index]!.tagInput === "" &&
            columns[index]!.tags.length > 0
        ) {
            updateColumn(index, {
                tags: columns[index]!.tags.slice(0, -1),
            });
        }
    }

    async function autoGeneratePrompt(index: number) {
        const title = columns[index]?.name?.trim() ?? "";
        if (!title) return;
        setGeneratingIndices((prev) => [...prev, index]);
        try {
            const col = columns[index]!;
            const { prompt } = await generateTabularColumnPrompt(title, {
                format: col.format,
                tags: col.format === "tag" ? col.tags : undefined,
            });
            updateColumn(index, { prompt });
        } finally {
            setGeneratingIndices((prev) => prev.filter((v) => v !== index));
        }
    }

    function handleSubmit(e: React.FormEvent) {
        e.preventDefault();
        if (columns.some((col) => !col.name.trim() || !col.prompt.trim()))
            return;
        if (isEditing && onSave && editingColumn) {
            const col = columns[0]!;
            onSave({
                index: editingColumn.index,
                name: col.name.trim(),
                prompt: col.prompt.trim(),
                format: col.format,
                tags: col.format === "tag" ? col.tags : undefined,
            });
        } else {
            onAdd(
                columns.map((col, i) => ({
                    index: existingCount + i,
                    name: col.name.trim(),
                    prompt: col.prompt.trim(),
                    format: col.format,
                    tags: col.format === "tag" ? col.tags : undefined,
                })),
            );
        }
        resetForm();
        onClose();
    }

    return createPortal(
        <div className="fixed inset-0 z-[101] flex items-center justify-center bg-black/20 backdrop-blur-xs">
            <div className="w-full max-w-2xl rounded-2xl bg-white shadow-2xl flex flex-col h-[600px]">
                {/* Header */}
                <div className="flex items-center justify-between px-6 pt-5 pb-2">
                    <div className="flex items-center gap-1.5 text-xs text-gray-400">
                        <span>Tabular Review</span>
                        <span>›</span>
                        <span>{isEditing ? "Edit column" : "New column"}</span>
                    </div>
                    <button
                        onClick={handleClose}
                        className="rounded-lg p-1.5 text-gray-400 hover:bg-gray-100 hover:text-gray-600 transition-colors"
                    >
                        <X className="h-4 w-4" />
                    </button>
                </div>

                <form
                    onSubmit={handleSubmit}
                    className="flex flex-col min-h-0 flex-1"
                >
                    {/* Body */}
                    <div className="px-6 pt-3 pb-5 space-y-5 overflow-y-auto flex-1">
                        {columns.map((column, index) => (
                            <div
                                key={index}
                                className="rounded-xl border border-gray-200 p-4"
                            >
                                {/* Name row */}
                                <div className="flex items-start gap-2">
                                    {/* Input + preset dropdown anchored to this wrapper */}
                                    <div
                                        className="relative flex flex-1 items-start"
                                        ref={
                                            presetsOpenIndex === index
                                                ? presetsRef
                                                : null
                                        }
                                    >
                                        <input
                                            type="text"
                                            value={column.name}
                                            onChange={(e) => {
                                                const name = e.target.value;
                                                const preset =
                                                    getPresetConfig(name);
                                                updateColumn(index, {
                                                    name,
                                                    ...(preset
                                                        ? {
                                                              prompt: preset.prompt,
                                                              format: preset.format,
                                                              tags:
                                                                  preset.tags ??
                                                                  [],
                                                              tagInput: "",
                                                          }
                                                        : {}),
                                                });
                                            }}
                                            placeholder="Column name"
                                            className="flex-1 text-2xl font-serif text-gray-800 placeholder-gray-400 focus:outline-none bg-transparent"
                                            autoFocus={index === 0}
                                        />
                                        <button
                                            type="button"
                                            onClick={() =>
                                                setPresetsOpenIndex(
                                                    presetsOpenIndex === index
                                                        ? null
                                                        : index,
                                                )
                                            }
                                            title="Column presets"
                                            className="mt-1.5 rounded-lg p-1.5 text-gray-500 transition-colors hover:bg-gray-100 hover:text-gray-700"
                                        >
                                            <ChevronDown
                                                className={`h-4 w-4 transition-transform ${presetsOpenIndex === index ? "rotate-180" : ""}`}
                                            />
                                        </button>
                                        {presetsOpenIndex === index && (
                                            <div className="absolute left-0 right-0 top-full mt-1 z-50 rounded-xl border border-gray-100 bg-white shadow-lg overflow-y-auto max-h-64">
                                                <button
                                                    type="button"
                                                    onClick={() => {
                                                        updateColumn(index, { ...EMPTY_DRAFT });
                                                        setPresetsOpenIndex(null);
                                                    }}
                                                    className="w-full px-3 py-2 text-left text-sm text-gray-400 hover:bg-gray-50 transition-colors border-b border-gray-100"
                                                >
                                                    No Preset
                                                </button>
                                                {PROMPT_PRESETS.map(
                                                    (preset) => (
                                                        <button
                                                            key={preset.name}
                                                            type="button"
                                                            onClick={() => {
                                                                updateColumn(
                                                                    index,
                                                                    {
                                                                        name: preset.name,
                                                                        prompt: preset.prompt,
                                                                        format: preset.format,
                                                                        tags:
                                                                            preset.tags ??
                                                                            [],
                                                                        tagInput:
                                                                            "",
                                                                    },
                                                                );
                                                                setPresetsOpenIndex(
                                                                    null,
                                                                );
                                                            }}
                                                            className="w-full px-3 py-2 text-left text-sm text-gray-700 hover:bg-gray-50 transition-colors"
                                                        >
                                                            {preset.name}
                                                        </button>
                                                    ),
                                                )}
                                            </div>
                                        )}
                                    </div>
                                    {columns.length > 1 && (
                                        <button
                                            type="button"
                                            onClick={() => removeColumn(index)}
                                            className="mt-1.5 rounded-lg p-1.5 text-gray-300 transition-colors hover:bg-gray-100 hover:text-gray-500"
                                        >
                                            <X className="h-4 w-4" />
                                        </button>
                                    )}
                                </div>

                                {/* Format */}
                                <div className="mt-4">
                                    <label className="text-sm font-medium text-gray-500">
                                        Format
                                    </label>
                                    <DropdownMenu>
                                        <DropdownMenuTrigger asChild>
                                            <button className="mt-1 flex items-center justify-between rounded-md border border-gray-200 bg-white px-2 py-1.5 text-sm text-gray-700 hover:border-gray-400 focus:outline-none">
                                                <span className="flex items-center gap-2">
                                                    {(() => {
                                                        const Icon = formatIcon(
                                                            column.format,
                                                        );
                                                        return (
                                                            <Icon className="h-3.5 w-3.5 text-gray-400" />
                                                        );
                                                    })()}
                                                    {formatLabel(column.format)}
                                                </span>
                                                <ChevronDown className="h-3.5 w-3.5 text-gray-400" />
                                            </button>
                                        </DropdownMenuTrigger>
                                        <DropdownMenuContent
                                            align="start"
                                            className="z-[200]"
                                        >
                                            <DropdownMenuRadioGroup
                                                value={column.format}
                                                onValueChange={(v) =>
                                                    updateColumn(index, {
                                                        format: v as ColumnFormat,
                                                        tags: [],
                                                        tagInput: "",
                                                    })
                                                }
                                            >
                                                {FORMAT_OPTIONS.map((o) => (
                                                    <DropdownMenuRadioItem
                                                        key={o.value}
                                                        value={o.value}
                                                    >
                                                        <o.icon className="h-3.5 w-3.5 text-gray-400" />
                                                        {o.label}
                                                    </DropdownMenuRadioItem>
                                                ))}
                                            </DropdownMenuRadioGroup>
                                        </DropdownMenuContent>
                                    </DropdownMenu>
                                </div>

                                {/* Tag input */}
                                {column.format === "tag" && (
                                    <div className="mt-3">
                                        <label className="text-sm font-medium text-gray-500">
                                            Tags
                                        </label>
                                        <div className="mt-1 flex flex-wrap gap-1.5 rounded-md border border-gray-200 px-2 py-1.5 focus-within:border-gray-400">
                                            {column.tags.map((tag, tagIdx) => (
                                                <span
                                                    key={tag}
                                                    className={`inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs ${TAG_COLORS[tagIdx % TAG_COLORS.length]}`}
                                                >
                                                    {tag}
                                                    <button
                                                        type="button"
                                                        onClick={() =>
                                                            updateColumn(
                                                                index,
                                                                {
                                                                    tags: column.tags.filter(
                                                                        (t) =>
                                                                            t !==
                                                                            tag,
                                                                    ),
                                                                },
                                                            )
                                                        }
                                                        className="text-gray-400 hover:text-gray-600"
                                                    >
                                                        <X className="h-2.5 w-2.5" />
                                                    </button>
                                                </span>
                                            ))}
                                            <input
                                                type="text"
                                                value={column.tagInput}
                                                onChange={(e) =>
                                                    updateColumn(index, {
                                                        tagInput:
                                                            e.target.value,
                                                    })
                                                }
                                                onKeyDown={(e) =>
                                                    handleTagKeyDown(e, index)
                                                }
                                                onBlur={() => commitTag(index)}
                                                placeholder="Add tag…"
                                                className="min-w-[80px] flex-1 bg-transparent text-sm text-gray-700 placeholder-gray-400 focus:outline-none"
                                            />
                                        </div>
                                        <p className="mt-1 text-xs text-gray-400">
                                            Press Enter or comma to add a tag.
                                        </p>
                                    </div>
                                )}

                                {/* Prompt */}
                                <div className="mt-4 flex items-center justify-between">
                                    <label className="text-sm font-medium text-gray-500">
                                        Prompt
                                    </label>
                                    <button
                                        type="button"
                                        onClick={() =>
                                            autoGeneratePrompt(index)
                                        }
                                        disabled={
                                            !column.name.trim() ||
                                            generatingIndices.includes(index)
                                        }
                                        className="inline-flex items-center gap-1.5 text-sm text-gray-500 transition-colors hover:text-gray-900 disabled:text-gray-300"
                                    >
                                        {generatingIndices.includes(index) ? (
                                            <span className="h-4 w-4 rounded-full border-2 border-gray-300 border-t-gray-600 animate-spin block" />
                                        ) : (
                                            <Plus className="h-4 w-4" />
                                        )}
                                        Auto-Generate Prompt
                                    </button>
                                </div>
                                <textarea
                                    rows={6}
                                    value={column.prompt}
                                    onChange={(e) =>
                                        updateColumn(index, {
                                            prompt: e.target.value,
                                        })
                                    }
                                    placeholder="Write the analysis prompt — describe what Mike should extract from each document for this column…"
                                    className="mt-2 w-full rounded-md border border-gray-200 px-3 py-2 text-sm text-gray-700 placeholder-gray-400 focus:border-gray-400 focus:outline-none bg-transparent resize-none leading-relaxed"
                                />
                            </div>
                        ))}

                        {!isEditing && (
                            <button
                                type="button"
                                onClick={addAnotherColumn}
                                className="inline-flex items-center gap-1.5 text-sm text-gray-500 transition-colors hover:text-gray-900"
                            >
                                <Plus className="h-4 w-4" />
                                Add another column
                            </button>
                        )}
                    </div>

                    {/* Footer */}
                    <div className="flex items-center justify-between border-t border-gray-100 px-6 py-4">
                        <div>
                            {isEditing && onDelete && (
                                <button
                                    type="button"
                                    onClick={onDelete}
                                    className="rounded-lg px-4 py-2 text-sm text-red-500 hover:bg-red-50 transition-colors"
                                >
                                    Delete
                                </button>
                            )}
                        </div>
                        <div className="flex items-center gap-2">
                            <button
                                type="button"
                                onClick={handleClose}
                                className="rounded-lg px-4 py-2 text-sm text-gray-500 hover:bg-gray-100 transition-colors"
                            >
                                Cancel
                            </button>
                            <button
                                type="submit"
                                disabled={columns.some(
                                    (col) => !col.name.trim() || !col.prompt.trim(),
                                )}
                                className="rounded-lg bg-gray-900 px-5 py-2 text-sm font-medium text-white hover:bg-gray-700 disabled:opacity-40 transition-colors"
                            >
                                {isEditing ? "Save changes" : "Add columns"}
                            </button>
                        </div>
                    </div>
                </form>
            </div>
        </div>,
        document.body,
    );
}
