import { useState } from "react";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogFooter,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import { useSaveConnection, useTestConnection } from "@/hooks/use-connections";
import { toast } from "sonner";
import type { ConnectionConfig, DbFlavor } from "@/types";
import { ENVIRONMENTS } from "@/lib/environment";
import { capsFor } from "@/lib/dbCapabilities";
import { Loader2, X } from "lucide-react";

type InputMode = "fields" | "dsn";

function parseDsn(dsn: string): Partial<ConnectionConfig> | null {
  try {
    const trimmed = dsn.trim();
    // Support both postgres:// and postgresql://
    const match = trimmed.match(
      /^(?:postgres(?:ql)?):\/\/(?:([^:@]*?)(?::([^@]*?))?@)?([^/:?]+)(?::(\d+))?(?:\/([^?]*))?(?:\?(.*))?$/
    );
    if (!match) return null;

    const [, user, password, host, port, database, queryStr] = match;

    const result: Partial<ConnectionConfig> = {};
    if (host) result.host = decodeURIComponent(host);
    if (port) result.port = parseInt(port, 10);
    if (user) result.user = decodeURIComponent(user);
    if (password !== undefined) result.password = decodeURIComponent(password);
    if (database) result.database = decodeURIComponent(database);

    if (queryStr) {
      const params = new URLSearchParams(queryStr);
      const ssl = params.get("sslmode");
      if (ssl) result.ssl_mode = ssl;
    }

    return result;
  } catch {
    return null;
  }
}

function buildDsn(config: ConnectionConfig): string {
  const ssl = config.ssl_mode ?? "prefer";
  const user = encodeURIComponent(config.user);
  const pass = config.password ? `:${encodeURIComponent(config.password)}` : "";
  const auth = config.user ? `${user}${pass}@` : "";
  return `postgresql://${auth}${config.host}:${config.port}/${encodeURIComponent(config.database)}?sslmode=${ssl}`;
}

const CONNECTION_COLORS = [
  { name: "Red", value: "#ef4444" },
  { name: "Orange", value: "#f97316" },
  { name: "Yellow", value: "#eab308" },
  { name: "Green", value: "#22c55e" },
  { name: "Cyan", value: "#06b6d4" },
  { name: "Blue", value: "#3b82f6" },
  { name: "Purple", value: "#a855f7" },
  { name: "Pink", value: "#ec4899" },
];

interface Props {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  connection?: ConnectionConfig | null;
}

const emptyConfig: ConnectionConfig = {
  id: "",
  name: "",
  host: "localhost",
  port: 5432,
  user: "postgres",
  password: "",
  database: "postgres",
  ssl_mode: "prefer",
  color: undefined,
  environment: undefined,
  db_flavor: "postgresql",
  secure: false,
};

export function ConnectionDialog({ open, onOpenChange, connection }: Props) {
  const [form, setForm] = useState<ConnectionConfig>(emptyConfig);
  const [mode, setMode] = useState<InputMode>("fields");
  const [dsn, setDsn] = useState("");
  const [dsnError, setDsnError] = useState<string | null>(null);
  const saveMutation = useSaveConnection();
  const testMutation = useTestConnection();

  const [prev, setPrev] = useState<{ open: boolean; connection: typeof connection }>({ open: false, connection: null });
  if (open !== prev.open || connection !== prev.connection) {
    setPrev({ open, connection });
    if (open) {
      const config = connection ?? { ...emptyConfig, id: crypto.randomUUID() };
      setForm(config);
      setMode("fields");
      setDsn(connection ? buildDsn(config) : "");
      setDsnError(null);
    }
  }

  const flavor: DbFlavor = form.db_flavor ?? "postgresql";
  const isClickHouse = flavor === "clickhouse";

  const update = (field: keyof ConnectionConfig, value: string | number | boolean) => {
    setForm((f) => ({ ...f, [field]: value }));
  };

  const handleFlavorChange = (next: DbFlavor) => {
    setForm((f) => {
      const caps = capsFor(next);
      // If user is on a default port for current flavor, swap to the new flavor's default
      const currentDefault = capsFor(f.db_flavor).defaultPort;
      const port = f.port === currentDefault ? caps.defaultPort : f.port;
      return {
        ...f,
        db_flavor: next,
        port,
        secure: next === "clickhouse" ? f.secure ?? false : false,
        ssl_mode: next === "clickhouse" ? undefined : f.ssl_mode ?? "prefer",
      };
    });
  };

  const handleTest = () => {
    testMutation.mutate(form, {
      onSuccess: (version) => {
        toast.success("Connection successful", { description: version });
      },
      onError: (err) => {
        toast.error("Connection failed", { description: String(err) });
      },
    });
  };

  const handleSave = () => {
    if (!form.name.trim()) {
      toast.error("Name is required");
      return;
    }
    saveMutation.mutate(form, {
      onSuccess: () => {
        toast.success("Connection saved");
        onOpenChange(false);
      },
      onError: (err) => {
        toast.error("Save failed", { description: String(err) });
      },
    });
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-[480px]">
        <DialogHeader>
          <DialogTitle>
            {connection ? "Edit Connection" : "New Connection"}
          </DialogTitle>
        </DialogHeader>

        <div className="grid gap-3 py-4">
          <div className="grid grid-cols-4 items-center gap-3">
            <label className="text-right text-sm text-muted-foreground">
              Name
            </label>
            <Input
              className="col-span-3"
              value={form.name}
              onChange={(e) => update("name", e.target.value)}
              placeholder="My Database"
            />
          </div>

          <div className="grid grid-cols-4 items-center gap-3">
            <label className="text-right text-sm text-muted-foreground">
              Engine
            </label>
            <Select value={flavor} onValueChange={(v) => handleFlavorChange(v as DbFlavor)}>
              <SelectTrigger className="col-span-3">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="postgresql">PostgreSQL</SelectItem>
                <SelectItem value="greenplum">Greenplum</SelectItem>
                <SelectItem value="clickhouse">ClickHouse</SelectItem>
              </SelectContent>
            </Select>
          </div>

          {!isClickHouse && (
          <div className="grid grid-cols-4 items-center gap-3">
            <label className="text-right text-sm text-muted-foreground">
              Mode
            </label>
            <div className="col-span-3 flex gap-1 rounded-md border p-0.5">
              <button
                type="button"
                className={`flex-1 rounded-sm px-2 py-1 text-xs font-medium transition-colors ${
                  mode === "fields"
                    ? "bg-background text-foreground shadow-sm"
                    : "text-muted-foreground hover:text-foreground"
                }`}
                onClick={() => {
                  if (mode === "dsn") {
                    const parsed = parseDsn(dsn);
                    if (parsed) {
                      setForm((f) => ({ ...f, ...parsed }));
                      setDsnError(null);
                    }
                  }
                  setMode("fields");
                }}
              >
                Fields
              </button>
              <button
                type="button"
                className={`flex-1 rounded-sm px-2 py-1 text-xs font-medium transition-colors ${
                  mode === "dsn"
                    ? "bg-background text-foreground shadow-sm"
                    : "text-muted-foreground hover:text-foreground"
                }`}
                onClick={() => {
                  setDsn(buildDsn(form));
                  setDsnError(null);
                  setMode("dsn");
                }}
              >
                DSN
              </button>
            </div>
          </div>
          )}

          {!isClickHouse && mode === "dsn" ? (
            <div className="grid grid-cols-4 items-start gap-3">
              <label className="text-right text-sm text-muted-foreground pt-2">
                DSN
              </label>
              <div className="col-span-3 space-y-1.5">
                <Input
                  className="font-mono text-xs"
                  value={dsn}
                  onChange={(e) => {
                    const value = e.target.value;
                    setDsn(value);
                    if (value.trim()) {
                      const parsed = parseDsn(value);
                      if (parsed) {
                        setForm((f) => ({ ...f, ...parsed }));
                        setDsnError(null);
                      } else {
                        setDsnError("Invalid DSN format");
                      }
                    } else {
                      setDsnError(null);
                    }
                  }}
                  placeholder="postgresql://user:password@host:5432/database?sslmode=prefer"
                />
                {dsnError && (
                  <p className="text-xs text-destructive">{dsnError}</p>
                )}
                <p className="text-[11px] text-muted-foreground">
                  postgresql://user:password@host:port/database?sslmode=prefer
                </p>
              </div>
            </div>
          ) : (
            <>
              <div className="grid grid-cols-4 items-center gap-3">
                <label className="text-right text-sm text-muted-foreground">
                  Host
                </label>
                <Input
                  className="col-span-3"
                  value={form.host}
                  onChange={(e) => update("host", e.target.value)}
                />
              </div>
              <div className="grid grid-cols-4 items-center gap-3">
                <label className="text-right text-sm text-muted-foreground">
                  Port
                </label>
                <Input
                  className="col-span-3"
                  type="number"
                  value={form.port}
                  onChange={(e) =>
                    update(
                      "port",
                      parseInt(e.target.value) || capsFor(flavor).defaultPort,
                    )
                  }
                />
              </div>
              <div className="grid grid-cols-4 items-center gap-3">
                <label className="text-right text-sm text-muted-foreground">
                  User
                </label>
                <Input
                  className="col-span-3"
                  value={form.user}
                  onChange={(e) => update("user", e.target.value)}
                />
              </div>
              <div className="grid grid-cols-4 items-center gap-3">
                <label className="text-right text-sm text-muted-foreground">
                  Password
                </label>
                <Input
                  className="col-span-3"
                  type="password"
                  value={form.password}
                  onChange={(e) => update("password", e.target.value)}
                />
              </div>
              <div className="grid grid-cols-4 items-center gap-3">
                <label className="text-right text-sm text-muted-foreground">
                  Database
                </label>
                <Input
                  className="col-span-3"
                  value={form.database}
                  onChange={(e) => update("database", e.target.value)}
                />
              </div>
              {isClickHouse ? (
                <div className="grid grid-cols-4 items-center gap-3">
                  <label className="text-right text-sm text-muted-foreground">
                    HTTPS
                  </label>
                  <div className="col-span-3 flex items-center gap-2">
                    <Button
                      type="button"
                      size="sm"
                      variant={form.secure ? "default" : "outline"}
                      className="h-7 px-3 text-xs"
                      onClick={() => update("secure", !form.secure)}
                    >
                      {form.secure ? "On" : "Off"}
                    </Button>
                    <span className="text-xs text-muted-foreground">
                      Use HTTPS scheme for ClickHouse HTTP endpoint
                    </span>
                  </div>
                </div>
              ) : (
                <div className="grid grid-cols-4 items-center gap-3">
                  <label className="text-right text-sm text-muted-foreground">
                    SSL Mode
                  </label>
                  <Select
                    value={form.ssl_mode ?? "prefer"}
                    onValueChange={(v) => update("ssl_mode", v)}
                  >
                    <SelectTrigger className="col-span-3">
                      <SelectValue />
                    </SelectTrigger>
                    <SelectContent>
                      <SelectItem value="disable">Disable</SelectItem>
                      <SelectItem value="prefer">Prefer</SelectItem>
                      <SelectItem value="require">Require</SelectItem>
                    </SelectContent>
                  </Select>
                </div>
              )}
            </>
          )}
          <div className="grid grid-cols-4 items-center gap-3">
            <label className="text-right text-sm text-muted-foreground">
              Environment
            </label>
            <Select
              value={form.environment ?? "__none__"}
              onValueChange={(v) =>
                setForm((f) => ({
                  ...f,
                  environment: v === "__none__" ? undefined : v,
                }))
              }
            >
              <SelectTrigger className="col-span-3">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="__none__">None</SelectItem>
                {ENVIRONMENTS.map((env) => (
                  <SelectItem key={env.value} value={env.value}>
                    <div className="flex items-center gap-2">
                      <span
                        className="h-2 w-2 rounded-full"
                        style={{ backgroundColor: env.color }}
                      />
                      {env.label}
                    </div>
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
          <div className="grid grid-cols-4 items-center gap-3">
            <label className="text-right text-sm text-muted-foreground">
              Color
            </label>
            <div className="col-span-3 flex items-center gap-1.5">
              <button
                type="button"
                className={`flex h-6 w-6 items-center justify-center rounded-full border-2 ${
                  !form.color ? "border-primary" : "border-transparent"
                } bg-muted`}
                onClick={() => setForm((f) => ({ ...f, color: undefined }))}
                title="No color"
              >
                <X className="h-3 w-3 text-muted-foreground" />
              </button>
              {CONNECTION_COLORS.map((c) => (
                <button
                  key={c.value}
                  type="button"
                  className={`h-6 w-6 rounded-full border-2 ${
                    form.color === c.value
                      ? "border-primary"
                      : "border-transparent"
                  }`}
                  style={{ backgroundColor: c.value }}
                  onClick={() => setForm((f) => ({ ...f, color: c.value }))}
                  title={c.name}
                />
              ))}
            </div>
          </div>
        </div>

        <DialogFooter>
          <Button
            variant="outline"
            onClick={handleTest}
            disabled={testMutation.isPending}
          >
            {testMutation.isPending && (
              <Loader2 className="mr-2 h-4 w-4 animate-spin" />
            )}
            Test
          </Button>
          <Button onClick={handleSave} disabled={saveMutation.isPending}>
            {saveMutation.isPending && (
              <Loader2 className="mr-2 h-4 w-4 animate-spin" />
            )}
            Save
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
