"use client";

import { useState } from "react";
import { FieldType } from "@capakraken/shared";
import type { BlueprintFieldDefinition, FieldOption, StaffingRequirement } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { RolePresetsEditor } from "./RolePresetsEditor.js";

const FIELD_TYPES: { value: FieldType; label: string }[] = [
  { value: FieldType.TEXT, label: "Text" },
  { value: FieldType.TEXTAREA, label: "Textarea" },
  { value: FieldType.NUMBER, label: "Number" },
  { value: FieldType.BOOLEAN, label: "Boolean" },
  { value: FieldType.DATE, label: "Date" },
  { value: FieldType.SELECT, label: "Select" },
  { value: FieldType.MULTI_SELECT, label: "Multi-Select" },
  { value: FieldType.URL, label: "URL" },
  { value: FieldType.EMAIL, label: "Email" },
];

const BTN_PRIMARY =
  "px-4 py-2 bg-brand-600 text-white rounded-lg hover:bg-brand-700 text-sm font-medium disabled:opacity-50";

const BTN_SECONDARY =
  "px-4 py-2 border border-gray-300 text-gray-700 rounded-lg hover:bg-gray-50 text-sm font-medium";

function makeEmptyField(order: number): BlueprintFieldDefinition {
  return {
    id: Math.random().toString(36).slice(2),
    key: "",
    label: "",
    type: FieldType.TEXT,
    required: false,
    order,
  };
}

// ---------------------------------------------------------------------------
// OptionsEditor — for SELECT / MULTI_SELECT
// ---------------------------------------------------------------------------
interface OptionsEditorProps {
  options: FieldOption[];
  onChange: (options: FieldOption[]) => void;
}

function OptionsEditor({ options, onChange }: OptionsEditorProps) {
  function addOption() {
    onChange([...options, { value: "", label: "" }]);
  }

  function removeOption(idx: number) {
    onChange(options.filter((_, i) => i !== idx));
  }

  function updateOption(idx: number, field: "value" | "label", val: string) {
    const next = options.map((o, i) =>
      i === idx ? { ...o, [field]: val } : o,
    );
    onChange(next);
  }

  return (
    <div className="mt-2 space-y-1.5">
      <p className="text-xs font-medium text-gray-600">Options</p>
      {options.map((opt, idx) => (
        <div key={idx} className="flex items-center gap-2">
          <input
            type="text"
            value={opt.value}
            onChange={(e) => updateOption(idx, "value", e.target.value)}
            placeholder="value"
            className="app-input flex-1"
          />
          <input
            type="text"
            value={opt.label}
            onChange={(e) => updateOption(idx, "label", e.target.value)}
            placeholder="label"
            className="app-input flex-1"
          />
          <button
            type="button"
            onClick={() => removeOption(idx)}
            className="app-action-danger-btn"
            aria-label="Remove option"
          >
            ×
          </button>
        </div>
      ))}
      <button
        type="button"
        onClick={addOption}
        className="text-xs text-brand-600 hover:text-brand-800 font-medium"
      >
        + Add option
      </button>
    </div>
  );
}

// ---------------------------------------------------------------------------
// FieldRow — a single field definition row
// ---------------------------------------------------------------------------
interface FieldRowProps {
  field: BlueprintFieldDefinition;
  onChange: (field: BlueprintFieldDefinition) => void;
  onDelete: () => void;
}

function FieldRow({ field, onChange, onDelete }: FieldRowProps) {
  const [expanded, setExpanded] = useState(false);

  const needsOptions =
    field.type === FieldType.SELECT || field.type === FieldType.MULTI_SELECT;

  function update<K extends keyof BlueprintFieldDefinition>(
    key: K,
    value: BlueprintFieldDefinition[K],
  ) {
    onChange({ ...field, [key]: value });
  }

  return (
    <div className="border border-gray-200 rounded-lg p-3 bg-white">
      {/* Main row */}
      <div className="flex flex-wrap items-center gap-2">
        {/* Drag handle placeholder */}
        <span className="text-gray-300 cursor-grab select-none text-lg leading-none">
          ☰
        </span>

        {/* Key */}
        <input
          type="text"
          value={field.key}
          onChange={(e) => update("key", e.target.value)}
          placeholder="field_key"
          className="app-input w-36 font-mono"
          aria-label="Field key"
        />

        {/* Label */}
        <input
          type="text"
          value={field.label}
          onChange={(e) => update("label", e.target.value)}
          placeholder="Label"
          className="app-input w-40"
          aria-label="Field label"
        />

        {/* Type */}
        <select
          value={field.type}
          onChange={(e) => {
            const t = e.target.value as FieldType;
            // Clear options when switching away from select types
            const clearedOptions =
              t === FieldType.SELECT || t === FieldType.MULTI_SELECT
                ? field.options ?? []
                : undefined;
            onChange({ ...field, type: t, options: clearedOptions } as BlueprintFieldDefinition);
          }}
          className="app-input w-36"
          aria-label="Field type"
        >
          {FIELD_TYPES.map((ft) => (
            <option key={ft.value} value={ft.value}>
              {ft.label}
            </option>
          ))}
        </select>

        {/* Required */}
        <label className="flex items-center gap-1.5 text-sm text-gray-700 cursor-pointer select-none whitespace-nowrap">
          <input
            type="checkbox"
            checked={field.required}
            onChange={(e) => update("required", e.target.checked)}
            className="w-4 h-4 rounded border-gray-300 text-brand-600 focus:ring-brand-500"
          />
          Req.
        </label>

        {/* Expand/Collapse optional fields */}
        <button
          type="button"
          onClick={() => setExpanded((v) => !v)}
          className="text-xs text-gray-400 hover:text-gray-600 ml-auto whitespace-nowrap"
          aria-label={expanded ? "Collapse options" : "Expand options"}
        >
          {expanded ? "▲ less" : "▼ more"}
        </button>

        {/* Delete */}
        <button
          type="button"
          onClick={onDelete}
          className="app-action-danger-btn"
          aria-label="Delete field"
        >
          ×
        </button>
      </div>

      {/* Expanded optional fields */}
      {expanded && (
        <div className="mt-3 grid grid-cols-1 sm:grid-cols-3 gap-2">
          <div className="flex flex-col gap-1">
            <label className="text-xs text-gray-500 font-medium">Group</label>
            <input
              type="text"
              value={field.group ?? ""}
              onChange={(e) => update("group", e.target.value || undefined)}
              placeholder="Section heading"
              className="app-input"
            />
          </div>
          <div className="flex flex-col gap-1">
            <label className="text-xs text-gray-500 font-medium">
              Placeholder
            </label>
            <input
              type="text"
              value={field.placeholder ?? ""}
              onChange={(e) =>
                update("placeholder", e.target.value || undefined)
              }
              placeholder="Placeholder text"
              className="app-input"
            />
          </div>
          <div className="flex flex-col gap-1">
            <label className="text-xs text-gray-500 font-medium">
              Description
            </label>
            <input
              type="text"
              value={field.description ?? ""}
              onChange={(e) =>
                update("description", e.target.value || undefined)
              }
              placeholder="Helper text"
              className="app-input"
            />
          </div>

          <div className="flex items-center gap-4 col-span-full pt-1">
            <label className="flex items-center gap-1.5 text-sm text-gray-700 cursor-pointer select-none">
              <input
                type="checkbox"
                checked={field.showInList ?? false}
                onChange={(e) => update("showInList", e.target.checked)}
                className="w-4 h-4 rounded border-gray-300 text-brand-600 focus:ring-brand-500"
              />
              Show in list view
            </label>
            <label className="flex items-center gap-1.5 text-sm text-gray-700 cursor-pointer select-none">
              <input
                type="checkbox"
                checked={field.isFilterable ?? false}
                onChange={(e) => update("isFilterable", e.target.checked)}
                className="w-4 h-4 rounded border-gray-300 text-brand-600 focus:ring-brand-500"
              />
              Filterable
            </label>
          </div>

          {needsOptions && (
            <div className="col-span-full">
              <OptionsEditor
                options={field.options ?? []}
                onChange={(opts) => update("options", opts)}
              />
            </div>
          )}
        </div>
      )}

      {/* Options inline hint when collapsed */}
      {!expanded && needsOptions && (field.options?.length ?? 0) === 0 && (
        <p className="mt-1 text-xs text-amber-600">
          No options defined yet — click ▼ more to add them.
        </p>
      )}
    </div>
  );
}

// ---------------------------------------------------------------------------
// BlueprintFieldEditor — the modal
// ---------------------------------------------------------------------------
interface BlueprintFieldEditorProps {
  blueprintId: string;
  blueprintName: string;
  initialFieldDefs: BlueprintFieldDefinition[];
  initialRolePresets?: StaffingRequirement[];
  initialTab?: "fields" | "presets";
  onClose: () => void;
}

export function BlueprintFieldEditor({
  blueprintId,
  blueprintName,
  initialFieldDefs,
  initialRolePresets = [],
  initialTab = "fields",
  onClose,
}: BlueprintFieldEditorProps) {
  const utils = trpc.useUtils();

  const [activeTab, setActiveTab] = useState<"fields" | "presets">(initialTab);
  const [fields, setFields] = useState<BlueprintFieldDefinition[]>(
    () =>
      [...initialFieldDefs].sort((a, b) => a.order - b.order),
  );
  const [saveError, setSaveError] = useState<string | null>(null);
  const [presetSaveError, setPresetSaveError] = useState<string | null>(null);

  const updateMutation = trpc.blueprint.update.useMutation();

  const presetMutation = trpc.blueprint.updateRolePresets.useMutation();

  function addField() {
    setFields((prev) => [...prev, makeEmptyField(prev.length)]);
  }

  function removeField(idx: number) {
    setFields((prev) =>
      prev
        .filter((_, i) => i !== idx)
        .map((f, i) => ({ ...f, order: i })),
    );
  }

  function updateField(idx: number, updated: BlueprintFieldDefinition) {
    setFields((prev) =>
      prev.map((f, i) => (i === idx ? updated : f)),
    );
  }

  function handleSave() {
    setSaveError(null);
    // Reassign order by current list position
    const normalised = fields.map((f, i) => ({ ...f, order: i }));
    updateMutation.mutate(
      {
        id: blueprintId,
        data: { fieldDefs: normalised },
      },
      {
        onSuccess: async () => {
          await utils.blueprint.list.invalidate();
          onClose();
        },
        onError: (err) => {
          setSaveError(err.message);
        },
      },
    );
  }

  // Close on backdrop click
  function handleBackdropClick(e: React.MouseEvent<HTMLDivElement>) {
    if (e.target === e.currentTarget) onClose();
  }

  return (
    <div
      className="fixed inset-0 bg-black/50 z-50 flex items-start justify-center overflow-y-auto py-8"
      onClick={handleBackdropClick}
    >
      <div className="bg-white rounded-xl shadow-2xl w-full max-w-3xl mx-4">
        {/* Header */}
        <div className="flex items-center justify-between px-6 py-4 border-b border-gray-200">
          <h2 className="text-lg font-semibold text-gray-900">
            Edit Fields:{" "}
            <span className="text-gray-600 font-normal">{blueprintName}</span>
          </h2>
          <button
            type="button"
            onClick={onClose}
            className="text-gray-400 hover:text-gray-600 text-2xl leading-none"
            aria-label="Close"
          >
            ×
          </button>
        </div>

        {/* Tabs */}
        <div className="flex border-b border-gray-200 px-6">
          {(["fields", "presets"] as const).map((tab) => (
            <button
              key={tab}
              type="button"
              onClick={() => setActiveTab(tab)}
              className={`px-4 py-2.5 text-sm font-medium border-b-2 -mb-px transition-colors ${
                activeTab === tab
                  ? "border-brand-500 text-brand-600"
                  : "border-transparent text-gray-500 hover:text-gray-700"
              }`}
            >
              {tab === "fields" ? "Fields" : "Role Presets"}
            </button>
          ))}
        </div>

        {activeTab === "fields" ? (
          <>
            {/* Field list */}
            <div className="px-6 py-4 space-y-3 max-h-[60vh] overflow-y-auto">
              {fields.length === 0 && (
                <p className="text-sm text-gray-400 text-center py-8">
                  No fields yet. Click &ldquo;+ Add Field&rdquo; to get started.
                </p>
              )}
              {fields.map((field, idx) => (
                <FieldRow
                  key={field.id}
                  field={field}
                  onChange={(updated) => updateField(idx, updated)}
                  onDelete={() => removeField(idx)}
                />
              ))}
            </div>

            {/* Add field button */}
            <div className="px-6 pb-2">
              <button
                type="button"
                onClick={addField}
                className="flex items-center gap-1.5 text-sm text-brand-600 hover:text-brand-800 font-medium"
              >
                <span className="text-lg leading-none">+</span> Add Field
              </button>
            </div>

            {/* Error */}
            {saveError && (
              <div className="mx-6 mb-2 px-3 py-2 bg-red-50 border border-red-200 rounded-lg text-sm text-red-700">
                {saveError}
              </div>
            )}

            {/* Footer */}
            <div className="flex items-center justify-end gap-3 px-6 py-4 border-t border-gray-200">
              <button type="button" onClick={onClose} className={BTN_SECONDARY}>
                Cancel
              </button>
              <button
                type="button"
                onClick={handleSave}
                disabled={updateMutation.isPending}
                className={BTN_PRIMARY}
              >
                {updateMutation.isPending ? "Saving…" : "Save Fields"}
              </button>
            </div>
          </>
        ) : (
          <div className="px-6 py-4">
            <p className="text-xs text-gray-500 mb-4">
              Role presets are auto-loaded in Step 3 of the Project Creation Wizard when this blueprint is selected.
            </p>
            <RolePresetsEditor
              initialPresets={initialRolePresets}
              onSave={(presets) =>
                presetMutation.mutate(
                  { id: blueprintId, rolePresets: presets },
                  {
                    onSuccess: async () => {
                      await utils.blueprint.list.invalidate();
                      setPresetSaveError(null);
                      onClose();
                    },
                    onError: (err) => {
                      setPresetSaveError(err.message);
                    },
                  },
                )
              }
              isSaving={presetMutation.isPending}
              saveError={presetSaveError}
            />
            <div className="flex justify-start mt-4 border-t border-gray-200 pt-4">
              <button type="button" onClick={onClose} className={BTN_SECONDARY}>
                Close
              </button>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}
