import { useState, useCallback } from "react";
import type { ToolResult } from "../../core/io/output-types";

interface ToolResultPanelTints {
  neon: string;
}

export function ToolResultPanel({
  result,
  dark,
  tints,
}: {
  result: ToolResult;
  dark?: boolean;
  tints?: ToolResultPanelTints;
}) {
  const [copied, setCopied] = useState(false);
  const isDark = dark ?? false;

  const handleCopy = useCallback((text: string) => {
    navigator.clipboard.writeText(text);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  }, []);

  const downloadBlob = useCallback((blob: Blob, filename: string) => {
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  }, []);

  const previewBlob = useCallback((blob: Blob) => {
    const url = URL.createObjectURL(blob);
    window.open(url, "_blank", "noopener,noreferrer");
    // The new tab keeps the blob alive; revoke after it has loaded.
    setTimeout(() => URL.revokeObjectURL(url), 60_000);
  }, []);

  const canPreview = (mimeType: string) =>
    mimeType === "application/pdf" ||
    mimeType.startsWith("image/") ||
    mimeType.startsWith("text/");

  if (result.type === "text") {
    return (
      <div 
        className="flex flex-col gap-[10px] rounded-[14px] border border-[var(--p-border)] p-[16px] min-h-[240px]"
        style={{
          background: isDark ? `color-mix(in oklab, ${tints?.neon || 'var(--p-accent)'} 4%, transparent)` : 'var(--p-surface-2)',
        }}
      >
        <div className="flex items-center justify-between font-mono text-[10px] text-[var(--p-muted)] tracking-wider uppercase">
          <span>output</span>
          {result.value && (
            <button
              onClick={() => handleCopy(result.value)}
              className="px-2 py-1 rounded-md bg-[var(--p-chip)] text-[var(--p-muted)] cursor-pointer hover:bg-[var(--p-border)] transition-colors"
            >
              {copied ? "Copied!" : "Copy"}
            </button>
          )}
        </div>
        <div className="flex-1 overflow-auto font-mono text-[13px] text-[var(--p-text)] whitespace-pre-wrap break-words">
          {result.value || ""}
        </div>
      </div>
    );
  }

  if (result.type === "json") {
    const value = result.value;
    const isObject = typeof value === "object" && value !== null && !Array.isArray(value);
    const valObj = isObject ? (value as Record<string, unknown>) : null;
    const primaryVal = valObj && "primary" in valObj ? String(valObj.primary) : null;

    // Filter out 'primary' from the fields displayed in the grid
    const fields = valObj
      ? Object.entries(valObj).filter(([key]) => key !== "primary")
      : [];

    return (
      <div className="flex flex-col gap-[16px]">
        {primaryVal !== null && (
          <div 
            className="flex flex-col gap-[8px] p-[20px] rounded-[14px] border border-[var(--p-border)] bg-[var(--p-surface)] relative group/primary overflow-hidden"
            style={{
              boxShadow: 'inset 0 1px 0 var(--p-shadow-inset)',
            }}
          >
            <div className="font-mono text-[10px] text-[var(--p-accent)] tracking-wider uppercase font-semibold">
              Primary Result
            </div>
            <div className="flex items-center justify-between gap-[16px]">
              <div className="font-mono text-[20px] font-bold text-[var(--p-text)] break-all select-all">
                {primaryVal}
              </div>
              <button
                onClick={() => handleCopy(primaryVal)}
                className="px-3 py-1.5 rounded-lg bg-[var(--p-accent)] text-[var(--p-accent-ink)] font-sans text-[12px] font-semibold cursor-pointer hover:opacity-90 transition-opacity whitespace-nowrap"
              >
                Copy
              </button>
            </div>
          </div>
        )}

        <div 
          className="flex flex-col gap-[10px] rounded-[14px] border border-[var(--p-border)] p-[16px] min-h-[160px]"
          style={{
            background: isDark ? `color-mix(in oklab, ${tints?.neon || 'var(--p-accent)'} 4%, transparent)` : 'var(--p-surface-2)',
          }}
        >
          <div className="flex items-center justify-between font-mono text-[10px] text-[var(--p-muted)] tracking-wider uppercase mb-2">
            <span>{primaryVal !== null ? "All Conversions / Details" : "output"}</span>
            {!primaryVal && (
              <button
                onClick={() => handleCopy(JSON.stringify(value, null, 2))}
                className="px-2 py-1 rounded-md bg-[var(--p-chip)] text-[var(--p-muted)] cursor-pointer hover:bg-[var(--p-border)] transition-colors"
              >
                {copied ? "Copied!" : "Copy"}
              </button>
            )}
          </div>
          <div className="flex-1 overflow-auto font-mono text-[13px] text-[var(--p-text)] whitespace-pre-wrap break-words">
            {isObject ? (
              <div className="grid grid-cols-1 gap-[10px]">
                {fields.map(([key, val]) => {
                  const valStr = typeof val === "object" && val !== null ? JSON.stringify(val) : String(val ?? "null");
                  const isValObject = typeof val === "object" && val !== null;
                  return (
                    <div 
                      key={key} 
                      className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-[8px] p-[12px] rounded-[10px] bg-[var(--p-surface)] border border-[var(--p-border)] group/field hover:border-[var(--p-muted)]/30 transition-all"
                    >
                      <div className="flex flex-col gap-[2px] flex-grow min-w-0">
                        <span className="text-[var(--p-muted)] text-[9px] uppercase tracking-wider font-bold">{key}</span>
                        {isValObject ? (
                          <div className="pl-2 border-l border-[var(--p-border)] mt-1">
                            {renderJsonValue(val)}
                          </div>
                        ) : (
                          <span className="text-[var(--p-text)] text-[13px] font-mono break-all">{valStr}</span>
                        )}
                      </div>
                      {!isValObject && (
                        <button
                          onClick={() => handleCopy(valStr)}
                          className="sm:opacity-0 group-hover/field:opacity-100 focus-visible:opacity-100 self-end sm:self-auto px-2 py-1 rounded bg-[var(--p-chip)] text-[var(--p-muted)] text-[11px] cursor-pointer hover:bg-[var(--p-border)] transition-all whitespace-nowrap"
                        >
                          Copy
                        </button>
                      )}
                    </div>
                  );
                })}
              </div>
            ) : (
              renderJsonValue(value)
            )}
          </div>
        </div>
      </div>
    );
  }

  if (result.type === "files" && result.files) {
    return (
      <div 
        className="flex flex-col gap-[10px] rounded-[14px] border border-[var(--p-border)] p-[16px]"
        style={{
          background: isDark ? `color-mix(in oklab, ${tints?.neon || 'var(--p-accent)'} 4%, transparent)` : 'var(--p-surface-2)',
        }}
      >
        <div className="font-mono text-[10px] text-[var(--p-muted)] tracking-wider uppercase mb-2">
          output files
        </div>
        <ul className="flex flex-col gap-2 m-0 p-0 list-none">
          {result.files.map((file, i) => (
            <li key={i} className="flex items-center justify-between p-3 rounded-xl bg-[var(--p-surface)] border border-[var(--p-border)]">
              <div className="flex flex-col gap-1">
                <span className="font-sans text-[13px] text-[var(--p-text)] font-medium">
                  {file.name}
                </span>
                <span className="font-mono text-[10px] text-[var(--p-muted)]">
                  {file.sizeAfter ? `${(file.sizeAfter / 1024).toFixed(1)} KB` : 'Ready'}
                </span>
              </div>
              <div className="flex items-center gap-2">
                {canPreview(file.mimeType) && (
                  <button
                    onClick={() => previewBlob(file.blob)}
                    className="px-3 py-1.5 rounded-lg bg-[var(--p-surface-2)] text-[var(--p-text)] border border-[var(--p-border)] font-sans text-xs font-semibold cursor-pointer"
                  >
                    Preview
                  </button>
                )}
                <button
                  onClick={() => downloadBlob(file.blob, file.name)}
                  className="px-3 py-1.5 rounded-lg bg-[var(--p-accent)] text-[var(--p-accent-ink)] font-sans text-xs font-semibold cursor-pointer"
                >
                  Download
                </button>
              </div>
            </li>
          ))}
        </ul>
      </div>
    );
  }

  if (result.type === "table" && result.columns && result.rows) {
    return (
      <div 
        className="flex flex-col gap-[10px] rounded-[14px] border border-[var(--p-border)] p-[16px] overflow-hidden"
        style={{
          background: isDark ? `color-mix(in oklab, ${tints?.neon || 'var(--p-accent)'} 4%, transparent)` : 'var(--p-surface-2)',
        }}
      >
        <div className="flex items-center justify-between font-mono text-[10px] text-[var(--p-muted)] tracking-wider uppercase">
          <span>output table</span>
          <button
            onClick={() => {
              const csv = [
                result.columns.join(","),
                ...result.rows.map(row => row.map(cell => `"${String(cell ?? "").replace(/"/g, '""')}"`).join(","))
              ].join("\n");
              handleCopy(csv);
            }}
            className="px-2 py-1 rounded-md bg-[var(--p-chip)] text-[var(--p-muted)] cursor-pointer hover:bg-[var(--p-border)] transition-colors"
          >
            Copy CSV
          </button>
        </div>
        <div className="overflow-x-auto w-full max-h-[400px] mt-2">
          <table className="w-full border-collapse text-left font-sans text-[13px] text-[var(--p-text)]">
            <thead>
              <tr className="border-b border-[var(--p-border)]">
                {result.columns.map((col, i) => (
                  <th key={i} className="pb-[8px] pr-[12px] font-semibold text-[var(--p-muted)] uppercase tracking-wider text-[10px] font-mono">
                    {col}
                  </th>
                ))}
              </tr>
            </thead>
            <tbody>
              {result.rows.map((row, rIndex) => (
                <tr 
                  key={rIndex} 
                  className="border-b border-[var(--p-border)] last:border-none hover:bg-[var(--p-chip)]/30 transition-colors"
                >
                  {row.map((cell, cIndex) => (
                    <td key={cIndex} className="py-[10px] pr-[12px] font-mono text-[12px] text-[var(--p-text)]">
                      {cell === null ? (
                        <span className="text-[var(--p-muted)] italic">null</span>
                      ) : (
                        String(cell)
                      )}
                    </td>
                  ))}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    );
  }

  return null;
}

function renderJsonValue(value: unknown): React.ReactNode {
  if (value === null || value === undefined) return "null";
  if (typeof value === "string") return value;
  if (typeof value === "number" || typeof value === "boolean") return String(value);

  if (Array.isArray(value)) {
    if (value.length === 0) return "[]";
    return (
      <div className="flex flex-col gap-1">
        {value.map((item, i) => (
          <div key={i} className="pl-3 border-l-2 border-[var(--p-border)]">
            {renderJsonValue(item)}
          </div>
        ))}
      </div>
    );
  }

  if (typeof value === "object") {
    const entries = Object.entries(value as Record<string, unknown>);
    if (entries.length === 0) return "{}";
    return (
      <div className="flex flex-col gap-1.5">
        {entries.map(([key, val]) => (
          <div key={key} className="flex flex-col gap-0.5">
            <span className="text-[var(--p-muted)] text-[11px] uppercase tracking-wider">{key}</span>
            <div className="pl-3">
              {typeof val === "object" && val !== null ? (
                renderJsonValue(val)
              ) : (
                <span className="text-[var(--p-text)]">{String(val ?? "null")}</span>
              )}
            </div>
          </div>
        ))}
      </div>
    );
  }

  return String(value);
}
