"use client";

/**
 * Right-pane table preview. Shows the first ~50 rows of the selected
 * table as a compact data grid. Cells longer than 200 chars are
 * truncated server-side; we render the rest as-is. Read-only.
 */

import { useEffect, useState } from "react";
import { Loader2, AlertCircle, Info } from "lucide-react";

interface PreviewedTable {
  columns: string[];
  rows: Array<Record<string, string>>;
  truncated: boolean;
  unsupported?: boolean;
  error?: string;
}

interface Props {
  projectId: string;
  dbUuid: string;
  schema: string;
  table: string;
}

export function TableViewer({ projectId, dbUuid, schema, table }: Props) {
  const [data, setData] = useState<PreviewedTable | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let cancelled = false;
    const ctrl = new AbortController();
    const t = setTimeout(() => ctrl.abort(), 12_000);
    setLoading(true);
    setError(null);
    setData(null);

    const url = `/api/projects/${projectId}/databases/${dbUuid}/preview` +
      `?schema=${encodeURIComponent(schema)}&table=${encodeURIComponent(table)}`;

    fetch(url, { credentials: "include", signal: ctrl.signal })
      .then(async r => {
        let body: unknown = {};
        try { body = await r.json(); } catch {/* keep {} */}
        if (!r.ok) throw new Error((body as { error?: string }).error || `HTTP ${r.status}`);
        return body as PreviewedTable;
      })
      .then(d => { if (!cancelled) setData(d); })
      .catch(err => {
        if (cancelled) return;
        if (err?.name === "AbortError") setError("Timed out after 12s.");
        else setError(err?.message || "Failed to load preview");
      })
      .finally(() => { clearTimeout(t); if (!cancelled) setLoading(false); });

    return () => { cancelled = true; ctrl.abort(); clearTimeout(t); };
  }, [projectId, dbUuid, schema, table]);

  if (loading) {
    return (
      <div style={center}>
        <Loader2 size={14} className="animate-spin" />
        <span style={{ marginLeft: 8 }}>Querying {schema}.{table}…</span>
      </div>
    );
  }
  if (error) {
    return (
      <div style={errorBox}>
        <AlertCircle size={13} /> {error}
      </div>
    );
  }
  if (!data) return null;

  if (data.rows.length === 0) {
    return (
      <div style={infoBox}>
        <Info size={13} />
        Table is empty.
      </div>
    );
  }

  return (
    <div style={wrap}>
      <div style={meta}>
        Showing {data.rows.length} row{data.rows.length === 1 ? "" : "s"}
        {data.truncated && " (truncated to first 50)"} ·{" "}
        {data.columns.length} column{data.columns.length === 1 ? "" : "s"} ·{" "}
        <code style={qual}>{schema}.{table}</code>
      </div>
      <div style={tableScroll}>
        <table style={tableEl}>
          <thead>
            <tr>
              {data.columns.map(c => (
                <th key={c} style={th}>{c}</th>
              ))}
            </tr>
          </thead>
          <tbody>
            {data.rows.map((row, i) => (
              <tr key={i} style={i % 2 === 0 ? trEven : trOdd}>
                {data.columns.map(c => (
                  <td key={c} style={td} title={row[c]}>
                    {row[c]}
                  </td>
                ))}
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

// ──────────────────────────────────────────────────

const INK = {
  ink: "#1a1a1a",
  mid: "#5f5e5a",
  muted: "#a09a90",
  borderSoft: "#efebe1",
  border: "#e8e4dc",
} as const;

const wrap: React.CSSProperties = {
  display: "flex", flexDirection: "column", gap: 8, minHeight: 0, flex: 1,
};
const meta: React.CSSProperties = {
  fontSize: "0.74rem", color: INK.mid,
};
const qual: React.CSSProperties = {
  fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',
  color: INK.ink,
};
const tableScroll: React.CSSProperties = {
  flex: 1, minHeight: 0, overflow: "auto",
  border: `1px solid ${INK.borderSoft}`, borderRadius: 6,
};
const tableEl: React.CSSProperties = {
  borderCollapse: "collapse",
  fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',
  fontSize: "0.76rem",
  width: "100%",
};
const th: React.CSSProperties = {
  position: "sticky", top: 0,
  textAlign: "left", padding: "6px 10px",
  background: "#fafaf6", color: INK.ink,
  fontWeight: 600, fontSize: "0.72rem",
  borderBottom: `1px solid ${INK.border}`,
  whiteSpace: "nowrap",
};
const td: React.CSSProperties = {
  padding: "5px 10px", color: INK.ink,
  borderBottom: `1px solid ${INK.borderSoft}`,
  whiteSpace: "nowrap", maxWidth: 360,
  overflow: "hidden", textOverflow: "ellipsis",
};
const trEven: React.CSSProperties = { background: "#fff" };
const trOdd: React.CSSProperties = { background: "#fcfaf3" };
const center: React.CSSProperties = {
  flex: 1, display: "flex", alignItems: "center", justifyContent: "center",
  color: INK.mid, fontSize: "0.85rem",
};
const errorBox: React.CSSProperties = {
  display: "flex", alignItems: "center", gap: 6,
  padding: "10px 12px", fontSize: "0.82rem", color: "#7a1f15",
  background: "#fbe9e7", border: `1px solid #f4c2bc`, borderRadius: 8,
};
const infoBox: React.CSSProperties = {
  display: "flex", alignItems: "center", gap: 6,
  padding: "10px 12px", fontSize: "0.82rem", color: INK.mid,
  background: "#fafaf6", border: `1px dashed ${INK.borderSoft}`, borderRadius: 8,
};
