import {
  getInputValue,
  setInputValue,
  type ToolInput,
  type ToolInputDefinition,
  type ToolInputFieldDefinition,
} from "../../core/io/input-types";
import { Dropzone } from "../ui/Dropzone";

interface ToolInputPanelTints {
  paper: string;
  ink: string;
  neon: string;
}

export function ToolInputPanel({
  definition,
  value,
  onChange,
  dark,
  tints,
}: {
  definition: ToolInputDefinition;
  value: ToolInput;
  onChange: (val: ToolInput) => void;
  dark?: boolean;
  tints?: ToolInputPanelTints;
}) {
  const isDark = dark ?? false;

  const fields: ToolInputFieldDefinition[] =
    definition.type === "group"
      ? definition.fields
      : definition.type === "none"
        ? []
        : [definition];

  const handleTextChange = (fieldKey: string, newText: string) => {
    const prev = getInputValue(value, fieldKey);
    onChange(setInputValue(value, fieldKey, { ...prev, text: newText }));
  };

  const handleFilesChange = (fieldKey: string, files?: File[]) => {
    const prev = getInputValue(value, fieldKey);
    onChange(setInputValue(value, fieldKey, { ...prev, files }));
  };

  if (definition.type === "none") {
    return (
      <div
        className="flex min-h-[160px] flex-col justify-center rounded-[14px] border border-[var(--p-border)] p-[24px]"
        style={{
          background: isDark ? "var(--p-bg)" : "var(--p-surface-2)",
        }}
      >
        <div className="mb-[8px] font-mono text-[10px] uppercase tracking-wider text-[var(--p-muted)]">
          no input required
        </div>
        <p className="m-0 font-sans text-[14px] leading-[1.6] text-[var(--p-muted)]">
          This tool runs from its options only.
        </p>
      </div>
    );
  }

  const renderFileField = (
    field: Extract<ToolInputFieldDefinition, { type: "files" }>,
    index: number
  ) => {
    const fieldKey = field.key ?? "input";
    const fieldValue = getInputValue(value, fieldKey);

    return (
      <div
        key={`${fieldKey}-${index}`}
        className="flex min-h-[240px] flex-col rounded-[14px] border border-[var(--p-border)] p-[24px] transition-colors"
        style={{
          background: isDark ? "var(--p-bg)" : "var(--p-surface-2)",
        }}
      >
        <div className="mb-[16px] flex items-center justify-between font-mono text-[10px] uppercase tracking-wider text-[var(--p-muted)]">
          <span>{field.label ?? "input files"}</span>
        </div>

        {field.description && (
          <p className="mb-[16px] mt-0 font-sans text-[13px] text-[var(--p-muted)]">
            {field.description}
          </p>
        )}

        {fieldValue.files && fieldValue.files.length > 0 ? (
          <div className="flex flex-1 flex-col gap-[12px]">
            <ul className="m-0 flex max-h-[160px] list-none flex-col gap-[8px] overflow-y-auto p-0">
              {fieldValue.files.map((file, i) => (
                <li
                  key={i}
                  className="flex items-center justify-between rounded-[10px] border border-[var(--p-border)] bg-[var(--p-surface)] p-[12px]"
                >
                  <div className="flex items-center gap-[12px] overflow-hidden">
                    <svg
                      width="18"
                      height="18"
                      viewBox="0 0 24 24"
                      fill="none"
                      stroke="var(--p-muted)"
                      strokeWidth="2"
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      className="shrink-0"
                    >
                      <path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z" />
                      <polyline points="13 2 13 9 20 9" />
                    </svg>
                    <span className="truncate font-sans text-[13px] text-[var(--p-text)]">
                      {file.name}
                    </span>
                  </div>
                  <span className="ml-[12px] whitespace-nowrap font-mono text-[10px] text-[var(--p-muted)]">
                    {(file.size / 1024 / 1024).toFixed(2)} MB
                  </span>
                </li>
              ))}
            </ul>
            <div className="mt-auto flex justify-end pt-[12px]">
              <button
                onClick={() => handleFilesChange(fieldKey, undefined)}
                className="cursor-pointer rounded-lg bg-[var(--p-chip)] px-3 py-1.5 font-sans text-[12px] text-[var(--p-muted)] transition-colors hover:bg-[var(--p-border)]"
              >
                Clear files
              </button>
            </div>
          </div>
        ) : (
          <div
            className="flex flex-1 flex-col items-center justify-center rounded-[10px] border-2 border-dashed transition-colors"
            style={{
              borderColor: isDark
                ? `color-mix(in oklab, ${tints?.neon || "var(--p-accent)"} 30%, var(--p-border))`
                : `color-mix(in oklab, ${tints?.ink || "var(--p-accent)"} 25%, var(--p-border))`,
              background: isDark
                ? `color-mix(in oklab, ${tints?.neon || "var(--p-accent)"} 4%, transparent)`
                : `color-mix(in oklab, ${tints?.paper || "var(--p-bg)"} 40%, transparent)`,
            }}
          >
            <svg
              width="44"
              height="44"
              viewBox="0 0 24 24"
              fill="none"
              stroke={isDark ? (tints?.neon || "currentColor") : (tints?.ink || "currentColor")}
              strokeWidth="1.6"
              strokeLinecap="round"
              strokeLinejoin="round"
              className="mb-2"
            >
              <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
              <polyline points="17 8 12 3 7 8" />
              <line x1="12" y1="3" x2="12" y2="15" />
            </svg>
            <Dropzone
              accept={field.accept?.join(",")}
              multiple={field.multiple}
              maxFiles={field.maxFiles}
              maxSizeMb={field.maxSizeMb}
              onFilesDrop={(files) => handleFilesChange(fieldKey, files)}
              className="w-full flex-1 border-none"
            />
            <div className="mb-[24px] font-mono text-[10px] uppercase tracking-wider text-[var(--p-muted)]">
              processed in your browser
            </div>
          </div>
        )}
      </div>
    );
  };

  const renderTextField = (
    field: Extract<ToolInputFieldDefinition, { type: "text" | "text-or-files" }>,
    index: number
  ) => {
    const fieldKey = field.key ?? "input";
    const fieldValue = getInputValue(value, fieldKey);
    const placeholder =
      field.type === "text"
        ? (field.placeholder ?? "Enter input here...")
        : "Enter input here...";

    const isMultiline =
      field.type === "text-or-files" ||
      (field.type === "text" && field.multiline !== false);
    const rows = field.type === "text" ? field.rows : undefined;

    return (
      <div
        key={`${fieldKey}-${index}`}
        className={`flex flex-col gap-[10px] rounded-[14px] border border-[var(--p-border)] p-[16px] ${
          isMultiline ? "min-h-[160px]" : ""
        }`}
        style={{
          background: isDark ? "var(--p-bg)" : "var(--p-surface-2)",
        }}
      >
        <div className="flex items-center justify-between font-mono text-[10px] uppercase tracking-wider text-[var(--p-muted)]">
          <span>{field.label ?? "input"}</span>
          <span>{isMultiline ? "paste / drop / type" : "type"}</span>
        </div>
        {field.description && (
          <p className="m-0 font-sans text-[13px] text-[var(--p-muted)]">
            {field.description}
          </p>
        )}
        {isMultiline ? (
          <textarea
            className="w-full flex-1 resize-none border-none bg-transparent font-mono text-[13px] text-[var(--p-text)] outline-none placeholder:text-[var(--p-muted)] placeholder:opacity-50"
            placeholder={placeholder}
            value={fieldValue.text || ""}
            maxLength={field.type === "text" ? field.maxLength : undefined}
            onChange={(e) => handleTextChange(fieldKey, e.target.value)}
            spellCheck={false}
            rows={rows ?? 6}
          />
        ) : (
          <input
            type="text"
            className="w-full border-none bg-transparent py-1 font-mono text-[13px] text-[var(--p-text)] outline-none placeholder:text-[var(--p-muted)] placeholder:opacity-50"
            placeholder={placeholder}
            value={fieldValue.text || ""}
            maxLength={field.type === "text" ? field.maxLength : undefined}
            onChange={(e) => handleTextChange(fieldKey, e.target.value)}
            spellCheck={false}
          />
        )}
      </div>
    );
  };

  return (
    <div className="flex flex-col gap-[16px]">
      {fields.map((field, index) =>
        field.type === "files"
          ? renderFileField(field, index)
          : renderTextField(field, index)
      )}
    </div>
  );
}
