"use client";

import { FormEvent, useEffect, useMemo, useState } from "react";
import {
  ColumnMetadata,
  deleteRow,
  fetchRows,
  insertRow,
  RowValues,
  TableMetadata,
} from "@/app/lib/api";

type Props = {
  table: TableMetadata | null;
  columns: ColumnMetadata[];
  refreshKey: number;
  clientName?: string | null;
  onMutation?: () => void;
};

const formatValue = (value: unknown) => {
  if (value === null) {
    return "null";
  }
  if (value === undefined) {
    return "";
  }
  if (typeof value === "object") {
    try {
      return JSON.stringify(value);
    } catch {
      return "[object]";
    }
  }
  return String(value);
};

export default function DataGridPanel({
  table,
  columns,
  refreshKey,
  clientName,
  onMutation,
}: Props) {
  const [rows, setRows] = useState<RowValues[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [status, setStatus] = useState<string | null>(null);
  const [insertPayload, setInsertPayload] = useState("{\n  \n}");
  const [deleteId, setDeleteId] = useState("");

  const columnNames = useMemo(
    () => (columns.length > 0
      ? columns.map((column) => column.column_name)
      : ["*"]),
    [columns],
  );

  useEffect(() => {
    if (!table || !clientName) {
      setRows([]);
      return;
    }
    setLoading(true);
    setError(null);
    fetchRows(table.table_name, columnNames, clientName)
      .then((data) => {
        setRows(data);
      })
      .catch((err) => {
        setError(err.message ?? "Unable to load rows");
      })
      .finally(() => {
        setLoading(false);
      });
  }, [table, refreshKey, columnNames, clientName]);

  const displayColumns = useMemo(() => {
    if (columnNames.length > 0 && columnNames[0] !== "*") {
      return columnNames;
    }
    if (rows.length === 0) {
      return [];
    }
    return Object.keys(rows[0]);
  }, [columnNames, rows]);

  const handleInsert = async (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    if (!table) return;
    if (!clientName) {
      setError("Select a Postgres client before inserting");
      return;
    }
    setError(null);
    setStatus(null);
    try {
      const payload = JSON.parse(insertPayload);
      if (
        payload === null ||
        typeof payload !== "object" ||
        Array.isArray(payload)
      ) {
        throw new Error("Insert payload must be a JSON object");
      }
      await insertRow(table.table_name, payload, clientName);
      setStatus("Row inserted successfully.");
      setInsertPayload("{\n  \n}");
      onMutation?.();
    } catch (err) {
      setError(err instanceof Error ? err.message : "Insert failed");
    }
  };

  const handleDelete = async (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    if (!table) return;
    if (!deleteId.trim()) {
      setError("Resource ID is required to delete a row");
      return;
    }
    setError(null);
    setStatus(null);
    try {
      if (!clientName) {
        setError("Select a Postgres client before deleting");
        return;
      }
      await deleteRow(table.table_name, deleteId.trim(), clientName);
      setStatus("Delete request submitted.");
      setDeleteId("");
      onMutation?.();
    } catch (err) {
      setError(err instanceof Error ? err.message : "Delete failed");
    }
  };

  return (
    <section className="flex flex-col gap-4 rounded-2xl border border-white/10 bg-zinc-900/60 p-5 shadow-lg shadow-black/50 backdrop-blur-sm">
      <div className="flex items-center justify-between">
        <div>
          <p className="text-sm uppercase tracking-wide text-cyan-300">
            Table data
          </p>
          <h2 className="text-3xl font-semibold text-white">
            {table?.table_name ?? "Select a table"}
          </h2>
        </div>
        {status && (
          <div className="rounded-full bg-emerald-500/20 px-3 py-1 text-xs text-emerald-200">
            {status}
          </div>
        )}
      </div>
      {error && (
        <div className="rounded-md bg-red-500/20 p-3 text-sm text-red-100">
          {error}
        </div>
      )}
      {!clientName && (
        <div className="rounded-md bg-amber-500/10 p-2 text-xs text-amber-100">
          Select a Postgres client before fetching live data.
        </div>
      )}
      <div className="rounded-xl border border-white/5 bg-black/40 p-3">
        {loading && (
          <div className="text-xs uppercase tracking-wide text-zinc-400">
            Loading rows …
          </div>
        )}
        {!loading && rows.length === 0 && (
          <p className="text-xs text-zinc-400">No rows to display.</p>
        )}
        {!loading && rows.length > 0 && (
          <div className="max-h-96 overflow-auto">
            <table className="w-full border-collapse text-sm">
              <thead>
                <tr>
                  {displayColumns.map((column) => (
                    <th
                      key={column}
                      className="sticky top-0 bg-zinc-900 px-3 py-2 text-left text-xs uppercase tracking-wider text-zinc-400"
                    >
                      {column}
                    </th>
                  ))}
                </tr>
              </thead>
              <tbody>
                {rows.map((row, rowIndex) => (
                  <tr
                    key={`row-${rowIndex}`}
                    className="border-b border-white/5 last:border-b-0"
                  >
                    {displayColumns.map((column) => (
                      <td
                        key={`${rowIndex}-${column}`}
                        className="px-3 py-2 align-top text-xs text-zinc-200"
                      >
                        {formatValue(row[column])}
                      </td>
                    ))}
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>
      <div className="flex flex-col gap-4 lg:flex-row">
        <form
          onSubmit={handleInsert}
          className="flex-1 rounded-xl border border-cyan-500/30 bg-cyan-500/5 p-3"
        >
          <p className="text-sm font-semibold text-cyan-100">Insert row</p>
          <p className="text-xs text-zinc-400">
            Provide a JSON object matching the table schema (example:{" "}
            {'{"id": "123"}'}).
          </p>
          <textarea
            value={insertPayload}
            onChange={(event) => setInsertPayload(event.target.value)}
            rows={5}
            className="mt-2 w-full rounded-xl border border-white/10 bg-black/60 p-2 text-xs font-mono text-white outline-none focus:border-cyan-200"
          />
          <button
            type="submit"
            className="mt-2 inline-flex items-center justify-center rounded-full bg-cyan-500 px-5 py-2 text-xs font-semibold uppercase tracking-wide text-black transition hover:brightness-110"
          >
            Insert
          </button>
        </form>
        <form
          onSubmit={handleDelete}
          className="flex-1 rounded-xl border border-white/10 bg-white/5 p-3"
        >
          <p className="text-sm font-semibold text-white">Delete row</p>
          <p className="text-xs text-zinc-400">
            Supply the identifier (resource_id) that matches the table key.
          </p>
          <input
            value={deleteId}
            onChange={(event) => setDeleteId(event.target.value)}
            placeholder="resource_id value"
            className="mt-2 w-full rounded-xl border border-white/10 bg-black/60 px-3 py-2 text-xs text-white outline-none focus:border-cyan-200"
          />
          <button
            type="submit"
            className="mt-2 inline-flex items-center justify-center rounded-full border border-transparent bg-red-500 px-5 py-2 text-xs font-semibold uppercase tracking-wide text-white transition hover:bg-red-400"
          >
            Delete
          </button>
        </form>
      </div>
    </section>
  );
}
