"use client";

import { useState, useCallback, useMemo, useRef } from "react";
import { useSettings } from "@/app/lib/settings";
import { runDdl, ApiError } from "@/app/lib/api";
import { Button } from "./ui/button";
import { Input } from "./ui/input";
import { Switch } from "./ui/switch";
import { Badge } from "./ui/badge";
import { ScrollArea } from "./ui/scroll-area";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
} from "./ui/dialog";
import { toast } from "sonner";
import { z } from "zod";
import Papa from "papaparse";
import {
  Plus,
  Trash2,
  Loader2,
  GripVertical,
  Link2,
  Key,
  Hash,
  Type,
  Calendar,
  ToggleLeft,
  Settings2,
  Info,
  ExternalLink,
  FileUp,
  ChevronDown,
  Save,
  Copy,
  Database,
} from "lucide-react";

type ColumnDef = {
  id: string;
  name: string;
  type: string;
  defaultValue: string;
  isPrimary: boolean;
  isNullable: boolean;
  isUnique: boolean;
  isIdentity: boolean;
  isArray: boolean;
};

type ForeignKeyDef = {
  id: string;
  column: string;
  refSchema: string;
  refTable: string;
  refColumn: string;
  onDelete: string;
  onUpdate: string;
};

type Props = {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  clientName: string | null;
  currentSchema: string;
  existingTableNames: string[];
  onCreated: () => void;
};

// Column name: only lowercase letters, numbers, underscore, hyphen. No spaces, no camelCase.
const COLUMN_NAME_REGEX = /^[a-z0-9_-]+$/;
const TABLE_NAME_REGEX = /^[a-z0-9_-]+$/;

const columnNameSchema = z
  .string()
  .min(1, "Column name is required")
  .refine((v) => !/\s/.test(v), "No spaces allowed")
  .refine(
    (v) => COLUMN_NAME_REGEX.test(v),
    "Only lowercase letters, numbers, underscore (_) and hyphen (-) allowed. No camelCase.",
  );

const tableNameSchema = z
  .string()
  .min(1, "Table name is required")
  .refine((v) => !/\s/.test(v), "No spaces allowed")
  .refine(
    (v) => TABLE_NAME_REGEX.test(v),
    "Only lowercase letters, numbers, underscore (_) and hyphen (-) allowed. No camelCase.",
  );

const PG_TYPES = [
  {
    group: "Numeric",
    types: ["int2", "int4", "int8", "float4", "float8", "numeric"],
  },
  { group: "Text", types: ["text", "varchar", "char", "uuid", "citext"] },
  {
    group: "Date/Time",
    types: ["timestamptz", "timestamp", "date", "time", "timetz", "interval"],
  },
  { group: "Boolean", types: ["bool"] },
  { group: "JSON", types: ["jsonb", "json"] },
  { group: "Binary", types: ["bytea"] },
  { group: "Network", types: ["inet", "cidr", "macaddr"] },
  {
    group: "Geometric",
    types: ["point", "line", "circle", "box", "path", "polygon"],
  },
];

const TYPE_LABELS: Record<string, string> = {
  int2: "int2 (smallint)",
  int4: "int4 (integer)",
  int8: "int8 (bigint)",
  float4: "float4 (real)",
  float8: "float8 (double)",
  numeric: "numeric",
  text: "text",
  varchar: "varchar",
  char: "char",
  uuid: "uuid",
  citext: "citext",
  timestamptz: "timestamptz",
  timestamp: "timestamp",
  date: "date",
  time: "time",
  timetz: "timetz",
  interval: "interval",
  bool: "bool (boolean)",
  jsonb: "jsonb",
  json: "json",
  bytea: "bytea",
  inet: "inet",
  cidr: "cidr",
  macaddr: "macaddr",
  point: "point",
  line: "line",
  circle: "circle",
  box: "box",
  path: "path",
  polygon: "polygon",
};

const DEFAULT_FOR_TYPE: Record<string, string> = {
  uuid: "gen_random_uuid()",
  timestamptz: "now()",
  timestamp: "now()",
  date: "CURRENT_DATE",
  time: "CURRENT_TIME",
};

const typeIcon = (t: string) => {
  if (["int2", "int4", "int8", "float4", "float8", "numeric"].includes(t))
    return Hash;
  if (["text", "varchar", "char", "citext"].includes(t)) return Type;
  if (
    ["timestamptz", "timestamp", "date", "time", "timetz", "interval"].includes(
      t,
    )
  )
    return Calendar;
  if (["bool"].includes(t)) return ToggleLeft;
  if (["jsonb", "json"].includes(t)) return Settings2;
  if (["uuid"].includes(t)) return Key;
  return Type;
};

const FK_ACTIONS = [
  "NO ACTION",
  "CASCADE",
  "SET NULL",
  "SET DEFAULT",
  "RESTRICT",
];

function newColumnId() {
  return crypto.randomUUID();
}

function defaultColumns(): ColumnDef[] {
  return [
    {
      id: newColumnId(),
      name: "id",
      type: "int8",
      defaultValue: "",
      isPrimary: true,
      isNullable: false,
      isUnique: false,
      isIdentity: true,
      isArray: false,
    },
    {
      id: newColumnId(),
      name: "created_at",
      type: "timestamptz",
      defaultValue: "now()",
      isPrimary: false,
      isNullable: true,
      isUnique: false,
      isIdentity: false,
      isArray: false,
    },
  ];
}

function inferTypeFromValues(values: string[]): string {
  const nonEmpty = values.filter((v) => v != null && String(v).trim() !== "");
  if (nonEmpty.length === 0) return "text";

  const allInt = nonEmpty.every((v) => /^-?\d+$/.test(String(v).trim()));
  if (allInt) return "int8";

  const allFloat = nonEmpty.every((v) =>
    /^-?\d+\.?\d*$/.test(String(v).trim()),
  );
  if (allFloat) return "float8";

  const allBool = nonEmpty.every((v) =>
    /^(true|false|yes|no|1|0)$/i.test(String(v).trim()),
  );
  if (allBool) return "bool";

  const allUuid = nonEmpty.every((v) =>
    /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(
      String(v).trim(),
    ),
  );
  if (allUuid) return "uuid";

  const allDate = nonEmpty.every(
    (v) =>
      /^\d{4}-\d{2}-\d{2}(T|\s)/.test(String(v).trim()) ||
      /^\d{4}-\d{2}-\d{2}$/.test(String(v).trim()),
  );
  if (allDate) return "timestamptz";

  return "text";
}

function sanitizeColumnName(name: string): string {
  return (
    name
      .toLowerCase()
      .replace(/\s+/g, "_")
      .replace(/[^a-z0-9_-]/g, "_")
      .replace(/_+/g, "_")
      .replace(/^_|_$/g, "") || "column"
  );
}

export default function CreateTableDialog({
  open,
  onOpenChange,
  clientName,
  currentSchema,
  existingTableNames,
  onCreated,
}: Props) {
  const { baseUrl, apiKey } = useSettings();
  const ctx = useMemo(() => ({ baseUrl, apiKey }), [baseUrl, apiKey]);
  const fileInputRef = useRef<HTMLInputElement>(null);

  const [tableName, setTableName] = useState("");
  const [description, setDescription] = useState("");
  const [enableRls, setEnableRls] = useState(true);
  const [enableRealtime, setEnableRealtime] = useState(false);
  const [columns, setColumns] = useState<ColumnDef[]>(defaultColumns);
  const [foreignKeys, setForeignKeys] = useState<ForeignKeyDef[]>([]);
  const [saving, setSaving] = useState(false);
  const [showSqlPreview, setShowSqlPreview] = useState(false);
  const [rawSql, setRawSql] = useState("");

  const existingNamesLower = useMemo(
    () => new Set(existingTableNames.map((n) => n.toLowerCase())),
    [existingTableNames],
  );
  const columnNamesLower = useMemo(
    () => columns.map((c) => c.name.trim().toLowerCase()).filter(Boolean),
    [columns],
  );
  const duplicateColumnNames = useMemo(() => {
    const seen = new Set<string>();
    const dups = new Set<string>();
    for (const n of columnNamesLower) {
      if (seen.has(n)) dups.add(n);
      else seen.add(n);
    }
    return dups;
  }, [columnNamesLower]);

  const tableNameError = useMemo(() => {
    const t = tableName.trim();
    if (!t) return null;
    const result = tableNameSchema.safeParse(t);
    if (!result.success)
      return result.error.issues[0]?.message ?? "Invalid table name";
    if (existingNamesLower.has(t.toLowerCase()))
      return "Table already exists in this schema";
    return null;
  }, [tableName, existingNamesLower]);

  const getColumnError = useCallback(
    (col: ColumnDef) => {
      const name = col.name.trim();
      if (!name) return null;
      const result = columnNameSchema.safeParse(name);
      if (!result.success)
        return result.error.issues[0]?.message ?? "Invalid column name";
      if (duplicateColumnNames.has(name.toLowerCase()))
        return "Column name already exists";
      return null;
    },
    [duplicateColumnNames],
  );

  const resetForm = useCallback(() => {
    setTableName("");
    setDescription("");
    setEnableRls(true);
    setEnableRealtime(false);
    setColumns(defaultColumns());
    setForeignKeys([]);
    setShowSqlPreview(false);
    setRawSql("");
  }, []);

  const handleClose = useCallback(
    (open: boolean) => {
      if (!open) resetForm();
      onOpenChange(open);
    },
    [onOpenChange, resetForm],
  );

  const addColumn = () => {
    setColumns((prev) => [
      ...prev,
      {
        id: newColumnId(),
        name: "",
        type: "text",
        defaultValue: "",
        isPrimary: false,
        isNullable: true,
        isUnique: false,
        isIdentity: false,
        isArray: false,
      },
    ]);
  };

  const removeColumn = (id: string) => {
    setColumns((prev) => prev.filter((c) => c.id !== id));
  };

  const updateColumn = (id: string, patch: Partial<ColumnDef>) => {
    setColumns((prev) =>
      prev.map((c) => {
        if (c.id !== id) return c;
        const updated = { ...c, ...patch };
        if (patch.isPrimary) {
          updated.isNullable = false;
        }
        return updated;
      }),
    );
  };

  const addForeignKey = () => {
    setForeignKeys((prev) => [
      ...prev,
      {
        id: newColumnId(),
        column: "",
        refSchema: "public",
        refTable: "",
        refColumn: "id",
        onDelete: "NO ACTION",
        onUpdate: "NO ACTION",
      },
    ]);
  };

  const removeForeignKey = (id: string) => {
    setForeignKeys((prev) => prev.filter((fk) => fk.id !== id));
  };

  const updateForeignKey = (id: string, patch: Partial<ForeignKeyDef>) => {
    setForeignKeys((prev) =>
      prev.map((fk) => (fk.id === id ? { ...fk, ...patch } : fk)),
    );
  };

  const buildSql = useCallback(() => {
    const primaryCols = columns.filter((c) => c.isPrimary);
    const colDefs = columns.map((c) => {
      let typeStr = c.type;
      if (c.isArray) typeStr += "[]";

      let def = `  "${c.name}" ${typeStr}`;
      if (c.isIdentity) def += " GENERATED BY DEFAULT AS IDENTITY";
      if (!c.isNullable) def += " NOT NULL";
      if (c.isUnique && !c.isPrimary) def += " UNIQUE";
      if (c.defaultValue.trim() && !c.isIdentity)
        def += ` DEFAULT ${c.defaultValue.trim()}`;
      return def;
    });

    if (primaryCols.length > 0) {
      colDefs.push(
        `  PRIMARY KEY (${primaryCols.map((c) => `"${c.name}"`).join(", ")})`,
      );
    }

    let sql = `CREATE TABLE "${currentSchema}"."${tableName.trim()}" (\n${colDefs.join(",\n")}\n);`;

    if (description.trim()) {
      sql += `\nCOMMENT ON TABLE "${currentSchema}"."${tableName.trim()}" IS '${description.trim().replace(/'/g, "''")}';`;
    }

    if (enableRls) {
      sql += `\nALTER TABLE "${currentSchema}"."${tableName.trim()}" ENABLE ROW LEVEL SECURITY;`;
    }

    for (const fk of foreignKeys) {
      if (fk.column && fk.refTable && fk.refColumn) {
        sql += `\nALTER TABLE "${currentSchema}"."${tableName.trim()}" ADD CONSTRAINT "fk_${tableName.trim()}_${fk.column}" FOREIGN KEY ("${fk.column}") REFERENCES "${fk.refSchema}"."${fk.refTable}"("${fk.refColumn}") ON DELETE ${fk.onDelete} ON UPDATE ${fk.onUpdate};`;
      }
    }

    return sql;
  }, [columns, currentSchema, tableName, description, enableRls, foreignKeys]);

  const handleSaveSql = useCallback(() => {
    const sql = buildSql();
    setRawSql(sql);
    setShowSqlPreview(true);
  }, [buildSql]);

  const handleCopySql = useCallback(() => {
    const sql = rawSql || buildSql();
    navigator.clipboard.writeText(sql);
    toast.success("SQL copied to clipboard");
  }, [rawSql, buildSql]);

  const handleExecute = async () => {
    if (!tableName.trim()) {
      toast.error("Table name is required.");
      return;
    }
    if (!clientName) {
      toast.error("Select a client first.");
      return;
    }
    if (columns.length === 0) {
      toast.error("Add at least one column.");
      return;
    }
    const emptyNames = columns.filter((c) => !c.name.trim());
    if (emptyNames.length > 0) {
      toast.error("All columns must have a name.");
      return;
    }
    if (tableNameError) {
      toast.error(tableNameError);
      return;
    }
    const errCol = columns.find((c) => getColumnError(c));
    if (errCol) {
      toast.error(getColumnError(errCol)!);
      return;
    }

    setSaving(true);
    try {
      const sql = rawSql || buildSql();
      await runDdl(ctx, sql, clientName);
      toast.success(`Table "${tableName.trim()}" created.`);
      handleClose(false);
      onCreated();
    } catch (err) {
      const msg =
        err instanceof ApiError ? err.message : "Failed to create table";
      toast.error(msg);
    } finally {
      setSaving(false);
    }
  };

  const handleCsvImport = useCallback(() => {
    fileInputRef.current?.click();
  }, []);

  const handleFileChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      const file = e.target.files?.[0];
      if (!file) return;
      e.target.value = "";

      Papa.parse(file, {
        header: true,
        skipEmptyLines: true,
        complete: (results) => {
          const data = results.data as Record<string, string>[];
          if (!data || data.length === 0) {
            toast.error("CSV is empty or has no headers");
            return;
          }
          const headers = results.meta.fields ?? Object.keys(data[0] ?? {});
          if (headers.length === 0) {
            toast.error("CSV has no column headers");
            return;
          }

          const newColumns: ColumnDef[] = headers.map((h) => {
            const values = data.map((r) => r[h] ?? "").filter(Boolean);
            const inferredType = inferTypeFromValues(values);
            const name = sanitizeColumnName(h);
            const isFirst = headers.indexOf(h) === 0;
            return {
              id: newColumnId(),
              name,
              type: inferredType,
              defaultValue:
                inferredType === "uuid"
                  ? "gen_random_uuid()"
                  : inferredType === "timestamptz"
                    ? "now()"
                    : "",
              isPrimary: isFirst,
              isNullable: !isFirst,
              isUnique: false,
              isIdentity: isFirst && inferredType === "int8",
              isArray: false,
            };
          });

          setColumns(newColumns);
          toast.success(
            `Imported ${headers.length} columns from ${data.length} rows`,
          );
        },
        error: (err) => {
          toast.error(err.message ?? "Failed to parse CSV");
        },
      });
    },
    [],
  );

  const selectClass =
    "h-9 w-full rounded-lg border border-border bg-background px-3 text-xs text-foreground outline-none focus:ring-2 focus:ring-ring-subtle transition-all";

  const defaultPlaceholder = (col: ColumnDef) => {
    if (col.isIdentity) return "auto-increment";
    return DEFAULT_FOR_TYPE[col.type] ?? "NULL";
  };

  return (
    <Dialog open={open} onOpenChange={handleClose}>
      <input
        ref={fileInputRef}
        type="file"
        accept=".csv"
        className="hidden"
        onChange={handleFileChange}
      />
      <DialogContent className="max-w-2xl max-h-[90vh] overflow-hidden flex flex-col p-0">
        {/* Header */}
        <div className="px-6 pt-6 pb-4 border-b border-border">
          <DialogHeader>
            <DialogTitle className="text-base">Create a new table</DialogTitle>
            <DialogDescription className="flex flex-wrap items-center gap-2">
              <span>under</span>
              <code className="rounded bg-muted px-1.5 py-0.5 text-body-sm font-mono text-foreground">
                {currentSchema}
              </code>
              {clientName && (
                <>
                  <span>in</span>
                  <Badge
                    variant="secondary"
                    className="text-caption font-normal gap-1"
                  >
                    <Database className="h-3 w-3" />
                    {clientName}
                  </Badge>
                </>
              )}
            </DialogDescription>
          </DialogHeader>
        </div>

        <ScrollArea className="flex-1 min-h-0">
          <div className="px-6 py-5 space-y-6">
            {/* Name & Description */}
            <div className="grid grid-cols-[100px_1fr] gap-y-4 gap-x-4 items-start">
              <label className="text-xs font-medium text-foreground pt-2.5">
                Name
              </label>
              <div className="space-y-1">
                <Input
                  value={tableName}
                  onChange={(e) => setTableName(e.target.value)}
                  placeholder="e.g. users, products, events"
                  className={`h-10 text-sm font-mono ${tableNameError ? "border-destructive" : ""}`}
                  autoFocus
                />
                {tableNameError && (
                  <div className="overflow-hidden transition-all duration-200 animate-in slide-in-from-top-1">
                    <p className="text-xs text-destructive flex items-center gap-1">
                      {tableNameError}
                    </p>
                  </div>
                )}
              </div>
              <label className="text-xs font-medium text-foreground">
                Description
              </label>
              <Input
                value={description}
                onChange={(e) => setDescription(e.target.value)}
                placeholder="Optional"
                className="h-10 text-sm text-muted-foreground"
              />
            </div>

            {/* RLS Toggle */}
            <div className="rounded-lg border border-border p-4 space-y-3">
              <div className="flex items-start gap-3">
                <div className="mt-0.5">
                  <Switch checked={enableRls} onCheckedChange={setEnableRls} />
                </div>
                <div className="flex-1">
                  <div className="flex items-center gap-2">
                    <span className="text-sm font-medium text-foreground">
                      Enable Row Level Security (RLS)
                    </span>
                    <Badge className="text-tiny px-1.5 py-0 bg-success-muted text-success border border-success-border">
                      RECOMMENDED
                    </Badge>
                  </div>
                  <p className="text-xs text-muted-foreground mt-0.5">
                    Restrict access to your table by enabling RLS and writing
                    Postgres policies.
                  </p>
                </div>
              </div>

              {enableRls && (
                <div className="rounded-lg bg-muted-card border border-border p-3 flex items-start gap-2.5">
                  <Info className="h-4 w-4 text-primary shrink-0 mt-0.5" />
                  <div>
                    <p className="text-xs font-medium text-foreground">
                      Policies are required to query data
                    </p>
                    <p className="text-body-sm text-muted-foreground mt-0.5">
                      You need to create an access policy before you can query
                      data from this table. Without a policy, querying this
                      table will return an empty array of results.
                    </p>
                  </div>
                </div>
              )}
            </div>

            {/* Realtime Toggle */}
            <div className="flex items-start gap-3 rounded-lg border border-border p-4">
              <div className="mt-0.5">
                <Switch
                  checked={enableRealtime}
                  onCheckedChange={setEnableRealtime}
                />
              </div>
              <div>
                <span className="text-sm font-medium text-foreground">
                  Enable Realtime
                </span>
                <p className="text-xs text-muted-foreground mt-0.5">
                  Broadcast changes on this table to authorized subscribers.
                </p>
              </div>
            </div>

            {/* Columns */}
            <div className="space-y-3">
              <div className="flex items-center justify-between">
                <h3 className="text-sm font-semibold text-foreground">
                  Columns
                </h3>
                <div className="flex items-center gap-2">
                  <button className="text-body-sm text-primary hover:underline flex items-center gap-1">
                    <ExternalLink className="h-3 w-3" /> About data types
                  </button>
                  <Button
                    variant="outline"
                    size="sm"
                    className="h-7 text-body-sm gap-1"
                    onClick={handleCsvImport}
                  >
                    <FileUp className="h-3 w-3" /> Import from CSV
                  </Button>
                </div>
              </div>

              {/* Column headers */}
              <div className="grid grid-cols-[20px_1fr_20px_140px_1fr_44px_44px_32px] gap-1.5 items-center px-1 text-caption font-medium text-muted-foreground uppercase tracking-wider">
                <span />
                <span>Name</span>
                <span />
                <span>Type</span>
                <span>Default</span>
                <span className="text-center">Primary</span>
                <span title="Nullable">Null</span>
                <span />
              </div>

              {/* Column rows */}
              <div className="space-y-1.5">
                {columns.map((col) => {
                  const Icon = typeIcon(col.type);
                  const colError = getColumnError(col);
                  return (
                    <div key={col.id} className="space-y-0">
                      <div
                        className={`grid grid-cols-[20px_1fr_20px_140px_1fr_44px_44px_32px] gap-1.5 items-center group ${colError ? "pb-0" : ""}`}
                      >
                        <div className="flex items-center justify-center">
                          <GripVertical className="h-3.5 w-3.5 text-muted-foreground-dim group-hover:text-muted-foreground-subtle cursor-grab" />
                        </div>

                        <div className="space-y-0">
                          <Input
                            value={col.name}
                            onChange={(e) =>
                              updateColumn(col.id, { name: e.target.value })
                            }
                            placeholder="column_name"
                            className={`h-9 text-xs font-mono ${colError ? "border-destructive" : ""}`}
                          />
                        </div>

                        <div
                          className="flex items-center justify-center"
                          title={TYPE_LABELS[col.type] ?? col.type}
                        >
                          <Icon className="h-3 w-3 text-muted-foreground-subtle" />
                        </div>

                        <div className="relative">
                          <Icon className="absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground-subtle pointer-events-none" />
                          <select
                            value={col.type}
                            onChange={(e) =>
                              updateColumn(col.id, { type: e.target.value })
                            }
                            className={`${selectClass} pl-8 pr-6 h-9 text-xs appearance-none`}
                          >
                            {PG_TYPES.map((group) => (
                              <optgroup key={group.group} label={group.group}>
                                {group.types.map((t) => (
                                  <option key={t} value={t}>
                                    {TYPE_LABELS[t] ?? t}
                                  </option>
                                ))}
                              </optgroup>
                            ))}
                          </select>
                          <ChevronDown className="absolute right-2 top-1/2 -translate-y-1/2 h-3 w-3 text-muted-foreground-dim pointer-events-none" />
                        </div>

                        <div className="space-y-0">
                          <Input
                            value={col.defaultValue}
                            onChange={(e) =>
                              updateColumn(col.id, {
                                defaultValue: e.target.value,
                              })
                            }
                            placeholder={defaultPlaceholder(col)}
                            disabled={col.isIdentity}
                            className="h-9 text-xs font-mono disabled:opacity-50"
                          />
                        </div>

                        <div className="flex items-center justify-center">
                          <button
                            onClick={() =>
                              updateColumn(col.id, {
                                isPrimary: !col.isPrimary,
                              })
                            }
                            className={`flex h-5 w-5 items-center justify-center rounded border transition-colors ${
                              col.isPrimary
                                ? "bg-primary border-primary text-primary-foreground"
                                : "border-border bg-background hover:border-foreground-border"
                            }`}
                            title="Primary key"
                          >
                            {col.isPrimary && (
                              <svg
                                className="h-3 w-3"
                                fill="none"
                                viewBox="0 0 24 24"
                                stroke="currentColor"
                                strokeWidth={3}
                              >
                                <path
                                  strokeLinecap="round"
                                  strokeLinejoin="round"
                                  d="M5 13l4 4L19 7"
                                />
                              </svg>
                            )}
                          </button>
                        </div>

                        <div className="flex items-center justify-center">
                          {col.isPrimary ? (
                            <Badge className="text-2xs px-1 py-0 bg-primary-muted text-primary border border-primary-border tabular-nums">
                              {columns.filter((c) => c.isPrimary).indexOf(col) +
                                1}
                            </Badge>
                          ) : (
                            <button
                              onClick={() =>
                                updateColumn(col.id, {
                                  isNullable: !col.isNullable,
                                })
                              }
                              className={`text-tiny font-medium px-1.5 py-0.5 rounded transition-colors ${
                                col.isNullable
                                  ? "text-muted-foreground-subtle hover:text-foreground"
                                  : "text-warning bg-warning-muted"
                              }`}
                              title={
                                col.isNullable ? "Allows NULL" : "NOT NULL"
                              }
                            >
                              {col.isNullable ? "NULL" : "NOT NULL"}
                            </button>
                          )}
                        </div>

                        <div className="flex items-center justify-center">
                          <button
                            onClick={() => removeColumn(col.id)}
                            className="h-7 w-7 flex items-center justify-center rounded-lg text-muted-foreground-dim hover:text-destructive hover:bg-destructive-muted transition-colors"
                            title="Remove column"
                          >
                            <Trash2 className="h-3.5 w-3.5" />
                          </button>
                        </div>
                      </div>
                      {colError && (
                        <div className="overflow-hidden transition-all duration-200 animate-in slide-in-from-top-1 pl-[20px]">
                          <p className="text-xs text-destructive flex items-center gap-1">
                            {colError}
                          </p>
                        </div>
                      )}
                    </div>
                  );
                })}
              </div>

              <button
                onClick={addColumn}
                className="w-full flex items-center justify-center gap-1.5 rounded-lg border border-dashed border-border bg-muted-panel py-2.5 text-xs text-muted-foreground hover:text-foreground hover:border-foreground-border hover:bg-muted-card transition-colors"
              >
                <Plus className="h-3.5 w-3.5" /> Add column
              </button>
            </div>

            {/* Foreign Keys */}
            <div className="space-y-3">
              <h3 className="text-sm font-semibold text-foreground">
                Foreign keys
              </h3>

              {foreignKeys.map((fk) => (
                <div
                  key={fk.id}
                  className="rounded-lg border border-border bg-card p-4 space-y-3"
                >
                  <div className="grid grid-cols-2 gap-3">
                    <div className="space-y-1.5">
                      <label className="text-caption font-medium text-muted-foreground uppercase tracking-wider">
                        Column
                      </label>
                      <select
                        value={fk.column}
                        onChange={(e) =>
                          updateForeignKey(fk.id, { column: e.target.value })
                        }
                        className={selectClass}
                      >
                        <option value="">Select column…</option>
                        {columns.map((c) => (
                          <option key={c.id} value={c.name}>
                            {c.name}
                          </option>
                        ))}
                      </select>
                    </div>
                    <div className="space-y-1.5">
                      <label className="text-caption font-medium text-muted-foreground uppercase tracking-wider">
                        References
                      </label>
                      <div className="flex gap-1.5">
                        <Input
                          value={fk.refSchema}
                          onChange={(e) =>
                            updateForeignKey(fk.id, {
                              refSchema: e.target.value,
                            })
                          }
                          placeholder="schema"
                          className="h-9 text-xs w-24"
                        />
                        <Input
                          value={fk.refTable}
                          onChange={(e) =>
                            updateForeignKey(fk.id, {
                              refTable: e.target.value,
                            })
                          }
                          placeholder="table"
                          className="h-9 text-xs flex-1"
                        />
                        <Input
                          value={fk.refColumn}
                          onChange={(e) =>
                            updateForeignKey(fk.id, {
                              refColumn: e.target.value,
                            })
                          }
                          placeholder="column"
                          className="h-9 text-xs w-20"
                        />
                      </div>
                    </div>
                  </div>
                  <div className="grid grid-cols-2 gap-3">
                    <div className="space-y-1.5">
                      <label className="text-caption font-medium text-muted-foreground uppercase tracking-wider">
                        On Delete
                      </label>
                      <select
                        value={fk.onDelete}
                        onChange={(e) =>
                          updateForeignKey(fk.id, { onDelete: e.target.value })
                        }
                        className={selectClass}
                      >
                        {FK_ACTIONS.map((a) => (
                          <option key={a} value={a}>
                            {a}
                          </option>
                        ))}
                      </select>
                    </div>
                    <div className="space-y-1.5">
                      <label className="text-caption font-medium text-muted-foreground uppercase tracking-wider">
                        On Update
                      </label>
                      <select
                        value={fk.onUpdate}
                        onChange={(e) =>
                          updateForeignKey(fk.id, { onUpdate: e.target.value })
                        }
                        className={selectClass}
                      >
                        {FK_ACTIONS.map((a) => (
                          <option key={a} value={a}>
                            {a}
                          </option>
                        ))}
                      </select>
                    </div>
                  </div>
                  <div className="flex justify-end">
                    <Button
                      variant="ghost"
                      size="sm"
                      className="h-7 text-caption text-destructive hover:text-destructive"
                      onClick={() => removeForeignKey(fk.id)}
                    >
                      <Trash2 className="h-3 w-3" /> Remove
                    </Button>
                  </div>
                </div>
              ))}

              <button
                onClick={addForeignKey}
                className="w-full flex items-center justify-center gap-1.5 rounded-lg border border-dashed border-border bg-muted-panel py-2.5 text-xs text-muted-foreground hover:text-foreground hover:border-foreground-border hover:bg-muted-card transition-colors"
              >
                <Plus className="h-3.5 w-3.5" /> Add foreign key relation
              </button>
            </div>

            {/* SQL Preview */}
            {showSqlPreview && (
              <div className="rounded-lg border border-border bg-muted-panel p-4 space-y-3">
                <div className="flex items-center justify-between">
                  <h3 className="text-sm font-semibold text-foreground">
                    SQL Preview
                  </h3>
                  <div className="flex gap-2">
                    <Button
                      variant="outline"
                      size="sm"
                      className="h-8 gap-1"
                      onClick={handleCopySql}
                    >
                      <Copy className="h-3 w-3" /> Copy
                    </Button>
                    <Button
                      variant="outline"
                      size="sm"
                      className="h-8"
                      onClick={() => setShowSqlPreview(false)}
                    >
                      Cancel
                    </Button>
                  </div>
                </div>
                <textarea
                  value={rawSql || buildSql()}
                  onChange={(e) => setRawSql(e.target.value)}
                  className="text-xs font-mono bg-background rounded p-3 w-full min-h-[120px] max-h-48 overflow-y-auto border border-border resize-y block"
                  spellCheck={false}
                />
                <p className="text-xs text-muted-foreground">
                  Edit the SQL above if needed, then click Execute to create the
                  table.
                </p>
              </div>
            )}
          </div>
        </ScrollArea>

        {/* Footer */}
        <div className="flex items-center justify-end gap-2 px-6 py-4 border-t border-border bg-muted-panel">
          <Button
            variant="outline"
            size="sm"
            onClick={() => handleClose(false)}
            className="h-9 px-4"
          >
            Cancel
          </Button>
          {!showSqlPreview ? (
            <>
              <Button
                variant="outline"
                size="sm"
                onClick={handleSaveSql}
                className="h-9 px-4 gap-1.5"
                disabled={!tableName.trim() || !!tableNameError}
              >
                <Save className="h-3.5 w-3.5" /> Save SQL
              </Button>
              <Button
                size="sm"
                onClick={handleExecute}
                disabled={saving || !tableName.trim() || !!tableNameError}
                className="h-9 px-4"
              >
                {saving && <Loader2 className="h-3 w-3 mr-1.5 animate-spin" />}
                Execute
              </Button>
            </>
          ) : (
            <>
              <Button
                variant="outline"
                size="sm"
                onClick={handleCopySql}
                className="h-9 px-4 gap-1.5"
              >
                <Copy className="h-3.5 w-3.5" /> Copy SQL
              </Button>
              <Button
                size="sm"
                onClick={handleExecute}
                disabled={saving}
                className="h-9 px-4"
              >
                {saving && <Loader2 className="h-3 w-3 mr-1.5 animate-spin" />}
                Execute
              </Button>
            </>
          )}
        </div>
      </DialogContent>
    </Dialog>
  );
}
