import { useState } from 'react';
import { Link, useLocation, useSearchParams } from 'react-router';
import { LayoutGrid, Plus, Pencil, Trash2, Search } from 'lucide-react';
import { useQueryClient } from '@tanstack/react-query';
import { useGlobal } from 'hooks/useGlobal';
import { useClient } from 'hooks/useClient';
import { useUserState } from 'state/useUserState';
import { useDashboardState, persistDashboardState } from 'state/useDashboardState';
import type { DashboardDefinition } from '../../components/Workspace';
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import {
  CREATING_DASHBOARD_KEY,
  EDITING_DASHBOARD_KEY,
  NEW_DASH_NAME_KEY,
  NEW_DASH_DESC_KEY,
  NEW_DASH_TEMPLATE_KEY,
} from './constants';
import { useNewDashboardDraft } from './useNewDashboardDraft';

export const DashboardListApp = () => {
  const location = useLocation();
  const client = useClient();
  const queryClient = useQueryClient();
  const { value: dashboards, setValue: setDashboards } = useDashboardState<DashboardDefinition[]>('workspaces', []);
  // Selection is URL state now (?selected=<id>), not a global — so it's deep-linkable and the rows are real links.
  const [searchParams, setSearchParams] = useSearchParams();
  const selected = searchParams.get('selected');
  const clearSelected = () =>
    setSearchParams(
      (p) => {
        p.delete('selected');
        return p;
      },
      { replace: true },
    );
  const [, setCreating] = useGlobal<boolean>(CREATING_DASHBOARD_KEY, false);
  const [, setEditing] = useGlobal<string | null>(EDITING_DASHBOARD_KEY, null);
  const [, setName] = useGlobal<string>(NEW_DASH_NAME_KEY, '');
  const [, setDescription] = useGlobal<string>(NEW_DASH_DESC_KEY, '');
  const [, setTemplateIdx] = useGlobal<number>(NEW_DASH_TEMPLATE_KEY, 0);
  const [, setFilePath] = useUserState<string>('files/currentPath', '/');
  // Shared with the file browser's "Create Dashboard here", which needs the same five writes seeded from
  // a folder rather than from nothing.
  const openNewDashboard = useNewDashboardDraft();

  const [search, setSearch] = useState('');
  const [deleting, setDeleting] = useState<DashboardDefinition | null>(null);
  const isDashboardsPage = location.pathname === '/dashboards';
  const filtered = search
    ? dashboards.filter((ws) => {
        const q = search.toLowerCase();
        return [ws.name, ws.id, ws.description ?? '', ws.cwd ?? ''].some((field) => field.toLowerCase().includes(q));
      })
    : dashboards;

  // Keep ?selected= while editing: you are still on this dashboard, just in edit mode. DashboardPreview
  // renders the form over the preview whenever `editing` is set, so there is nothing to clear it for —
  // and on mobile `selected` is what opens the right-hand panel the form lives in (DashboardsScreen),
  // so clearing it opened the form where you could not see it. Cancelling or refreshing now returns to
  // the dashboard you were editing instead of an empty preview.
  const handleEdit = (ev: React.MouseEvent, ws: DashboardDefinition) => {
    ev.stopPropagation();
    setCreating(false);
    setEditing(ws.id);
    setName(ws.name);
    setDescription(ws.description ?? '');
    setTemplateIdx(ws.templateIdx ?? 0);
    const cwdPath = !ws.cwd || ws.cwd === '~' ? '/' : ws.cwd.replace(/^~\//, '/');
    setFilePath(cwdPath);
  };

  const handleDelete = (ev: React.MouseEvent, ws: DashboardDefinition) => {
    ev.stopPropagation();
    setDeleting(ws);
  };

  const confirmDelete = () => {
    if (!deleting) return;
    setDashboards((prev) => prev.filter((w) => w.id !== deleting.id));
    if (selected === deleting.id) clearSelected();

    const layoutKey = `ws-layout-${deleting.id}`;
    const currentState = queryClient.getQueryData<Record<string, unknown>>(['DASHBOARD_STATE']) ?? {};
    const { [layoutKey]: _, ...rest } = currentState;
    queryClient.setQueryData(['DASHBOARD_STATE'], rest);
    persistDashboardState(client, queryClient, { [layoutKey]: null });
    setDeleting(null);
  };

  return (
    <div className="flex flex-col h-full overflow-y-auto">
      <div className="p-3 pb-0 flex flex-col gap-2">
        <Link
          to="/dashboards"
          className="flex items-center gap-2.5 rounded-lg px-3 py-2 text-sm font-medium bg-duck-teal/15 text-duck-teal"
        >
          <LayoutGrid className="h-4 w-4" />
          Dashboards
        </Link>
        <button
          type="button"
          onClick={() => openNewDashboard()}
          className="flex items-center justify-center gap-1 py-2 px-3 rounded-lg text-sm font-medium bg-duck-teal hover:bg-duck-teal/90 text-white transition-all cursor-pointer"
        >
          <Plus className="h-4 w-4 shrink-0" />
          New Dashboard
        </button>
      </div>
      <div className="relative px-3 pt-2">
        <Search className="absolute left-6 top-1/2 h-3.5 w-3.5 text-gray-500 pointer-events-none" />
        <input
          type="text"
          value={search}
          onChange={(ev) => setSearch(ev.target.value)}
          placeholder="Search dashboards"
          className="w-full rounded-lg border border-duck-dark/15 bg-transparent py-1.5 pl-8 pr-3 text-sm text-white placeholder:text-gray-500 focus:outline-none focus:ring-1 focus:ring-duck-teal/30 focus:border-duck-teal/40"
        />
      </div>
      <div className="flex flex-col gap-0.5 px-3 pt-2">
        {filtered.map((ws) => (
          <div
            key={ws.id}
            className={`flex items-center rounded-lg text-sm font-medium group ${
              isDashboardsPage && selected === ws.id
                ? 'bg-duck-teal/10 text-duck-teal'
                : 'text-duck-dark/80 dark:text-white/80 hover:bg-duck-dark/5'
            }`}
          >
            <Link
              to={isDashboardsPage ? `/dashboards?selected=${ws.id}` : `/dashboards/${ws.id}`}
              // Picking a dashboard leaves edit/create mode — otherwise an abandoned edit would follow you
              // onto the next one. Not preventDefault'd, so the link still navigates normally.
              onClick={() => {
                setCreating(false);
                setEditing(null);
              }}
              className="flex flex-1 items-center gap-2.5 py-2 px-3 min-w-0 cursor-pointer"
            >
              <LayoutGrid className="h-4 w-4 shrink-0" />
              <span className="flex-1 text-left truncate">{ws.name}</span>
            </Link>
            {isDashboardsPage && (
              <div className="flex shrink-0 items-center pr-2">
                <button
                  type="button"
                  onClick={(ev) => handleEdit(ev, ws)}
                  className="shrink-0 p-1 rounded text-duck-dark/20 md:opacity-0 md:group-hover:opacity-100 hover:text-duck-teal transition-opacity cursor-pointer"
                >
                  <Pencil className="h-3.5 w-3.5" />
                </button>
                <button
                  type="button"
                  onClick={(ev) => handleDelete(ev, ws)}
                  className="shrink-0 p-1 rounded text-duck-dark/20 md:opacity-0 md:group-hover:opacity-100 hover:text-red-500 transition-opacity cursor-pointer"
                >
                  <Trash2 className="h-3.5 w-3.5" />
                </button>
              </div>
            )}
          </div>
        ))}
        {filtered.length === 0 && (
          <p className="text-xs text-gray-500 px-3 py-4 text-center">{search ? 'No matches' : 'No dashboards yet'}</p>
        )}
      </div>

      <AlertDialog
        open={deleting !== null}
        onOpenChange={(open) => {
          if (!open) setDeleting(null);
        }}
      >
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Delete dashboard</AlertDialogTitle>
            <AlertDialogDescription>
              Are you sure you want to delete <strong>{deleting?.name}</strong>? This action cannot be undone.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>Cancel</AlertDialogCancel>
            <AlertDialogAction onClick={confirmDelete} className="bg-red-600 hover:bg-red-700">
              Delete
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  );
};
