import { useState, useEffect, useCallback, useRef } from "react";
import ResponsiveGridLayout from "react-grid-layout";
import "react-grid-layout/css/styles.css";
import "react-resizable/css/styles.css";
import { supabase } from "@/integrations/supabase/client";
import { useAuth } from "@/contexts/AuthContext";
import { Card } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import {
  Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription,
} from "@/components/ui/dialog";
import { Plus, Lock, Unlock, GripVertical, X, RotateCcw } from "lucide-react";
import { useToast } from "@/hooks/use-toast";
import { useIsMobile } from "@/hooks/use-mobile";
import { CARD_CATALOG, getCardDef } from "./widgets/cardRegistry";
import StatWidget from "./widgets/StatWidget";
import TableWidget from "./widgets/TableWidget";
import ChartWidget from "./widgets/ChartWidget";
import QuickActionsWidget from "./widgets/QuickActionsWidget";
import StatusUpdatesWidget from "./widgets/StatusUpdatesWidget";
import {
  type LayoutItem,
  enrichDashboardLayout,
  generateDashboardLayout,
  normalizeSavedDashboardLayout,
} from "./layoutUtils";

const DEFAULT_CARDS = [
  "stat_pending_arc", "stat_open_violations", "stat_collections", "stat_active_owners", "stat_open_requests",
  "chart_community_health", "chart_recent_activity",
  "table_tasks", "table_projects", "table_reminders",
  "table_stripe", "table_form_inbox",
  "status_updates",
  "quick_actions",
];

function renderWidget(cardId: string) {
  const def = getCardDef(cardId);
  if (!def) return <div className="p-4 text-muted-foreground">Unknown</div>;

  switch (def.type) {
    case "stat":
      return <StatWidget cardId={cardId} />;
    case "chart":
      return <ChartWidget cardId={cardId} />;
    case "table":
      return <TableWidget cardId={cardId} />;
    case "quick_action":
      return <QuickActionsWidget />;
    case "status_updates":
      return <StatusUpdatesWidget />;
    default:
      return null;
  }
}

export function CustomizableDashboard() {
  const { user } = useAuth();
  const { toast } = useToast();
  const isMobile = useIsMobile();
  const [cards, setCards] = useState<string[]>(DEFAULT_CARDS);
  const [layouts, setLayouts] = useState<LayoutItem[]>(() => generateDashboardLayout(DEFAULT_CARDS));
  const [isEditing, setIsEditing] = useState(false);
  const [addDialogOpen, setAddDialogOpen] = useState(false);
  const [loaded, setLoaded] = useState(false);
  const [saving, setSaving] = useState(false);
  const containerRef = useRef<HTMLDivElement>(null);
  const [containerWidth, setContainerWidth] = useState(1200);

  const saveLayoutItem = useCallback(async (newLayouts: LayoutItem[], newCards: string[]) => {
    if (!user?.id) return;
    setSaving(true);
    try {
      await (supabase.from("user_dashboard_layouts" as any) as any).upsert({
        user_id: user.id,
        layout: newLayouts,
        cards: newCards,
        updated_at: new Date().toISOString(),
      }, { onConflict: "user_id" });
    } catch (err) {
      console.error("Failed to save layout:", err);
    } finally {
      setSaving(false);
    }
  }, [user?.id]);

  useEffect(() => {
    if (!loaded) return;

    const el = containerRef.current;
    if (!el) return;

    const updateWidth = () => {
      const nextWidth = Math.floor(el.getBoundingClientRect().width);
      if (nextWidth > 0) {
        setContainerWidth((current) => (current === nextWidth ? current : nextWidth));
      }
    };

    updateWidth();

    const ro = new ResizeObserver(() => {
      window.requestAnimationFrame(updateWidth);
    });

    ro.observe(el);
    window.addEventListener("resize", updateWidth);

    return () => {
      ro.disconnect();
      window.removeEventListener("resize", updateWidth);
    };
  }, [loaded]);

  useEffect(() => {
    if (!user?.id) return;
    const load = async () => {
      const { data } = await supabase
        .from("user_dashboard_layouts" as any)
        .select("layout, cards")
        .eq("user_id", user.id)
        .maybeSingle();

      if (data && (data as any).cards && (data as any).layout) {
        const savedCards = (data as any).cards as string[];
        const savedLayoutItems = (data as any).layout as LayoutItem[];
        const { layout: normalizedLayouts, didUpgradeLegacyLayout } = normalizeSavedDashboardLayout(savedCards, savedLayoutItems);
        setCards(savedCards);
        setLayouts(normalizedLayouts);

        if (didUpgradeLegacyLayout) {
          void saveLayoutItem(normalizedLayouts, savedCards);
        }
      }
      setLoaded(true);
    };
    load();
  }, [user?.id, saveLayoutItem]);

  const handleLayoutChange = useCallback((newLayoutItems: LayoutItem[]) => {
    const enriched = enrichDashboardLayout(newLayoutItems);
    setLayouts(enriched);
    if (isEditing) {
      saveLayoutItem(enriched, cards);
    }
  }, [isEditing, cards, saveLayoutItem]);

  const addCard = (cardId: string) => {
    if (cards.includes(cardId)) return;
    const def = getCardDef(cardId);
    if (!def) return;

    const newCards = [...cards, cardId];
    const maxY = layouts.reduce((max, l) => Math.max(max, l.y + l.h), 0);
    const newLayoutItem: LayoutItem = {
      i: cardId,
      x: 0,
      y: maxY,
      w: def.defaultW,
      h: def.defaultH,
      minW: def.minW,
      minH: def.minH,
    };
    const newLayouts = [...layouts, newLayoutItem];
    setCards(newCards);
    setLayouts(newLayouts);
    saveLayoutItem(newLayouts, newCards);
    setAddDialogOpen(false);
    toast({ title: `Added "${def.title}" card` });
  };

  const removeCard = (cardId: string) => {
    const newCards = cards.filter((c) => c !== cardId);
    const newLayouts = layouts.filter((l) => l.i !== cardId);
    setCards(newCards);
    setLayouts(newLayouts);
    saveLayoutItem(newLayouts, newCards);
    toast({ title: "Card removed" });
  };

  const resetLayoutItem = () => {
    const newCards = [...DEFAULT_CARDS];
    const newLayouts = generateDashboardLayout(DEFAULT_CARDS);
    setCards(newCards);
    setLayouts(newLayouts);
    saveLayoutItem(newLayouts, newCards);
    toast({ title: "Dashboard reset to default" });
  };

  const availableCards = CARD_CATALOG.filter((c) => !cards.includes(c.id));

  if (!loaded) {
    return (
      <div className="flex items-center justify-center py-20">
        <div className="h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent" />
      </div>
    );
  }

  return (
    <div className="w-full min-w-0">
      <div className="mb-4 flex items-center justify-between">
        <div>
          <h1 className="text-xl font-semibold text-foreground">Dashboard</h1>
          <p className="text-xs text-muted-foreground">
            {isEditing ? "Drag cards to reposition, resize from corners" : "Click the lock icon to customize"}
          </p>
        </div>
        <div className="flex items-center gap-2">
          {isEditing && (
            <>
              <Button variant="outline" size="sm" onClick={() => setAddDialogOpen(true)}>
                <Plus className="mr-1.5 h-4 w-4" /> Add Card
              </Button>
              <Button variant="outline" size="sm" onClick={resetLayoutItem}>
                <RotateCcw className="mr-1.5 h-4 w-4" /> Reset
              </Button>
            </>
          )}
          <Button
            variant={isEditing ? "default" : "outline"}
            size="sm"
            onClick={() => setIsEditing(!isEditing)}
          >
            {isEditing ? <Unlock className="mr-1.5 h-4 w-4" /> : <Lock className="mr-1.5 h-4 w-4" />}
            {isEditing ? "Done Editing" : "Customize"}
          </Button>
          {saving && <Badge variant="secondary" className="animate-pulse text-xs">Saving...</Badge>}
        </div>
      </div>

      <div ref={containerRef} className="w-full min-w-0">
        {isMobile ? (
          <div className="space-y-3">
            {cards.map((cardId) => {
              const layoutItem = layouts.find((item) => item.i === cardId);
              const minHeight = ((layoutItem?.h ?? getCardDef(cardId)?.defaultH ?? 3) * 60) + 12;

              return (
                <Card
                  key={cardId}
                  className={`relative w-full overflow-hidden border shadow-sm transition-all group ${isEditing ? "ring-1 ring-primary/20" : ""}`}
                  style={{ minHeight }}
                >
                  {isEditing && (
                    <div className="absolute left-0 right-0 top-0 z-20 flex items-center justify-between border-b bg-muted/80 px-2 py-1 backdrop-blur-sm">
                      <div className="flex items-center gap-1 text-muted-foreground">
                        <GripVertical className="h-4 w-4" />
                        <span className="text-2xs font-medium">{getCardDef(cardId)?.title}</span>
                      </div>
                      <button
                        onClick={(e) => {
                          e.stopPropagation();
                          removeCard(cardId);
                        }}
                        className="rounded p-0.5 text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive"
                      >
                        <X className="h-3.5 w-3.5" />
                      </button>
                    </div>
                  )}
                  <div className={isEditing ? "h-full pt-7" : "h-full"}>
                    {renderWidget(cardId)}
                  </div>
                </Card>
              );
            })}
          </div>
        ) : (
          <ResponsiveGridLayout
            className="dashboard-grid"
            layout={layouts}
            width={containerWidth}
            cols={12}
            rowHeight={60}
            isDraggable={isEditing}
            isResizable={isEditing}
            onLayoutChange={handleLayoutChange}
            draggableHandle=".drag-handle"
            compactType="vertical"
            margin={[12, 12] as any}
          >
            {cards.map((cardId) => (
              <div key={cardId}>
                <Card className={`relative h-full overflow-hidden border shadow-sm transition-all group ${isEditing ? "ring-1 ring-primary/20 hover:ring-primary/40" : ""}`}>
                  {isEditing && (
                    <div className="absolute left-0 right-0 top-0 z-20 flex items-center justify-between border-b bg-muted/80 px-2 py-1 backdrop-blur-sm">
                      <div className="drag-handle flex cursor-grab items-center gap-1 text-muted-foreground active:cursor-grabbing">
                        <GripVertical className="h-4 w-4" />
                        <span className="text-2xs font-medium">{getCardDef(cardId)?.title}</span>
                      </div>
                      <button
                        onClick={(e) => {
                          e.stopPropagation();
                          removeCard(cardId);
                        }}
                        className="rounded p-0.5 text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive"
                      >
                        <X className="h-3.5 w-3.5" />
                      </button>
                    </div>
                  )}
                  <div className={isEditing ? "h-full pt-7" : "h-full"}>
                    {renderWidget(cardId)}
                  </div>
                </Card>
              </div>
            ))}
          </ResponsiveGridLayout>
        )}
      </div>

      <Dialog open={addDialogOpen} onOpenChange={setAddDialogOpen}>
        <DialogContent className="max-w-lg">
          <DialogHeader>
            <DialogTitle>Add Dashboard Card</DialogTitle>
            <DialogDescription>Choose a card to add to your dashboard</DialogDescription>
          </DialogHeader>
          <div className="max-h-[400px] space-y-2 overflow-y-auto">
            {availableCards.length === 0 ? (
              <p className="py-4 text-center text-sm text-muted-foreground">All cards have been added</p>
            ) : (
              availableCards.map((card) => (
                <button
                  key={card.id}
                  className="flex w-full items-center gap-3 rounded-lg border p-3 text-left transition-all hover:border-primary/30 hover:bg-muted/50"
                  onClick={() => addCard(card.id)}
                >
                  <div className="flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-primary/10">
                    <card.icon className="h-4 w-4 text-primary" />
                  </div>
                  <div className="min-w-0">
                    <p className="text-sm font-medium text-foreground">{card.title}</p>
                    <p className="text-xs text-muted-foreground">{card.description}</p>
                  </div>
                  <Badge variant="outline" className="text-2xs shrink-0 capitalize">{card.type.replace("_", " ")}</Badge>
                </button>
              ))
            )}
          </div>
        </DialogContent>
      </Dialog>
    </div>
  );
}
