"use client";

import { FormEvent, useEffect, useMemo, useState } from "react";
import { ColumnMetadata, runDdl, TableMetadata } from "@/app/lib/api";

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

export default function SchemaActionsPanel({
  table,
  columns,
  onSchemaChange,
  clientName,
}: Props) {
  const [addName, setAddName] = useState("");
  const [addType, setAddType] = useState("text");
  const [addDefault, setAddDefault] = useState("");
  const [dropName, setDropName] = useState("");
  const [defaultColumn, setDefaultColumn] = useState("");
  const [defaultValue, setDefaultValue] = useState("");
  const [customSql, setCustomSql] = useState("");
  const [status, setStatus] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);

  const resetForm = () => {
    setStatus(null);
    setError(null);
    setAddName("");
    setDropName("");
    setDefaultColumn("");
    setDefaultValue("");
    setCustomSql("");
  };

  useEffect(() => {
    const timer = setTimeout(() => resetForm(), 0);
    return () => clearTimeout(timer);
  }, [table?.table_name]);

  const columnNames = useMemo(
    () => columns.map((column) => column.column_name),
    [columns],
  );

  const tableName = table?.table_name ?? "unknown";

  const handleAddColumn = async (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    if (!clientName) {
      setError("Select a Postgres client before running DDL");
      return;
    }
    if (!table || !addName.trim() || !addType.trim()) {
      setError("Column name and type are required");
      return;
    }
    setError(null);
    setStatus(null);
    const defaultClause = addDefault.trim()
      ? ` DEFAULT ${addDefault.trim()}`
      : "";
    const statement =
      `ALTER TABLE ${tableName} ADD COLUMN ${addName.trim()} ${addType.trim()}${defaultClause};`;
    try {
      await runDdl(statement, clientName);
      setStatus(`Added column ${addName.trim()}.`);
      setAddName("");
      setAddType("text");
      setAddDefault("");
      onSchemaChange?.();
    } catch (err) {
      setError(err instanceof Error ? err.message : "DDL failed");
    }
  };

  const handleDropColumn = async (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    if (!clientName) {
      setError("Select a Postgres client before running DDL");
      return;
    }
    if (!table || !dropName.trim()) {
      setError("Provide a column name to drop");
      return;
    }
    setError(null);
    setStatus(null);
    const statement =
      `ALTER TABLE ${tableName} DROP COLUMN ${dropName.trim()};`;
    try {
      await runDdl(statement, clientName);
      setStatus(`Dropped ${dropName.trim()}.`);
      setDropName("");
      onSchemaChange?.();
    } catch (err) {
      setError(err instanceof Error ? err.message : "DDL failed");
    }
  };

  const handleDefaultChange = async (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    if (!clientName) {
      setError("Select a Postgres client before running DDL");
      return;
    }
    if (!table || !defaultColumn.trim()) {
      setError("Select a column to update its default");
      return;
    }
    setError(null);
    setStatus(null);
    const clause = defaultValue.trim()
      ? `SET DEFAULT ${defaultValue.trim()}`
      : "DROP DEFAULT";
    const statement =
      `ALTER TABLE ${tableName} ALTER COLUMN ${defaultColumn.trim()} ${clause};`;
    try {
      await runDdl(statement, clientName);
      setStatus(
        defaultValue.trim()
          ? `Set default on ${defaultColumn.trim()}.`
          : `Cleared default from ${defaultColumn.trim()}.`,
      );
      setDefaultValue("");
      onSchemaChange?.();
    } catch (err) {
      setError(err instanceof Error ? err.message : "DDL failed");
    }
  };

  const handleCustom = async (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    if (!customSql.trim()) {
      setError("Provide a SQL statement to run");
      return;
    }
    setError(null);
    setStatus(null);
    try {
      if (!clientName) {
        setError("Select a Postgres client before running DDL");
        return;
      }
      await runDdl(customSql.trim(), clientName);
      setStatus("Custom statement executed.");
      setCustomSql("");
      onSchemaChange?.();
    } catch (err) {
      setError(err instanceof Error ? err.message : "DDL failed");
    }
  };

  return (
    <section className="flex flex-col gap-4 rounded-2xl border border-white/10 bg-white/5 p-4 shadow-lg shadow-black/40 backdrop-blur">
      <div className="flex items-center justify-between">
        <div>
          <p className="text-xs uppercase tracking-wider text-zinc-400">
            Schema actions
          </p>
          <h2 className="text-2xl font-semibold text-white">Columns</h2>
        </div>
        <span className="rounded-full bg-blue-500/20 px-3 py-1 text-xs text-blue-200">
          {columns.length} columns
        </span>
      </div>
      {error && (
        <div className="rounded-md bg-red-500/20 p-2 text-xs 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 running schema actions.
        </div>
      )}
      <div className="h-40 overflow-auto rounded-xl border border-white/5 bg-zinc-900/60">
        <table className="w-full text-xs">
          <thead className="bg-white/5 text-left text-[11px] uppercase tracking-wider text-zinc-400">
            <tr>
              <th className="px-3 py-2">Name</th>
              <th className="px-3 py-2">Type</th>
              <th className="px-3 py-2">Default</th>
              <th className="px-3 py-2">Nullable</th>
            </tr>
          </thead>
          <tbody>
            {columns.map((column) => (
              <tr
                key={column.column_name}
                className="border-b border-white/5 last:border-b-0"
              >
                <td className="px-3 py-2 text-sm text-white">
                  {column.column_name}
                </td>
                <td className="px-3 py-2 text-xs text-zinc-300">
                  {column.data_type ?? "unknown"}
                </td>
                <td className="px-3 py-2 text-xs text-zinc-300">
                  {column.column_default ?? "—"}
                </td>
                <td className="px-3 py-2 text-xs text-zinc-300">
                  {column.is_nullable ?? "—"}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      {status && (
        <div className="rounded-md bg-emerald-500/20 p-2 text-xs text-emerald-100">
          {status}
        </div>
      )}
      <div className="grid gap-3">
        <form
          onSubmit={handleAddColumn}
          className="rounded-xl border border-cyan-500/30 bg-cyan-500/5 p-3 text-xs"
        >
          <p className="text-[11px] font-semibold text-cyan-100">Add column</p>
          <div className="mt-2 flex flex-col gap-2">
            <input
              value={addName}
              onChange={(event) => setAddName(event.target.value)}
              placeholder="column_name"
              className="w-full rounded-xl border border-white/10 bg-black/40 px-3 py-2 text-xs text-white outline-none"
            />
            <input
              value={addType}
              onChange={(event) => setAddType(event.target.value)}
              placeholder="data type (e.g. varchar(255))"
              className="w-full rounded-xl border border-white/10 bg-black/40 px-3 py-2 text-xs text-white outline-none"
            />
            <input
              value={addDefault}
              onChange={(event) => setAddDefault(event.target.value)}
              placeholder="default value (optional)"
              className="w-full rounded-xl border border-white/10 bg-black/40 px-3 py-2 text-xs text-white outline-none"
            />
          </div>
          <button
            type="submit"
            className="mt-3 inline-flex items-center justify-center rounded-full bg-cyan-500 px-4 py-1 text-[11px] font-semibold uppercase tracking-wide text-black transition hover:brightness-110"
          >
            Add
          </button>
        </form>
        <form
          onSubmit={handleDropColumn}
          className="rounded-xl border border-white/10 bg-white/5 p-3 text-xs"
        >
          <p className="text-[11px] font-semibold text-white">Drop column</p>
          <input
            value={dropName}
            onChange={(event) => setDropName(event.target.value)}
            placeholder="column_name"
            className="mt-2 w-full rounded-xl border border-white/10 bg-black/40 px-3 py-2 text-xs text-white outline-none"
          />
          <button
            type="submit"
            className="mt-3 inline-flex items-center justify-center rounded-full border border-transparent bg-red-500 px-4 py-1 text-[11px] font-semibold uppercase tracking-wide text-white transition hover:bg-red-400"
          >
            Drop
          </button>
        </form>
        <form
          onSubmit={handleDefaultChange}
          className="rounded-xl border border-white/10 bg-white/5 p-3 text-xs"
        >
          <p className="text-[11px] font-semibold text-white">
            Alter defaults
          </p>
          <select
            value={defaultColumn}
            onChange={(event) => setDefaultColumn(event.target.value)}
            className="mt-2 w-full rounded-xl border border-white/10 bg-black/40 px-3 py-2 text-xs text-white outline-none"
          >
            <option value="">Select column</option>
            {columnNames.map((name) => (
              <option key={name} value={name}>
                {name}
              </option>
            ))}
          </select>
          <input
            value={defaultValue}
            onChange={(event) => setDefaultValue(event.target.value)}
            placeholder="default expression (empty to drop)"
            className="mt-2 w-full rounded-xl border border-white/10 bg-black/40 px-3 py-2 text-xs text-white outline-none"
          />
          <button
            type="submit"
            className="mt-3 inline-flex items-center justify-center rounded-full border border-transparent bg-amber-500 px-4 py-1 text-[11px] font-semibold uppercase tracking-wide text-black transition hover:bg-amber-400"
          >
            Run
          </button>
        </form>
        <form
          onSubmit={handleCustom}
          className="rounded-xl border border-white/10 bg-white/5 p-3 text-xs"
        >
          <p className="text-[11px] font-semibold text-white">Custom SQL</p>
          <textarea
            value={customSql}
            onChange={(event) => setCustomSql(event.target.value)}
            rows={4}
            placeholder={`ALTER TABLE ${tableName} ...`}
            className="mt-2 w-full rounded-xl border border-white/10 bg-black/40 p-2 text-xs font-mono text-white outline-none"
          />
          <button
            type="submit"
            className="mt-3 inline-flex items-center justify-center rounded-full bg-emerald-500 px-4 py-1 text-[11px] font-semibold uppercase tracking-wide text-black transition hover:brightness-110"
          >
            Execute
          </button>
        </form>
      </div>
    </section>
  );
}
