"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 { THEME } from "@/components/project/dashboard-ui";
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={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 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>
  );
}

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

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.75rem",
  color: INK.mid,
  display: "flex",
  justifyContent: "space-between",
  padding: "4px 8px",
};
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,
};
