'use client';

import { useEffect, useState, useCallback, useRef, useMemo } from 'react';
import { useParams } from 'next/navigation';
import { useDispatch, useSelector } from 'react-redux';
import { AppDispatch, RootState } from '@/store/store';
import {
  fetchMasterDecks,
  uploadMasterDeck,
  deleteMasterDeck,
  reparseMasterDeck,
  updateMasterDeckLayout,
  deleteMasterDeckLayout,
  bulkDeleteMasterDeckLayouts,
  MasterDeck,
} from '@/store/slices/adminSlice';
import Link from 'next/link';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Textarea } from '@/components/ui/textarea';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import {
  ArrowLeft,
  Upload,
  Layers,
  RefreshCw,
  Trash2,
  ChevronDown,
  ChevronRight,
  FileCode,
  CheckCircle2,
  Clock,
  Loader2,
  XCircle,
  Search,
  CheckSquare,
  Square,
  X,
  Code,
  AlertTriangle,
} from 'lucide-react';
import { toast } from 'sonner';

const STATUS_CONFIG: Record<string, { icon: React.ReactNode; label: string; className: string }> = {
  pending: { icon: <Clock className="w-3.5 h-3.5" />, label: 'Pending', className: 'bg-yellow-100 text-yellow-700' },
  processing: { icon: <Loader2 className="w-3.5 h-3.5 animate-spin" />, label: 'Processing', className: 'bg-blue-100 text-blue-700' },
  completed: { icon: <CheckCircle2 className="w-3.5 h-3.5" />, label: 'Completed', className: 'bg-green-100 text-green-700' },
  failed: { icon: <XCircle className="w-3.5 h-3.5" />, label: 'Failed', className: 'bg-red-100 text-red-700' },
};

function StatusBadge({ status }: { status: string }) {
  const cfg = STATUS_CONFIG[status] || STATUS_CONFIG.pending;
  return (
    <span className={`inline-flex items-center gap-1 text-xs px-2 py-0.5 rounded-full ${cfg.className}`}>
      {cfg.icon}
      {cfg.label}
    </span>
  );
}

export default function MasterDecksPage() {
  const params = useParams();
  const clientId = params.id as string;
  const dispatch = useDispatch<AppDispatch>();
  const { masterDecks } = useSelector((state: RootState) => state.admin);

  const [loading, setLoading] = useState(true);
  const [uploading, setUploading] = useState(false);
  const [expandedDeck, setExpandedDeck] = useState<string | null>(null);
  const [editLayout, setEditLayout] = useState<{ deckId: string; layoutIndex: number; layout: Record<string, unknown> } | null>(null);
  const fileInputRef = useRef<HTMLInputElement>(null);

  const load = useCallback(async () => {
    setLoading(true);
    await dispatch(fetchMasterDecks(clientId));
    setLoading(false);
  }, [dispatch, clientId]);

  useEffect(() => {
    load();
  }, [load]);

  // Poll for status changes on processing decks
  useEffect(() => {
    const hasProcessing = masterDecks.some((d) => d.parse_status === 'pending' || d.parse_status === 'processing');
    if (!hasProcessing) return;

    const interval = setInterval(() => {
      dispatch(fetchMasterDecks(clientId));
    }, 5000);

    return () => clearInterval(interval);
  }, [masterDecks, dispatch, clientId]);

  const handleUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;

    setUploading(true);
    try {
      await dispatch(uploadMasterDeck({ clientId, file })).unwrap();
      toast.success('Master deck uploaded — parsing started');
    } catch (err) {
      toast.error(typeof err === 'string' ? err : 'Upload failed');
    } finally {
      setUploading(false);
      if (fileInputRef.current) fileInputRef.current.value = '';
    }
  };

  const handleReparse = async (deckId: string, parseMode?: string) => {
    try {
      await dispatch(reparseMasterDeck({ deckId, parseMode })).unwrap();
      toast.success('Reparse triggered');
      dispatch(fetchMasterDecks(clientId));
    } catch (err) {
      toast.error(typeof err === 'string' ? err : 'Reparse failed');
    }
  };

  const handleDelete = async (deckId: string) => {
    try {
      await dispatch(deleteMasterDeck(deckId)).unwrap();
      toast.success('Master deck removed');
    } catch {
      toast.error('Failed to remove deck');
    }
  };

  const handleSaveLayout = async () => {
    if (!editLayout) return;
    try {
      await dispatch(
        updateMasterDeckLayout({
          deckId: editLayout.deckId,
          layoutIndex: editLayout.layoutIndex,
          data: {
            layout_name: editLayout.layout.layout_name as string,
            layout_type: editLayout.layout.layout_type as string,
            react_code: editLayout.layout.react_code as string,
          },
        })
      ).unwrap();
      toast.success('Layout updated');
      setEditLayout(null);
      dispatch(fetchMasterDecks(clientId));
    } catch {
      toast.error('Failed to update layout');
    }
  };

  const handleDeleteLayout = async (deckId: string, layoutIndex: number) => {
    try {
      await dispatch(deleteMasterDeckLayout({ deckId, layoutIndex })).unwrap();
      toast.success('Layout deleted');
      dispatch(fetchMasterDecks(clientId));
    } catch {
      toast.error('Failed to delete layout');
    }
  };

  const handleBulkDeleteLayouts = async (deckId: string, indices: number[]) => {
    if (indices.length === 0) return;
    try {
      await dispatch(bulkDeleteMasterDeckLayouts({ deckId, indices })).unwrap();
      toast.success(`${indices.length} layout(s) deleted`);
      dispatch(fetchMasterDecks(clientId));
    } catch {
      toast.error('Failed to delete layouts');
    }
  };

  if (loading) {
    return (
      <div className="space-y-4">
        <div className="h-8 w-64 bg-gray-200 rounded animate-pulse" />
        <div className="h-48 bg-gray-200 rounded animate-pulse" />
      </div>
    );
  }

  return (
    <div className="space-y-6 max-w-5xl">
      <div className="flex items-center justify-between">
        <div className="flex items-center gap-3">
          <Link href={`/admin/clients/${clientId}`}>
            <Button variant="ghost" size="sm">
              <ArrowLeft className="w-4 h-4 mr-1" />Back
            </Button>
          </Link>
          <h1 className="text-2xl font-semibold">Master Decks</h1>
        </div>
        <div>
          <label className="inline-flex items-center gap-2 px-4 py-2 bg-[#5146E5] text-white rounded-lg cursor-pointer hover:bg-[#5146E5]/90 text-sm font-medium">
            {uploading ? <Loader2 className="w-4 h-4 animate-spin" /> : <Upload className="w-4 h-4" />}
            {uploading ? 'Uploading...' : 'Upload PPTX'}
            <input
              ref={fileInputRef}
              type="file"
              accept=".pptx,application/vnd.openxmlformats-officedocument.presentationml.presentation"
              onChange={handleUpload}
              disabled={uploading}
              className="hidden"
            />
          </label>
        </div>
      </div>

      {masterDecks.length === 0 ? (
        <div className="flex flex-col items-center justify-center h-48 border-2 border-dashed border-gray-300 rounded-lg">
          <Layers className="w-10 h-10 text-gray-400 mb-2" />
          <p className="text-gray-500">No master decks uploaded yet.</p>
          <p className="text-sm text-gray-400 mt-1">Upload a PPTX file to get started.</p>
        </div>
      ) : (
        <div className="space-y-3">
          {masterDecks.map((deck) => (
            <DeckCard
              key={deck.id}
              deck={deck}
              expanded={expandedDeck === deck.id}
              onToggle={() => setExpandedDeck(expandedDeck === deck.id ? null : deck.id)}
              onReparse={(parseMode?: string) => handleReparse(deck.id, parseMode)}
              onDelete={() => handleDelete(deck.id)}
              onEditLayout={(idx, layout) => setEditLayout({ deckId: deck.id, layoutIndex: idx, layout: { ...layout } })}
              onDeleteLayout={(idx) => handleDeleteLayout(deck.id, idx)}
              onBulkDeleteLayouts={(indices) => handleBulkDeleteLayouts(deck.id, indices)}
            />
          ))}
        </div>
      )}

      {/* Layout Edit Dialog */}
      <Dialog open={!!editLayout} onOpenChange={(open) => !open && setEditLayout(null)}>
        <DialogContent className="max-w-2xl max-h-[80vh] overflow-y-auto">
          <DialogHeader>
            <DialogTitle>Edit Layout</DialogTitle>
          </DialogHeader>
          {editLayout && (
            <div className="space-y-4">
              <div className="space-y-1">
                <Label>Layout Name</Label>
                <Input
                  value={(editLayout.layout.layout_name as string) || ''}
                  onChange={(e) =>
                    setEditLayout({ ...editLayout, layout: { ...editLayout.layout, layout_name: e.target.value } })
                  }
                />
              </div>
              <div className="space-y-1">
                <Label>Layout Type</Label>
                <Input
                  value={(editLayout.layout.layout_type as string) || ''}
                  onChange={(e) =>
                    setEditLayout({ ...editLayout, layout: { ...editLayout.layout, layout_type: e.target.value } })
                  }
                  placeholder="e.g. title_slide, content, two_column"
                />
              </div>
              <div className="space-y-1">
                <Label>React Code</Label>
                <Textarea
                  value={(editLayout.layout.react_code as string) || ''}
                  onChange={(e) =>
                    setEditLayout({ ...editLayout, layout: { ...editLayout.layout, react_code: e.target.value } })
                  }
                  rows={12}
                  className="font-mono text-sm"
                  placeholder="TSX code for the layout component..."
                />
              </div>
              <div className="flex justify-end gap-2">
                <Button variant="outline" onClick={() => setEditLayout(null)}>
                  Cancel
                </Button>
                <Button onClick={handleSaveLayout}>Save Changes</Button>
              </div>
            </div>
          )}
        </DialogContent>
      </Dialog>
    </div>
  );
}

function DeckCard({
  deck,
  expanded,
  onToggle,
  onReparse,
  onDelete,
  onEditLayout,
  onDeleteLayout,
  onBulkDeleteLayouts,
}: {
  deck: MasterDeck;
  expanded: boolean;
  onToggle: () => void;
  onReparse: (parseMode?: string) => void;
  onDelete: () => void;
  onEditLayout: (idx: number, layout: Record<string, unknown>) => void;
  onDeleteLayout: (idx: number) => void;
  onBulkDeleteLayouts: (indices: number[]) => void;
}) {
  const layouts = (deck.layouts || []) as Array<Record<string, unknown>>;
  const [searchQuery, setSearchQuery] = useState('');
  const [typeFilter, setTypeFilter] = useState('all');
  const [codeFilter, setCodeFilter] = useState<'all' | 'has_code' | 'no_code'>('all');
  const [selectedIndices, setSelectedIndices] = useState<Set<number>>(new Set());
  const [selectMode, setSelectMode] = useState(false);
  const [confirmDelete, setConfirmDelete] = useState<number | null>(null);
  const [confirmBulkDelete, setConfirmBulkDelete] = useState(false);

  // Extract unique layout types
  const layoutTypes = useMemo(() => {
    const types = new Set<string>();
    layouts.forEach((l) => {
      const t = (l.layout_type as string) || 'custom';
      types.add(t);
    });
    return Array.from(types).sort();
  }, [layouts]);

  // Filter layouts
  const filteredLayouts = useMemo(() => {
    return layouts.map((layout, idx) => ({ layout, originalIndex: idx })).filter(({ layout }) => {
      const name = ((layout.layout_name as string) || '').toLowerCase();
      const type = ((layout.layout_type as string) || 'custom').toLowerCase();
      const hasCode = !!(layout.react_code as string);

      if (searchQuery && !name.includes(searchQuery.toLowerCase())) return false;
      if (typeFilter !== 'all' && type !== typeFilter.toLowerCase()) return false;
      if (codeFilter === 'has_code' && !hasCode) return false;
      if (codeFilter === 'no_code' && hasCode) return false;
      return true;
    });
  }, [layouts, searchQuery, typeFilter, codeFilter]);

  const toggleSelect = (idx: number) => {
    const next = new Set(selectedIndices);
    if (next.has(idx)) next.delete(idx);
    else next.add(idx);
    setSelectedIndices(next);
  };

  const selectAll = () => {
    const allVisible = new Set(filteredLayouts.map((f) => f.originalIndex));
    setSelectedIndices(allVisible);
  };

  const deselectAll = () => {
    setSelectedIndices(new Set());
  };

  const exitSelectMode = () => {
    setSelectMode(false);
    setSelectedIndices(new Set());
  };

  const handleBulkDelete = () => {
    if (selectedIndices.size === 0) return;
    setConfirmBulkDelete(true);
  };

  const confirmAndBulkDelete = () => {
    const indices = Array.from(selectedIndices).sort((a, b) => b - a);
    onBulkDeleteLayouts(indices);
    exitSelectMode();
    setConfirmBulkDelete(false);
  };

  const handleSingleDelete = (idx: number) => {
    setConfirmDelete(idx);
  };

  const confirmAndDelete = () => {
    if (confirmDelete !== null) {
      onDeleteLayout(confirmDelete);
      setConfirmDelete(null);
    }
  };

  const isFiltering = searchQuery || typeFilter !== 'all' || codeFilter !== 'all';

  return (
    <div className="bg-white rounded-lg border">
      <div className="flex items-center justify-between p-4">
        <div className="flex items-center gap-3 flex-1 min-w-0">
          <button onClick={onToggle} className="text-gray-400 hover:text-gray-600">
            {expanded ? <ChevronDown className="w-5 h-5" /> : <ChevronRight className="w-5 h-5" />}
          </button>
          {deck.thumbnail_path ? (
            <img
              src={`/api/v1/admin/master-decks/${deck.id}/screenshot/${deck.thumbnail_path.split('/').pop()}`}
              alt={deck.name}
              className="w-16 h-10 object-cover rounded border flex-shrink-0 bg-white"
              onError={(e) => {
                (e.target as HTMLImageElement).style.display = 'none';
                (e.target as HTMLImageElement).nextElementSibling?.classList.remove('hidden');
              }}
            />
          ) : null}
          <Layers className={`w-5 h-5 text-[#5146E5] flex-shrink-0 ${deck.thumbnail_path ? 'hidden' : ''}`} />
          <div className="min-w-0">
            <p className="font-medium truncate">{deck.name}</p>
            <p className="text-xs text-gray-500">
              {deck.created_at ? new Date(deck.created_at).toLocaleDateString() : ''}
              {layouts.length > 0 && ` · ${layouts.length} layouts`}
              {` · mode: ${deck.parse_mode || 'slides'}`}
            </p>
          </div>
        </div>
        <div className="flex items-center gap-2">
          <StatusBadge status={deck.parse_status} />
          <Select
            defaultValue=""
            onValueChange={(v) => {
              if (v === 'slides' || v === 'layouts') onReparse(v);
            }}
            disabled={deck.parse_status === 'processing'}
          >
            <SelectTrigger className="w-auto h-8 px-2 border-none shadow-none hover:bg-gray-100" title="Reparse">
              <RefreshCw className="w-4 h-4" />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="slides">Reparse (slides mode)</SelectItem>
              <SelectItem value="layouts">Reparse (layouts mode)</SelectItem>
            </SelectContent>
          </Select>
          <Button variant="ghost" size="sm" onClick={onDelete} title="Remove">
            <Trash2 className="w-4 h-4 text-red-500" />
          </Button>
        </div>
      </div>

      {expanded && (
        <div className="border-t px-4 pb-4 pt-3">
          {deck.parse_status === 'failed' && (
            <p className="text-sm text-red-600 mb-3">
              Parsing failed. Check server logs or try reparsing.
            </p>
          )}

          {deck.parse_status === 'processing' && (
            <div className="flex items-center gap-2 text-sm text-blue-600 mb-3">
              <Loader2 className="w-4 h-4 animate-spin" />
              Parsing in progress... This may take a few minutes.
            </div>
          )}

          {deck.parse_status === 'pending' && (
            <p className="text-sm text-yellow-600 mb-3">
              Queued for parsing...
            </p>
          )}

          {layouts.length === 0 && deck.parse_status === 'completed' && (
            <p className="text-sm text-gray-500">No layouts extracted.</p>
          )}

          {layouts.length > 0 && (
            <>
              {/* Toolbar: Search + Filters + Select Mode */}
              <div className="flex flex-wrap items-center gap-2 mb-3">
                <div className="relative flex-1 min-w-[180px] max-w-xs">
                  <Search className="absolute left-2.5 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-gray-400" />
                  <Input
                    value={searchQuery}
                    onChange={(e) => setSearchQuery(e.target.value)}
                    placeholder="Search layouts..."
                    className="pl-8 h-8 text-sm"
                  />
                </div>

                <Select value={typeFilter} onValueChange={setTypeFilter}>
                  <SelectTrigger className="w-[140px] h-8 text-sm">
                    <SelectValue placeholder="Type" />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value="all">All types</SelectItem>
                    {layoutTypes.map((t) => (
                      <SelectItem key={t} value={t}>{t}</SelectItem>
                    ))}
                  </SelectContent>
                </Select>

                <Select value={codeFilter} onValueChange={(v) => setCodeFilter(v as typeof codeFilter)}>
                  <SelectTrigger className="w-[140px] h-8 text-sm">
                    <SelectValue placeholder="Code" />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value="all">All</SelectItem>
                    <SelectItem value="has_code">Has code</SelectItem>
                    <SelectItem value="no_code">Missing code</SelectItem>
                  </SelectContent>
                </Select>

                <div className="flex items-center gap-1 ml-auto">
                  {selectMode ? (
                    <>
                      <Button variant="ghost" size="sm" onClick={selectAll} className="h-8 text-xs">
                        Select all
                      </Button>
                      <Button variant="ghost" size="sm" onClick={deselectAll} className="h-8 text-xs">
                        Deselect
                      </Button>
                      {selectedIndices.size > 0 && (
                        <Button
                          variant="destructive"
                          size="sm"
                          onClick={handleBulkDelete}
                          className="h-8 text-xs"
                        >
                          <Trash2 className="w-3.5 h-3.5 mr-1" />
                          Delete {selectedIndices.size}
                        </Button>
                      )}
                      <Button variant="ghost" size="sm" onClick={exitSelectMode} className="h-8 text-xs">
                        <X className="w-3.5 h-3.5" />
                      </Button>
                    </>
                  ) : (
                    <Button variant="outline" size="sm" onClick={() => setSelectMode(true)} className="h-8 text-xs">
                      <CheckSquare className="w-3.5 h-3.5 mr-1" />
                      Select
                    </Button>
                  )}
                </div>
              </div>

              {/* Filter stats */}
              <div className="text-xs text-gray-400 mb-2">
                {isFiltering
                  ? `${filteredLayouts.length} of ${layouts.length} layouts`
                  : `${layouts.length} layouts`
                }
                {selectedIndices.size > 0 && ` · ${selectedIndices.size} selected`}
              </div>

              {/* Layout grid */}
              {filteredLayouts.length === 0 ? (
                <p className="text-sm text-gray-400 text-center py-6">No layouts match your filters.</p>
              ) : (
                <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-3">
                  {filteredLayouts.map(({ layout, originalIndex }) => {
                    const screenshotPath = layout.screenshot_path as string | undefined;
                    const screenshotFilename = screenshotPath ? screenshotPath.split('/').pop() : null;
                    const hasCode = !!(layout.react_code as string);
                    const isSelected = selectedIndices.has(originalIndex);

                    return (
                      <div
                        key={originalIndex}
                        className={`relative text-left bg-gray-50 rounded-lg border p-2 transition-colors group overflow-hidden ${
                          isSelected
                            ? 'border-[#5146E5] bg-[#5146E5]/5 ring-1 ring-[#5146E5]'
                            : 'hover:border-[#5146E5] hover:bg-[#5146E5]/5'
                        }`}
                      >
                        {/* Select checkbox */}
                        {selectMode && (
                          <button
                            onClick={() => toggleSelect(originalIndex)}
                            className="absolute top-2 left-2 z-10 bg-white rounded shadow-sm"
                          >
                            {isSelected ? (
                              <CheckSquare className="w-5 h-5 text-[#5146E5]" />
                            ) : (
                              <Square className="w-5 h-5 text-gray-300 hover:text-gray-500" />
                            )}
                          </button>
                        )}

                        {/* Delete button */}
                        {!selectMode && (
                          <button
                            onClick={(e) => {
                              e.stopPropagation();
                              handleSingleDelete(originalIndex);
                            }}
                            className="absolute top-2 right-2 z-10 p-1 bg-white rounded shadow-sm opacity-0 group-hover:opacity-100 transition-opacity hover:bg-red-50"
                            title="Delete layout"
                          >
                            <Trash2 className="w-3.5 h-3.5 text-red-500" />
                          </button>
                        )}

                        {/* Clickable area for editing */}
                        <button
                          onClick={() => {
                            if (selectMode) {
                              toggleSelect(originalIndex);
                            } else {
                              onEditLayout(originalIndex, layout);
                            }
                          }}
                          className="w-full text-left"
                        >
                          {screenshotFilename ? (
                            <img
                              src={`/api/v1/admin/master-decks/${deck.id}/screenshot/${screenshotFilename}`}
                              alt={(layout.layout_name as string) || `Layout ${originalIndex + 1}`}
                              className="w-full h-24 object-cover rounded mb-2 bg-white"
                              loading="lazy"
                            />
                          ) : (
                            <div className="w-full h-24 flex items-center justify-center bg-gray-100 rounded mb-2">
                              <FileCode className="w-8 h-8 text-gray-300" />
                            </div>
                          )}
                          <div className="px-1">
                            <p className="text-xs font-medium truncate">
                              {(layout.layout_name as string) || `Layout ${originalIndex + 1}`}
                            </p>
                            <div className="flex items-center gap-1 mt-1">
                              <span className="text-[10px] text-gray-400 px-1.5 py-0.5 bg-gray-200 rounded">
                                {(layout.layout_type as string) || 'custom'}
                              </span>
                              {hasCode ? (
                                <span className="text-[10px] text-green-600 px-1.5 py-0.5 bg-green-50 rounded flex items-center gap-0.5">
                                  <Code className="w-2.5 h-2.5" /> TSX
                                </span>
                              ) : (
                                <span className="text-[10px] text-orange-600 px-1.5 py-0.5 bg-orange-50 rounded flex items-center gap-0.5">
                                  <AlertTriangle className="w-2.5 h-2.5" /> No code
                                </span>
                              )}
                            </div>
                          </div>
                        </button>
                      </div>
                    );
                  })}
                </div>
              )}
            </>
          )}
        </div>
      )}

      {/* Single delete confirmation */}
      <Dialog open={confirmDelete !== null} onOpenChange={(open) => !open && setConfirmDelete(null)}>
        <DialogContent className="max-w-sm">
          <DialogHeader>
            <DialogTitle>Delete Layout</DialogTitle>
          </DialogHeader>
          <p className="text-sm text-gray-600">
            Are you sure you want to delete this layout? This action cannot be undone.
          </p>
          <div className="flex justify-end gap-2 mt-4">
            <Button variant="outline" size="sm" onClick={() => setConfirmDelete(null)}>Cancel</Button>
            <Button variant="destructive" size="sm" onClick={confirmAndDelete}>Delete</Button>
          </div>
        </DialogContent>
      </Dialog>

      {/* Bulk delete confirmation */}
      <Dialog open={confirmBulkDelete} onOpenChange={setConfirmBulkDelete}>
        <DialogContent className="max-w-sm">
          <DialogHeader>
            <DialogTitle>Delete {selectedIndices.size} Layouts</DialogTitle>
          </DialogHeader>
          <p className="text-sm text-gray-600">
            Are you sure you want to delete {selectedIndices.size} selected layout(s)? This action cannot be undone.
          </p>
          <div className="flex justify-end gap-2 mt-4">
            <Button variant="outline" size="sm" onClick={() => setConfirmBulkDelete(false)}>Cancel</Button>
            <Button variant="destructive" size="sm" onClick={confirmAndBulkDelete}>Delete All</Button>
          </div>
        </DialogContent>
      </Dialog>
    </div>
  );
}
