"use client";

import { cn } from "@/app/lib/utils";
import { TableMetadata } from "@/app/lib/api";
import { useSettings } from "@/app/lib/settings";
import { useAppStore } from "@/app/lib/store";
import { ScrollArea } from "./ui/scroll-area";
import { Badge } from "./ui/badge";
import { Input } from "./ui/input";
import {
  ContextMenu,
  ContextMenuTrigger,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuSeparator,
} from "./ui/context-menu";
import {
  Database,
  Table2,
  Search,
  ChevronDown,
  Loader2,
  Server,
  Zap,
  FileCode2,
  AlertCircle,
  Settings,
  Activity,
  KeyRound,
  BookOpen,
  FileText,
  ClipboardList,
  HardDrive,
  Code2,
  GitBranch,
  Users,
  Copy,
  Pencil,
  Download,
  Trash2,
  EyeOff,
  Link2,
  Menu,
  X,
  PanelLeftClose,
  BarChart3,
  Layers,
  Building2,
  ShieldCheck,
  Workflow,
} from "lucide-react";
import { useState, useMemo, useCallback } from "react";
import { toast } from "sonner";

type Props = {
  clients: string[];
  selectedClient: string | null;
  onClientChange: (client: string) => void;
  tables: TableMetadata[];
  selectedTable: TableMetadata | null;
  onSelectTable: (table: TableMetadata) => void;
  tablesLoading: boolean;
  tablesError: string | null;
  clientsLoading: boolean;
  clientsError: string | null;
  activeView: string;
  onViewChange: (view: string) => void;
  schemas: string[];
  currentSchema: string;
  onSchemaChange: (schema: string) => void;
  onShowConnection: () => void;
  onCollapse?: () => void;
};

const NAV_ITEMS = [
  { id: "table-editor", label: "Table Editor", icon: Table2 },
  { id: "sql-editor", label: "SQL Editor", icon: FileCode2 },
  { id: "database", label: "Database", icon: Database },
] as const;

const DB_NAV = [
  { id: "functions", label: "Functions", icon: Code2 },
  { id: "triggers", label: "Triggers", icon: Zap },
  { id: "replication", label: "Replication", icon: GitBranch },
  { id: "backups", label: "Backups", icon: HardDrive },
  { id: "pipelines", label: "Pipelines", icon: Workflow },
  { id: "auth", label: "Authentication", icon: Users },
  { id: "auth-config", label: "Auth Setup", icon: ShieldCheck },
] as const;

const BOTTOM_NAV = [
  { id: "logs", label: "Logs", icon: FileText },
  { id: "audit-log", label: "Audit Log", icon: ClipboardList },
  { id: "api-keys", label: "API Keys", icon: KeyRound },
  { id: "data-api", label: "Data API", icon: Server },
  { id: "observability", label: "Observability", icon: Activity },
  { id: "storage", label: "Storage", icon: HardDrive },
  {
    id: "client-statistics",
    label: "Client Statistics",
    icon: BarChart3,
    requiresKey: true,
    flagKey: "enableClientStatistics",
  },
  {
    id: "cluster-health",
    label: "Cluster Health",
    icon: Activity,
    flagKey: "enableClusterHealth",
  },
  {
    id: "sdk-docs",
    label: "SDK Docs",
    icon: BookOpen,
    flagKey: "enableSdkDocs",
  },
  { id: "modules", label: "Modules", icon: Layers, flagKey: "enableModules" },
  {
    id: "workspace",
    label: "Workspace",
    icon: Building2,
    flagKey: "enableWorkspaceSettings",
  },
  { id: "settings", label: "Settings", icon: Settings },
] as const;

export default function Sidebar({
  clients,
  selectedClient,
  onClientChange,
  tables,
  selectedTable,
  onSelectTable,
  tablesLoading,
  tablesError,
  clientsLoading,
  clientsError,
  activeView,
  onViewChange,
  schemas,
  currentSchema,
  onSchemaChange,
  onShowConnection,
  onCollapse,
}: Props) {
  const { baseUrl, apiKey, localBackupApiKey, isConfigured } = useSettings();
  const effectiveApiKey = apiKey || localBackupApiKey;
  const { flags, workspace } = useAppStore();
  const [tableFilter, setTableFilter] = useState("");
  const [mobileOpen, setMobileOpen] = useState(false);

  const hostname = useMemo(() => {
    try {
      return new URL(baseUrl).hostname;
    } catch {
      return baseUrl;
    }
  }, [baseUrl]);

  const filteredTables = useMemo(() => {
    if (!tableFilter) return tables;
    const l = tableFilter.toLowerCase();
    return tables.filter(
      (t) =>
        t.table_name.toLowerCase().includes(l) ||
        (t.table_schema ?? "").toLowerCase().includes(l),
    );
  }, [tables, tableFilter]);

  const grouped = useMemo(() => {
    const m = new Map<string, TableMetadata[]>();
    for (const t of filteredTables) {
      const s = t.table_schema ?? "public";
      if (!m.has(s)) m.set(s, []);
      m.get(s)!.push(t);
    }
    return m;
  }, [filteredTables]);

  const handleCopyName = useCallback((name: string) => {
    navigator.clipboard.writeText(name);
    toast.success("Copied table name");
  }, []);

  const handleCopySchema = useCallback((t: TableMetadata) => {
    const schema = t.table_schema ?? "public";
    navigator.clipboard.writeText(`${schema}.${t.table_name}`);
    toast.success("Copied schema-qualified name");
  }, []);

  const handleNavClick = useCallback(
    (id: string) => {
      onViewChange(id);
      setMobileOpen(false);
    },
    [onViewChange],
  );

  const sidebarContent = (
    <>
      {/* Logo */}
      <div className="flex items-center gap-2.5 border-b border-border px-3 py-2.5">
        <div
          className="flex h-7 w-7 items-center justify-center rounded text-white text-caption font-bold shrink-0"
          style={{ backgroundColor: workspace.logoColor }}
        >
          {workspace.logoInitials.slice(0, 2).toUpperCase()}
        </div>
        <div className="flex-1 min-w-0">
          <div className="text-xs font-semibold text-foreground tracking-tight leading-none truncate">
            {workspace.name}
          </div>
          <div className="text-tiny text-muted-foreground truncate leading-none mt-0.5">
            {hostname}
          </div>
        </div>
        <button
          onClick={() => onShowConnection()}
          className="p-1 rounded text-muted-foreground hover:text-foreground transition-colors"
          title="Connection info"
        >
          <Link2 className="h-3.5 w-3.5" />
        </button>
        {onCollapse && (
          <button
            onClick={onCollapse}
            className="p-1 rounded text-muted-foreground hover:text-foreground transition-colors"
            title="Hide sidebar"
          >
            <PanelLeftClose className="h-3.5 w-3.5" />
          </button>
        )}
      </div>

      {/* Client selector */}
      <div className="border-b border-border px-2.5 py-1.5">
        <div className="flex items-center gap-1.5 rounded border border-border-subtle bg-background px-2 py-1">
          <Server className="h-3 w-3 text-muted-foreground shrink-0" />
          {clientsLoading ? (
            <span className="flex items-center gap-1 text-body-sm text-muted-foreground">
              <Loader2 className="h-2.5 w-2.5 animate-spin" />
              Loading…
            </span>
          ) : clientsError ? (
            <button
              onClick={() => handleNavClick("settings")}
              className="flex items-center gap-1 text-body-sm text-destructive hover:text-foreground transition-colors w-full"
              title={clientsError}
            >
              <AlertCircle className="h-2.5 w-2.5 shrink-0" />
              <span className="truncate text-left">
                {isConfigured ? clientsError : "Set API key in Settings"}
              </span>
            </button>
          ) : clients.length === 0 ? (
            <button
              onClick={() => handleNavClick("settings")}
              className="flex items-center gap-1 text-body-sm text-muted-foreground hover:text-foreground transition-colors w-full"
            >
              <span className="truncate text-left">No clients available</span>
            </button>
          ) : (
            <select
              value={selectedClient ?? ""}
              onChange={(e) => e.target.value && onClientChange(e.target.value)}
              className="flex-1 bg-transparent text-body-sm text-foreground outline-none appearance-none cursor-pointer min-w-0"
            >
              <option value="" disabled>
                Select client
              </option>
              {clients.map((c) => (
                <option key={c} value={c}>
                  {c}
                </option>
              ))}
            </select>
          )}
          <ChevronDown className="h-2.5 w-2.5 text-muted-foreground shrink-0" />
        </div>

        {schemas.length > 1 && (
          <div className="flex items-center gap-1.5 mt-1 rounded border border-border-subtle bg-background px-2 py-1">
            <Database className="h-3 w-3 text-muted-foreground shrink-0" />
            <select
              value={currentSchema}
              onChange={(e) => onSchemaChange(e.target.value)}
              className="flex-1 bg-transparent text-body-sm text-foreground outline-none appearance-none cursor-pointer min-w-0"
            >
              {schemas.map((s) => (
                <option key={s} value={s}>
                  {s}
                </option>
              ))}
            </select>
            <ChevronDown className="h-2.5 w-2.5 text-muted-foreground shrink-0" />
          </div>
        )}
      </div>

      {/* Nav */}
      <nav className="border-b border-border px-1.5 py-1 space-y-px">
        {NAV_ITEMS.map((item) => (
          <button
            key={item.id}
            onClick={() => handleNavClick(item.id)}
            className={cn(
              "flex w-full items-center gap-2 rounded px-2.5 py-1 text-body-sm font-medium transition-colors",
              activeView === item.id
                ? "text-foreground"
                : "text-muted-foreground hover:text-foreground",
            )}
          >
            <item.icon
              className={cn(
                "h-3.5 w-3.5 shrink-0",
                activeView === item.id && "text-primary",
              )}
            />
            {item.label}
          </button>
        ))}
      </nav>

      {/* Table list */}
      <div className="flex flex-col flex-1 min-h-0">
        <div className="px-2.5 pt-2 pb-1.5">
          <div className="relative">
            <Search className="absolute left-2 top-1/2 h-3 w-3 -translate-y-1/2 text-muted-foreground" />
            <Input
              placeholder="Search tables..."
              value={tableFilter}
              onChange={(e) => setTableFilter(e.target.value)}
              className="h-6 pl-7 text-body-sm bg-background border-border-subtle"
            />
          </div>
        </div>
        <ScrollArea className="flex-1 px-1.5">
          {tablesLoading && (
            <div className="flex items-center justify-center py-6">
              <Loader2 className="h-3.5 w-3.5 animate-spin text-muted-foreground" />
            </div>
          )}
          {tablesError && !tablesLoading && (
            <div className="px-2 py-2 text-body-sm text-destructive">
              {tablesError}
            </div>
          )}
          {!tablesLoading && !tablesError && tables.length === 0 && (
            <div className="px-2 py-4 text-center text-body-sm text-muted-foreground">
              No tables found
            </div>
          )}
          {!tablesLoading &&
            Array.from(grouped.entries()).map(([schema, schemaTables]) => (
              <div key={schema} className="mb-1.5">
                <div className="flex items-center gap-1 px-1.5 py-0.5">
                  <ChevronDown className="h-2.5 w-2.5 text-muted-foreground-faint" />
                  <span className="text-tiny font-medium uppercase tracking-wider text-muted-foreground-subtle">
                    {schema}
                  </span>
                  <Badge
                    variant="secondary"
                    className="ml-auto h-3.5 px-1 text-2xs bg-accent"
                  >
                    {schemaTables.length}
                  </Badge>
                </div>
                <div className="space-y-px">
                  {schemaTables.map((t) => {
                    const sel =
                      t.table_name === selectedTable?.table_name &&
                      (t.table_schema ?? "public") ===
                        (selectedTable?.table_schema ?? "public");
                    return (
                      <ContextMenu
                        key={`${t.table_schema ?? "public"}.${t.table_name}`}
                      >
                        <ContextMenuTrigger asChild>
                          <button
                            onClick={() => {
                              onSelectTable(t);
                              setMobileOpen(false);
                            }}
                            className={cn(
                              "flex w-full items-center gap-1.5 rounded px-2 py-0.75 text-body-sm transition-colors",
                              sel
                                ? "text-foreground font-medium"
                                : "text-muted-foreground hover:text-foreground",
                            )}
                          >
                            <Table2
                              className={cn(
                                "h-3 w-3 shrink-0",
                                sel ? "text-primary opacity-100" : "opacity-40",
                              )}
                            />
                            <span className="truncate">{t.table_name}</span>
                          </button>
                        </ContextMenuTrigger>
                        <ContextMenuContent>
                          <ContextMenuItem
                            onClick={() => handleCopyName(t.table_name)}
                          >
                            <Copy className="h-3 w-3" /> Copy name
                          </ContextMenuItem>
                          <ContextMenuItem onClick={() => handleCopySchema(t)}>
                            <Copy className="h-3 w-3" /> Copy table schema
                          </ContextMenuItem>
                          <ContextMenuSeparator />
                          <ContextMenuItem
                            onClick={() => {
                              onSelectTable(t);
                              handleNavClick("table-editor");
                            }}
                          >
                            <Pencil className="h-3 w-3" /> Edit table
                          </ContextMenuItem>
                          <ContextMenuItem disabled>
                            <Download className="h-3 w-3" /> Export data
                          </ContextMenuItem>
                          <ContextMenuSeparator />
                          <ContextMenuItem disabled>
                            <EyeOff className="h-3 w-3" /> Hide table
                          </ContextMenuItem>
                          <ContextMenuItem destructive disabled>
                            <Trash2 className="h-3 w-3" /> Delete table
                          </ContextMenuItem>
                        </ContextMenuContent>
                      </ContextMenu>
                    );
                  })}
                </div>
              </div>
            ))}
        </ScrollArea>
      </div>

      {/* Database sub-nav */}
      <div className="border-t border-border px-1.5 py-1 space-y-px">
        <div className="px-2.5 py-0.5">
          <span className="text-tiny font-medium uppercase tracking-wider text-muted-foreground-dim">
            Database
          </span>
        </div>
        {DB_NAV.map((item) => (
          <button
            key={item.id}
            onClick={() => handleNavClick(item.id)}
            className={cn(
              "flex w-full items-center gap-2 rounded px-2.5 py-1 text-body-sm font-medium transition-colors",
              activeView === item.id
                ? "text-foreground"
                : "text-muted-foreground hover:text-foreground",
            )}
          >
            <item.icon
              className={cn(
                "h-3.5 w-3.5 shrink-0",
                activeView === item.id && "text-primary",
              )}
            />
            {item.label}
          </button>
        ))}
      </div>

      {/* Bottom nav */}
      <div className="border-t border-border px-1.5 py-1 space-y-px">
        {BOTTOM_NAV.filter((item) => {
          if ("requiresKey" in item && item.requiresKey && !effectiveApiKey)
            return false;
          if ("flagKey" in item && item.flagKey) {
            return flags[item.flagKey as keyof typeof flags];
          }
          return true;
        }).map((item) => (
          <button
            key={item.id}
            onClick={() => handleNavClick(item.id)}
            className={cn(
              "flex w-full items-center gap-2 rounded px-2.5 py-1 text-body-sm font-medium transition-colors",
              activeView === item.id
                ? "text-foreground"
                : "text-muted-foreground hover:text-foreground",
            )}
          >
            <item.icon
              className={cn(
                "h-3.5 w-3.5 shrink-0",
                activeView === item.id && "text-primary",
              )}
            />
            {item.label}
          </button>
        ))}
      </div>

      {/* Footer */}
      <div className="border-t border-border px-3 py-1.5">
        <div className="flex items-center gap-2">
          <div
            className={cn(
              "h-1.5 w-1.5 rounded-full",
              selectedClient ? "bg-success" : "bg-muted-panel",
            )}
          />
          <span className="text-caption text-muted-foreground-subtle truncate">
            {selectedClient ?? "Disconnected"}
          </span>
        </div>
      </div>
    </>
  );

  return (
    <>
      {/* Mobile toggle */}
      <button
        onClick={() => setMobileOpen(!mobileOpen)}
        className="fixed top-3 left-3 z-50 md:hidden flex h-8 w-8 items-center justify-center rounded-lg border border-border bg-card shadow-lg"
      >
        {mobileOpen ? <X className="h-4 w-4" /> : <Menu className="h-4 w-4" />}
      </button>

      {/* Mobile overlay */}
      {mobileOpen && (
        <div
          className="fixed inset-0 z-40 bg-overlay backdrop-blur-sm md:hidden transition-opacity"
          onClick={() => setMobileOpen(false)}
        />
      )}

      {/* Sidebar */}
      <aside
        className={cn(
          "flex h-full w-full flex-col border-r border-border bg-sidebar shrink-0",
          "md:min-w-[200px] md:max-w-80",
          "max-md:fixed max-md:z-40 max-md:top-0 max-md:left-0 max-md:w-70 max-md:shadow-2xl max-md:transition-transform max-md:duration-200",
          mobileOpen ? "max-md:translate-x-0" : "max-md:-translate-x-full",
        )}
      >
        {sidebarContent}
      </aside>
    </>
  );
}
