import { FormEvent } from "react";
import { ChevronRight, RefreshCw, Table2 } from "lucide-react";
import { RowValues, TableMetadata } from "@/app/lib/api";
import { Badge } from "@/app/components/ui/badge";
import { Button } from "@/app/components/ui/button";
import {
  Card,
  CardContent,
  CardHeader,
  CardTitle,
} from "@/app/components/ui/card";
import { Input } from "@/app/components/ui/input";
import { Label } from "@/app/components/ui/label";
import { Textarea } from "@/app/components/ui/textarea";

type Driver = "athena" | "postgresql" | "supabase";

type DatabaseTabProps = {
  busy: boolean;
  selectedClient: string;
  schemaClients: string[];
  onSelectedClientChange: (value: string) => void;
  onRefresh: () => void;
  tables: TableMetadata[];
  selectedTableName: string;
  onSelectTable: (table: TableMetadata) => void;
  visibleColumns: string[];
  rowConditionColumn: string;
  onRowConditionColumnChange: (value: string) => void;
  rows: RowValues[];
  rowEdits: Record<string, Record<string, string>>;
  onRowEditChange: (rowKey: string, column: string, value: string) => void;
  onSaveRow: (rowIndex: number, row: RowValues) => void;
  onInsertSubmit: (event: FormEvent) => void;
  insertPayload: string;
  onInsertPayloadChange: (value: string) => void;
  onDeleteSubmit: (event: FormEvent) => void;
  deleteResourceId: string;
  onDeleteResourceIdChange: (value: string) => void;
  createTableJson: string;
  onCreateTableJsonChange: (value: string) => void;
  onCreateTable: () => void;
  editTableJson: string;
  onEditTableJsonChange: (value: string) => void;
  onApplyTableEdit: () => void;
  dropSchemaName: string;
  onDropSchemaNameChange: (value: string) => void;
  dropCascade: boolean;
  onDropCascadeChange: (value: boolean) => void;
  onDropTable: () => void;
  createIndexJson: string;
  onCreateIndexJsonChange: (value: string) => void;
  onCreateIndex: () => void;
  dropIndexName: string;
  onDropIndexNameChange: (value: string) => void;
  dropIndexSchema: string;
  onDropIndexSchemaChange: (value: string) => void;
  onDropIndex: () => void;
  sql: string;
  onSqlChange: (value: string) => void;
  sqlDriver: Driver;
  onSqlDriverChange: (value: Driver) => void;
  sqlDbName: string;
  onSqlDbNameChange: (value: string) => void;
  onRunSql: () => void;
  sqlResult: string;
};

function 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 DatabaseTab({
  busy,
  selectedClient,
  schemaClients,
  onSelectedClientChange,
  onRefresh,
  tables,
  selectedTableName,
  onSelectTable,
  visibleColumns,
  rowConditionColumn,
  onRowConditionColumnChange,
  rows,
  rowEdits,
  onRowEditChange,
  onSaveRow,
  onInsertSubmit,
  insertPayload,
  onInsertPayloadChange,
  onDeleteSubmit,
  deleteResourceId,
  onDeleteResourceIdChange,
  createTableJson,
  onCreateTableJsonChange,
  onCreateTable,
  editTableJson,
  onEditTableJsonChange,
  onApplyTableEdit,
  dropSchemaName,
  onDropSchemaNameChange,
  dropCascade,
  onDropCascadeChange,
  onDropTable,
  createIndexJson,
  onCreateIndexJsonChange,
  onCreateIndex,
  dropIndexName,
  onDropIndexNameChange,
  dropIndexSchema,
  onDropIndexSchemaChange,
  onDropIndex,
  sql,
  onSqlChange,
  sqlDriver,
  onSqlDriverChange,
  sqlDbName,
  onSqlDbNameChange,
  onRunSql,
  sqlResult,
}: DatabaseTabProps) {
  return (
    <div className="grid h-full min-h-0 gap-4 xl:grid-cols-[280px_minmax(0,1fr)_420px]">
      <Card className="h-full min-h-0">
        <CardHeader className="pb-2">
          <div className="flex items-center justify-between">
            <CardTitle className="flex items-center gap-2">
              <Table2 className="h-4 w-4" /> Tables
            </CardTitle>
            <Button
              size="sm"
              variant="outline"
              onClick={onRefresh}
              disabled={busy}
            >
              <RefreshCw className="h-3 w-3" /> Refresh
            </Button>
          </div>
        </CardHeader>
        <CardContent className="space-y-3">
          <div className="space-y-1">
            <Label>X-Athena-Client</Label>
            <select
              value={selectedClient}
              onChange={(event) => onSelectedClientChange(event.target.value)}
              className="h-9 w-full rounded-md border border-border bg-surface-subtle px-3 text-sm"
            >
              {schemaClients.map((client) => (
                <option key={client} value={client}>
                  {client}
                </option>
              ))}
            </select>
          </div>
          <div className="h-[calc(100vh-300px)] overflow-auto rounded-md border border-border">
            {tables.map((table) => (
              <button
                key={`${table.table_schema ?? "public"}.${table.table_name}`}
                onClick={() => onSelectTable(table)}
                className={`flex w-full items-center justify-between border-b border-border px-3 py-2 text-left text-sm hover:bg-muted-card ${table.table_name === selectedTableName ? "bg-primary-subtle" : ""}`}
              >
                <div>
                  <p>{table.table_name}</p>
                  <p className="text-xs text-muted-foreground">
                    {table.table_schema ?? "public"}
                  </p>
                </div>
                <ChevronRight className="h-4 w-4 text-muted-foreground" />
              </button>
            ))}
          </div>
        </CardContent>
      </Card>

      <Card className="h-full min-h-0">
        <CardHeader className="pb-2">
          <div className="flex flex-wrap items-center justify-between gap-3">
            <div>
              <CardTitle className="text-base">
                {selectedTableName || "Select table"}
              </CardTitle>
              <p className="text-xs text-muted-foreground">
                Editable full-screen data grid
              </p>
            </div>
            <div className="flex items-center gap-2">
              <Label>Update match</Label>
              <select
                value={rowConditionColumn}
                onChange={(event) =>
                  onRowConditionColumnChange(event.target.value)
                }
                className="h-8 rounded-md border border-border bg-surface-subtle px-2 text-xs"
              >
                {visibleColumns.map((name) => (
                  <option key={name} value={name}>
                    {name}
                  </option>
                ))}
              </select>
              <Badge variant="secondary">{rows.length} rows</Badge>
            </div>
          </div>
        </CardHeader>
        <CardContent className="flex h-[calc(100vh-220px)] min-h-0 flex-col gap-3">
          <div className="min-h-0 flex-1 overflow-auto rounded-md border border-border">
            <table className="w-full min-w-[900px] table-fixed border-collapse">
              <thead className="sticky top-0 z-10 bg-surface-elevated">
                <tr>
                  {visibleColumns.map((name) => (
                    <th
                      key={name}
                      className="border-b border-border px-2 py-2 text-left text-xs font-medium text-muted-foreground"
                    >
                      {name}
                    </th>
                  ))}
                  <th className="w-24 border-b border-border px-2 py-2 text-left text-xs font-medium text-muted-foreground">
                    Actions
                  </th>
                </tr>
              </thead>
              <tbody>
                {rows.map((row, rowIndex) => (
                  <tr key={`r-${rowIndex}`} className="border-b border-border">
                    {visibleColumns.map((column) => {
                      const rowKey = String(rowIndex);
                      const current =
                        rowEdits[rowKey]?.[column] ?? formatValue(row[column]);
                      return (
                        <td
                          key={`${rowIndex}-${column}`}
                          className="px-2 py-1 align-top"
                        >
                          <Input
                            value={current}
                            onChange={(event) =>
                              onRowEditChange(
                                rowKey,
                                column,
                                event.target.value,
                              )
                            }
                            className="h-8"
                          />
                        </td>
                      );
                    })}
                    <td className="px-2 py-1">
                      <Button
                        size="sm"
                        onClick={() => onSaveRow(rowIndex, row)}
                        disabled={busy}
                      >
                        Save
                      </Button>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>

          <div className="grid grid-cols-1 gap-3 xl:grid-cols-2">
            <form
              onSubmit={onInsertSubmit}
              className="space-y-2 rounded-md border border-border p-3"
            >
              <Label>Insert row</Label>
              <Textarea
                value={insertPayload}
                onChange={(event) => onInsertPayloadChange(event.target.value)}
                rows={5}
                className="font-mono text-xs"
              />
              <Button type="submit" size="sm" disabled={busy}>
                Insert
              </Button>
            </form>
            <form
              onSubmit={onDeleteSubmit}
              className="space-y-2 rounded-md border border-border p-3"
            >
              <Label>Delete row by resource_id</Label>
              <Input
                value={deleteResourceId}
                onChange={(event) =>
                  onDeleteResourceIdChange(event.target.value)
                }
                placeholder="resource_id"
              />
              <Button
                type="submit"
                size="sm"
                variant="destructive"
                disabled={busy}
              >
                Delete
              </Button>
            </form>
          </div>
        </CardContent>
      </Card>

      <Card className="h-full min-h-0">
        <CardHeader>
          <CardTitle>Schema + SQL</CardTitle>
        </CardHeader>
        <CardContent className="h-[calc(100vh-160px)] space-y-3 overflow-auto">
          <div className="space-y-2 rounded-md border border-border p-3">
            <Label>Create table</Label>
            <Textarea
              value={createTableJson}
              onChange={(event) => onCreateTableJsonChange(event.target.value)}
              rows={7}
              className="font-mono text-xs"
            />
            <Button
              size="sm"
              onClick={onCreateTable}
              disabled={busy || !selectedClient}
            >
              Create table
            </Button>
          </div>
          <div className="space-y-2 rounded-md border border-border p-3">
            <Label>Edit table</Label>
            <Textarea
              value={editTableJson}
              onChange={(event) => onEditTableJsonChange(event.target.value)}
              rows={7}
              className="font-mono text-xs"
            />
            <Button
              size="sm"
              variant="secondary"
              onClick={onApplyTableEdit}
              disabled={busy || !selectedClient}
            >
              Apply edit
            </Button>
          </div>
          <div className="space-y-2 rounded-md border border-border p-3">
            <Label>Drop table</Label>
            <div className="grid grid-cols-[1fr_auto] gap-2">
              <Input
                value={dropSchemaName}
                onChange={(event) => onDropSchemaNameChange(event.target.value)}
                placeholder="schema"
              />
              <label className="flex items-center gap-2 text-xs text-muted-foreground">
                <input
                  type="checkbox"
                  checked={dropCascade}
                  onChange={(event) =>
                    onDropCascadeChange(event.target.checked)
                  }
                />
                cascade
              </label>
            </div>
            <Button
              size="sm"
              variant="destructive"
              onClick={onDropTable}
              disabled={busy || !selectedClient || !selectedTableName}
            >
              Drop table
            </Button>
          </div>
          <div className="space-y-2 rounded-md border border-border p-3">
            <Label>Create index</Label>
            <Textarea
              value={createIndexJson}
              onChange={(event) => onCreateIndexJsonChange(event.target.value)}
              rows={5}
              className="font-mono text-xs"
            />
            <Button
              size="sm"
              onClick={onCreateIndex}
              disabled={busy || !selectedClient}
            >
              Create index
            </Button>
          </div>
          <div className="space-y-2 rounded-md border border-border p-3">
            <Label>Drop index</Label>
            <div className="grid grid-cols-2 gap-2">
              <Input
                value={dropIndexName}
                onChange={(event) => onDropIndexNameChange(event.target.value)}
                placeholder="index_name"
              />
              <Input
                value={dropIndexSchema}
                onChange={(event) =>
                  onDropIndexSchemaChange(event.target.value)
                }
                placeholder="schema"
              />
            </div>
            <Button
              size="sm"
              variant="destructive"
              onClick={onDropIndex}
              disabled={busy || !selectedClient}
            >
              Drop index
            </Button>
          </div>
          <div className="space-y-2 rounded-md border border-border p-3">
            <Label>Raw SQL executor</Label>
            <Textarea
              value={sql}
              onChange={(event) => onSqlChange(event.target.value)}
              rows={6}
              className="font-mono text-xs"
            />
            <div className="grid grid-cols-[auto_1fr_auto] gap-2">
              <select
                value={sqlDriver}
                onChange={(event) =>
                  onSqlDriverChange(event.target.value as Driver)
                }
                className="h-9 rounded-md border border-border bg-surface-subtle px-2 text-xs"
              >
                <option value="athena">athena</option>
                <option value="postgresql">postgresql</option>
                <option value="supabase">supabase</option>
              </select>
              <Input
                value={sqlDbName}
                onChange={(event) => onSqlDbNameChange(event.target.value)}
                placeholder="db_name"
              />
              <Button size="sm" onClick={onRunSql} disabled={busy}>
                Run SQL
              </Button>
            </div>
            <pre className="max-h-56 overflow-auto rounded-md border border-border bg-background p-2 text-body-sm text-muted-foreground">
              {sqlResult || "Result appears here."}
            </pre>
          </div>
        </CardContent>
      </Card>
    </div>
  );
}
