import { Suspense, useCallback, useEffect, useState } from "react";
import type { ToolInput } from "../../core/io/input-types";
import type {
  ToolOptionsValue,
  UnknownPlimiPlugin,
} from "../../core/plugins/plugin-types";
import { describeToolPermissions } from "../../core/plugins/plugin-permissions";
import { normalizeToolOptions } from "../../core/plugins/plugin-validation";
import { ToolInputPanel } from "./ToolInputPanel";
import { ToolOptionsPanel } from "./ToolOptionsPanel";
import { ToolResultPanel } from "./ToolResultPanel";
import { ToolProgress } from "./ToolProgress";
import { useToolExecution } from "./useToolExecution";
import { CategoryIcon } from "../ui/CategoryIcon";
import { getPluginExamples } from "../../core/plugins/plugin-examples";
import { ExampleActionButton } from "./ExampleActionButton";

const TINTS: Record<string, { paper: string; ink: string; neon: string }> = {
  image: { paper: "#E8F5E9", ink: "#2E7D32", neon: "#69F0AE" },
  pdf: { paper: "#FFEBEE", ink: "#C62828", neon: "#FF5252" },
  developer: { paper: "#E3F2FD", ink: "#1565C0", neon: "#448AFF" },
  text: { paper: "#FFF8E1", ink: "#F57F17", neon: "#FFD740" },
  crypto: { paper: "#F3E5F5", ink: "#6A1B9A", neon: "#E040FB" },
  privacy: { paper: "#E0F2F1", ink: "#00695C", neon: "#64FFDA" },
};

function ToolHeader({
  plugin,
  dark,
  onClose,
}: {
  plugin: UnknownPlimiPlugin;
  dark: boolean;
  onClose?: () => void;
}) {
  const tints = TINTS[plugin.manifest.category] || TINTS.developer;
  const permissions = describeToolPermissions(plugin);

  return (
    <div className="flex items-center justify-between gap-3 border-b border-[var(--p-border)] bg-[var(--p-surface)] px-[18px] py-[14px] md:px-[24px] md:py-[20px]">
      <div className="flex min-w-0 items-center gap-[14px]">
        <span
          className="inline-flex h-[36px] w-[36px] shrink-0 items-center justify-center rounded-[12px] md:h-[44px] md:w-[44px]"
          style={{
            background: dark
              ? `color-mix(in oklab, ${tints.neon} 12%, transparent)`
              : tints.paper,
          }}
        >
          <CategoryIcon
            category={plugin.manifest.category}
            color={dark ? tints.neon : tints.ink}
            size={24}
            strokeWidth={2}
            aria-hidden="true"
          />
        </span>
        <div className="min-w-0">
          <div className="truncate font-sans text-[15px] font-semibold tracking-tight text-[var(--p-text)] md:text-[18px]">
            {plugin.manifest.name}
          </div>
          <div className="truncate font-mono text-[11px] uppercase tracking-wider text-[var(--p-muted)]">
            {plugin.manifest.category} / {permissions.join(" / ")}
          </div>
        </div>
      </div>

      {onClose && (
        <button
          onClick={onClose}
          className="shrink-0 rounded-lg bg-[var(--p-chip)] px-3 py-2 font-sans text-[13px] text-[var(--p-muted)] cursor-pointer"
        >
          Close
        </button>
      )}
    </div>
  );
}

export function ToolShell({
  plugin,
  onClose,
  dark,
}: {
  plugin: UnknownPlimiPlugin;
  onClose?: () => void;
  dark?: boolean;
}) {
  const [input, setInput] = useState<ToolInput>({});
  const [options, setOptions] = useState<ToolOptionsValue>({});
  const [runWarning, setRunWarning] = useState<string | null>(null);
  const { run, cancel, result, isExecuting, progress, error } =
    useToolExecution(plugin);

  const tints = TINTS[plugin.manifest.category] || TINTS.developer;
  const isDark = dark ?? false;
  const examples = getPluginExamples(plugin);
  const primaryExample = examples[0];

  const handleRun = useCallback(async () => {
    const normalizedOptions = normalizeToolOptions(plugin.optionsSchema, options);
    if (plugin.getRunWarning) {
      const warning = await plugin.getRunWarning(input, normalizedOptions);
      if (warning) {
        setRunWarning(warning);
        return;
      }
    }
    await run(input, normalizedOptions);
  }, [input, options, run, plugin]);

  const handleConfirmRun = useCallback(async () => {
    setRunWarning(null);
    const normalizedOptions = normalizeToolOptions(plugin.optionsSchema, options);
    await run(input, normalizedOptions);
  }, [input, options, run, plugin]);

  const handleApplyExample = useCallback(() => {
    if (!primaryExample) return;

    setInput(primaryExample.input);
    if (primaryExample.options) {
      const exampleOptions = Object.fromEntries(
        Object.entries(primaryExample.options).filter(([, value]) => value !== undefined)
      ) as ToolOptionsValue;

      setOptions((currentOptions) => ({
        ...currentOptions,
        ...exampleOptions,
      }));
    }
  }, [primaryExample]);

  useEffect(() => {
    if (plugin.capabilities?.customUi && plugin.customUi) {
      return;
    }

    const handleKeyDown = (e: KeyboardEvent) => {
      if ((e.ctrlKey || e.metaKey) && e.key === "Enter") {
        e.preventDefault();
        if (!isExecuting) {
          handleRun();
        }
      }
    };

    window.addEventListener("keydown", handleKeyDown);
    return () => {
      window.removeEventListener("keydown", handleKeyDown);
    };
  }, [handleRun, isExecuting, plugin]);

  if (plugin.capabilities?.customUi && plugin.customUi) {
    const CustomUi = plugin.customUi;

    return (
      <>
        <ToolHeader plugin={plugin} dark={isDark} onClose={onClose} />
        <div className="min-h-0 flex-1 overflow-y-auto bg-[var(--p-surface)]">
          <Suspense
            fallback={
              <div className="p-6 font-sans text-sm text-[var(--p-muted)]">
                Loading tool...
              </div>
            }
          >
            <CustomUi plugin={plugin} dark={isDark} examples={examples} />
          </Suspense>
        </div>
      </>
    );
  }

  return (
    <>
      <ToolHeader plugin={plugin} dark={isDark} onClose={onClose} />

      <div
        className={`flex min-h-0 flex-1 flex-col gap-[16px] overflow-y-auto bg-[var(--p-surface)] p-[18px] md:grid md:gap-[24px] md:p-[28px] ${
          plugin.optionsSchema ? "md:grid-cols-[1fr_300px]" : "md:grid-cols-1"
        }`}
      >
        <div className="order-1 flex flex-col gap-[24px] md:col-start-1 md:row-start-1">
          <ToolInputPanel
            definition={plugin.manifest.input}
            value={input}
            onChange={setInput}
            dark={isDark}
            tints={tints}
          />
        </div>

        {plugin.optionsSchema && (
          <div className="order-2 md:col-start-2 md:row-start-1 md:row-span-2">
            <ToolOptionsPanel
              schema={plugin.optionsSchema}
              value={options}
              onChange={setOptions}
              dark={isDark}
              tints={tints}
              toolCategory={plugin.manifest.category}
            />
          </div>
        )}

        <div className="order-3 flex flex-col gap-[24px] empty:hidden md:col-start-1 md:row-start-2">
          {isExecuting && (
            <ToolProgress
              percentage={progress.percentage ?? 0}
              message={progress.message}
              onCancel={plugin.capabilities?.cancelable ? cancel : undefined}
              dark={isDark}
              tints={tints}
            />
          )}

          {error && (
            <div className="rounded-xl border border-red-200 bg-red-100 p-4 font-sans text-sm text-red-800">
              <strong>Error:</strong> {error}
            </div>
          )}

          {result && !isExecuting && (
            <ToolResultPanel result={result} dark={isDark} tints={tints} />
          )}
        </div>
      </div>

      <div className="flex items-center justify-between gap-3 border-t border-[var(--p-border)] bg-[var(--p-surface)] px-[18px] py-[12px] pb-[max(12px,env(safe-area-inset-bottom))] md:px-[24px] md:py-[14px]">
        <span className="font-mono text-[11px] text-[var(--p-muted)]">
          ready when you are
        </span>
        <div className="flex shrink-0 items-center gap-2">
          {primaryExample && (
            <ExampleActionButton
              label={primaryExample.label}
              disabled={isExecuting}
              onClick={handleApplyExample}
            />
          )}
          <button
            onClick={handleRun}
            disabled={isExecuting}
            className="cursor-pointer rounded-[10px] bg-[var(--p-accent)] px-[18px] py-[10px] font-sans text-[13px] font-semibold tracking-tight text-[var(--p-accent-ink)] transition-opacity disabled:cursor-not-allowed disabled:opacity-50"
          >
            {isExecuting ? "Running..." : `Run ${plugin.manifest.name.split(" ")[0]}`}
          </button>
        </div>
      </div>

      {runWarning && (
        <div
          role="presentation"
          onClick={() => setRunWarning(null)}
          className="fixed inset-0 z-[60] flex items-center justify-center p-4 animate-plimi-fade"
          style={{
            background: "color-mix(in oklab, var(--p-bg) 60%, transparent)",
            backdropFilter: "blur(4px)",
          }}
        >
          <div
            role="alertdialog"
            aria-modal="true"
            aria-label="Confirm download"
            onClick={(e) => e.stopPropagation()}
            className="w-full max-w-[420px] rounded-[18px] border-[1.5px] border-[var(--p-border)] bg-[var(--p-surface)] p-[22px] animate-plimi-slide"
            style={{ boxShadow: "0 40px 80px -30px var(--p-shadow-soft)" }}
          >
            <div className="font-sans text-[16px] font-semibold tracking-tight text-[var(--p-text)]">
              One-time download
            </div>
            <p className="mt-2 mb-5 font-sans text-[13px] leading-relaxed text-[var(--p-muted)]">
              {runWarning}
            </p>
            <div className="flex justify-end gap-2">
              <button
                onClick={() => setRunWarning(null)}
                className="cursor-pointer rounded-[10px] bg-[var(--p-chip)] px-[16px] py-[9px] font-sans text-[13px] font-medium text-[var(--p-muted)]"
              >
                Cancel
              </button>
              <button
                onClick={handleConfirmRun}
                className="cursor-pointer rounded-[10px] bg-[var(--p-accent)] px-[16px] py-[9px] font-sans text-[13px] font-semibold text-[var(--p-accent-ink)]"
              >
                Download &amp; run
              </button>
            </div>
          </div>
        </div>
      )}
    </>
  );
}
