import { useState, useCallback } from "react";
import {
  ResizableHandle,
  ResizablePanel,
  ResizablePanelGroup,
} from "@/components/ui/resizable";
import { SqlEditor } from "@/components/editor/SqlEditor";
import { ResultsPanel } from "@/components/results/ResultsPanel";
import { ExplainView } from "@/components/results/ExplainView";
import { useQueryExecution } from "@/hooks/use-query-execution";
import { useAddHistory } from "@/hooks/use-history";
import { useCompletionSchema } from "@/hooks/use-completion-schema";
import { useConnections } from "@/hooks/use-connections";
import { useAppStore } from "@/stores/app-store";
import { Button } from "@/components/ui/button";
import { Play, Loader2, Lock, BarChart3, Download, AlignLeft, Bookmark, Table2, Braces } from "lucide-react";
import { format as formatSql } from "sql-formatter";
import { SaveQueryDialog } from "@/components/saved-queries/SaveQueryDialog";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { exportCsv, exportJson } from "@/lib/tauri";
import { save } from "@tauri-apps/plugin-dialog";
import { toast } from "sonner";
import type { QueryResult, ExplainResult } from "@/types";

interface Props {
  connectionId: string;
  initialSql?: string;
  onSqlChange?: (sql: string) => void;
  onResult?: (result: QueryResult | null, error: string | null) => void;
}

export function WorkspacePanel({
  connectionId,
  initialSql = "",
  onSqlChange,
  onResult,
}: Props) {
  const readOnlyMap = useAppStore((s) => s.readOnlyMap);
  const currentDatabase = useAppStore((s) => s.currentDatabase);
  const isReadOnly = readOnlyMap[connectionId] ?? true;

  const [sqlValue, setSqlValue] = useState(initialSql);
  const [result, setResult] = useState<QueryResult | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [explainData, setExplainData] = useState<ExplainResult | null>(null);
  const [resultView, setResultView] = useState<"results" | "explain">("results");
  const [resultViewMode, setResultViewMode] = useState<"table" | "json">("table");
  const [saveDialogOpen, setSaveDialogOpen] = useState(false);

  const queryMutation = useQueryExecution();
  const addHistoryMutation = useAddHistory();
  const { data: connections } = useConnections();
  const { data: completionSchema } = useCompletionSchema(connectionId);

  const connName =
    connections?.find((c) => c.id === connectionId)?.name ?? "unknown";

  const handleChange = useCallback(
    (val: string) => {
      setSqlValue(val);
      onSqlChange?.(val);
    },
    [onSqlChange]
  );

  const recordHistory = useCallback(
    (
      sql: string,
      status: "success" | "error",
      executionTimeMs: number,
      rowCount?: number,
      errorMessage?: string
    ) => {
      addHistoryMutation.mutate({
        id: crypto.randomUUID(),
        connection_id: connectionId,
        connection_name: connName,
        database: currentDatabase ?? "",
        sql,
        status,
        error_message: errorMessage,
        row_count: rowCount,
        execution_time_ms: executionTimeMs,
        executed_at: new Date().toISOString(),
      });
    },
    [addHistoryMutation, connectionId, connName, currentDatabase]
  );

  const handleExecute = useCallback(() => {
    if (!sqlValue.trim() || !connectionId) return;
    setError(null);
    setExplainData(null);
    setResultView("results");
    queryMutation.mutate(
      { connectionId, sql: sqlValue },
      {
        onSuccess: (data) => {
          setResult(data);
          setError(null);
          onResult?.(data, null);
          recordHistory(
            sqlValue,
            "success",
            data.execution_time_ms,
            data.row_count
          );
        },
        onError: (err) => {
          setResult(null);
          setError(String(err));
          onResult?.(null, String(err));
          recordHistory(sqlValue, "error", 0, undefined, String(err));
        },
      }
    );
  }, [connectionId, sqlValue, queryMutation, onResult, recordHistory]);

  const handleExplain = useCallback(() => {
    if (!sqlValue.trim() || !connectionId) return;
    setError(null);
    const explainSql = `EXPLAIN (ANALYZE, COSTS, BUFFERS, FORMAT JSON) ${sqlValue}`;
    queryMutation.mutate(
      { connectionId, sql: explainSql },
      {
        onSuccess: (data) => {
          try {
            const raw = data.rows[0]?.[0];
            const parsed =
              typeof raw === "string" ? JSON.parse(raw) : raw;
            const plan: ExplainResult = Array.isArray(parsed)
              ? parsed[0]
              : parsed;
            setExplainData(plan);
            setResultView("explain");
            setResult(null);
            setError(null);
          } catch {
            setError("Failed to parse EXPLAIN output");
            setExplainData(null);
          }
        },
        onError: (err) => {
          setResult(null);
          setError(String(err));
          setExplainData(null);
        },
      }
    );
  }, [connectionId, sqlValue, queryMutation]);

  const handleFormat = useCallback(() => {
    if (!sqlValue.trim()) return;
    try {
      const formatted = formatSql(sqlValue, { language: "postgresql" });
      setSqlValue(formatted);
      onSqlChange?.(formatted);
    } catch {
      // Silently ignore format errors on invalid SQL
    }
  }, [sqlValue, onSqlChange]);

  const handleExport = useCallback(
    async (format: "csv" | "json") => {
      if (!result || result.columns.length === 0) return;
      const ext = format === "csv" ? "csv" : "json";
      const path = await save({
        title: `Export as ${ext.toUpperCase()}`,
        defaultPath: `query_result.${ext}`,
        filters: [{ name: ext.toUpperCase(), extensions: [ext] }],
      });
      if (!path) return;
      try {
        if (format === "csv") {
          await exportCsv(path, result.columns, result.rows as unknown[][]);
        } else {
          await exportJson(path, result.columns, result.rows as unknown[][]);
        }
        toast.success(`Exported to ${path}`);
      } catch (err) {
        toast.error("Export failed", { description: String(err) });
      }
    },
    [result]
  );

  return (
    <>
    <ResizablePanelGroup orientation="vertical">
      <ResizablePanel id="editor" defaultSize="40%" minSize="15%">
        <div className="flex h-full flex-col">
          {/* Editor action bar */}
          <div className="flex items-center gap-1 border-b border-border/40 px-2 py-1">
            <Button
              size="xs"
              variant="ghost"
              className="gap-1 text-[11px] text-primary hover:bg-primary/10 hover:text-primary"
              onClick={handleExecute}
              disabled={queryMutation.isPending || !sqlValue.trim()}
            >
              {queryMutation.isPending && resultView === "results" ? (
                <Loader2 className="h-3 w-3 animate-spin" />
              ) : (
                <Play className="h-3 w-3" />
              )}
              Run
            </Button>
            <Button
              size="xs"
              variant="ghost"
              className="gap-1 text-[11px]"
              onClick={handleExplain}
              disabled={queryMutation.isPending || !sqlValue.trim()}
            >
              {queryMutation.isPending && resultView === "explain" ? (
                <Loader2 className="h-3 w-3 animate-spin" />
              ) : (
                <BarChart3 className="h-3 w-3" />
              )}
              Explain
            </Button>
            <Button
              size="xs"
              variant="ghost"
              className="gap-1 text-[11px]"
              onClick={handleFormat}
              disabled={!sqlValue.trim()}
              title="Format SQL (Shift+Alt+F)"
            >
              <AlignLeft className="h-3 w-3" />
              Format
            </Button>
            <Button
              size="xs"
              variant="ghost"
              className="gap-1 text-[11px]"
              onClick={() => setSaveDialogOpen(true)}
              disabled={!sqlValue.trim()}
              title="Save query"
            >
              <Bookmark className="h-3 w-3" />
              Save
            </Button>

            {result && result.columns.length > 0 && (
              <>
                <div className="mx-1 h-3.5 w-px bg-border/40" />
                <DropdownMenu>
                  <DropdownMenuTrigger asChild>
                    <Button
                      size="xs"
                      variant="ghost"
                      className="gap-1 text-[11px]"
                    >
                      <Download className="h-3 w-3" />
                      Export
                    </Button>
                  </DropdownMenuTrigger>
                  <DropdownMenuContent align="start">
                    <DropdownMenuItem onClick={() => handleExport("csv")}>
                      Export CSV
                    </DropdownMenuItem>
                    <DropdownMenuItem onClick={() => handleExport("json")}>
                      Export JSON
                    </DropdownMenuItem>
                  </DropdownMenuContent>
                </DropdownMenu>
              </>
            )}

            <div className="flex-1" />

            <span className="text-[10px] text-muted-foreground/50 font-mono">
              {"\u2318"}Enter
            </span>
            {isReadOnly && (
              <span className="ml-2 flex items-center gap-1 rounded-sm bg-warning/10 px-1.5 py-0.5 text-[10px] font-semibold tracking-wide text-warning">
                <Lock className="h-2.5 w-2.5" />
                READ
              </span>
            )}
          </div>
          <div className="min-h-0 flex-1">
            <SqlEditor
              value={sqlValue}
              onChange={handleChange}
              onExecute={handleExecute}
              onFormat={handleFormat}
              schema={completionSchema}
            />
          </div>
        </div>
      </ResizablePanel>
      <ResizableHandle withHandle />
      <ResizablePanel id="results" defaultSize="60%" minSize="15%">
        <div className="flex h-full flex-col overflow-hidden">
          {(explainData || result || error) && (
            <div className="flex shrink-0 items-center border-b border-border/40 text-xs">
              <button
                className={`relative px-3 py-1.5 font-medium transition-colors ${
                  resultView === "results"
                    ? "text-foreground"
                    : "text-muted-foreground hover:text-foreground/70"
                }`}
                onClick={() => setResultView("results")}
              >
                Results
                {resultView === "results" && (
                  <span className="absolute bottom-0 left-1/4 right-1/4 h-0.5 rounded-t bg-primary" />
                )}
              </button>
              {explainData && (
                <button
                  className={`relative px-3 py-1.5 font-medium transition-colors ${
                    resultView === "explain"
                      ? "text-foreground"
                      : "text-muted-foreground hover:text-foreground/70"
                  }`}
                  onClick={() => setResultView("explain")}
                >
                  Explain
                  {resultView === "explain" && (
                    <span className="absolute bottom-0 left-1/4 right-1/4 h-0.5 rounded-t bg-primary" />
                  )}
                </button>
              )}
              {resultView === "results" && result && result.columns.length > 0 && (
                <div className="ml-auto mr-2 flex items-center overflow-hidden rounded border border-border/40">
                  <button
                    className={`flex items-center gap-1 px-2 py-0.5 text-[11px] font-medium transition-colors ${
                      resultViewMode === "table"
                        ? "bg-accent text-foreground"
                        : "text-muted-foreground hover:text-foreground"
                    }`}
                    onClick={() => setResultViewMode("table")}
                    title="Table view"
                  >
                    <Table2 className="h-3 w-3" />
                    Table
                  </button>
                  <button
                    className={`flex items-center gap-1 px-2 py-0.5 text-[11px] font-medium transition-colors ${
                      resultViewMode === "json"
                        ? "bg-accent text-foreground"
                        : "text-muted-foreground hover:text-foreground"
                    }`}
                    onClick={() => setResultViewMode("json")}
                    title="JSON view"
                  >
                    <Braces className="h-3 w-3" />
                    JSON
                  </button>
                </div>
              )}
            </div>
          )}
          <div className="min-h-0 flex-1">
            {resultView === "explain" && explainData ? (
              <ExplainView data={explainData} />
            ) : (
              <ResultsPanel
                result={result}
                error={error}
                isLoading={queryMutation.isPending && resultView === "results"}
                viewMode={resultViewMode}
              />
            )}
          </div>
        </div>
      </ResizablePanel>
    </ResizablePanelGroup>

    <SaveQueryDialog
      open={saveDialogOpen}
      onOpenChange={setSaveDialogOpen}
      sql={sqlValue}
      connectionId={connectionId}
    />
    </>
  );
}
