import { useState, useEffect, useMemo } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Plus, LayoutGrid, List, GripVertical } from 'lucide-react';
import { supabase } from '@/integrations/supabase/client';
import { toast } from 'sonner';
import { handleError } from '@/lib/errorHandler';
import { AddRideCreditDialog } from './AddRideCreditDialog';
import { RideCreditCard } from './RideCreditCard';
import { SortableRideCreditCard } from './SortableRideCreditCard';
import { RideCreditFilters } from './RideCreditFilters';
import { UserRideCredit } from '@/types/database';
import { useRideCreditFilters } from '@/hooks/useRideCreditFilters';
import { useIsMobile } from '@/hooks/use-mobile';
import {
  DndContext,
  DragEndEvent,
  closestCenter,
  PointerSensor,
  useSensor,
  useSensors,
} from '@dnd-kit/core';
import {
  SortableContext,
  verticalListSortingStrategy,
  arrayMove,
} from '@dnd-kit/sortable';

interface RideCreditsManagerProps {
  userId: string;
}

export function RideCreditsManager({ userId }: RideCreditsManagerProps) {
  const [credits, setCredits] = useState<UserRideCredit[]>([]);
  const [loading, setLoading] = useState(true);
  const [viewMode, setViewMode] = useState<'grid' | 'list'>('grid');
  const [sortBy, setSortBy] = useState<'date' | 'count' | 'name' | 'custom'>('custom');
  const [isAddDialogOpen, setIsAddDialogOpen] = useState(false);
  const [isEditMode, setIsEditMode] = useState(false);
  const isMobile = useIsMobile();

  // Use the filter hook
  const {
    filters,
    updateFilter,
    clearFilters,
    filteredCredits,
    activeFilterCount,
  } = useRideCreditFilters(credits);

  const sensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: {
        distance: 8,
      },
    })
  );

  useEffect(() => {
    fetchCredits();
  }, [userId, sortBy]);

  const fetchCredits = async () => {
    try {
      setLoading(true);
      
      // Build main query with enhanced data
      let query = supabase
        .from('user_ride_credits')
        .select(`
          *,
          rides:ride_id (
            id,
            name,
            slug,
            category,
            status,
            coaster_type,
            seating_type,
            intensity_level,
            max_speed_kmh,
            max_height_meters,
            length_meters,
            inversions,
            card_image_url,
            average_rating,
            review_count,
            parks:park_id (
              id,
              name,
              slug,
              park_type,
              locations:location_id (
                country,
                state_province,
                city
              )
            ),
            manufacturer:companies!rides_manufacturer_id_fkey (
              id,
              name
            ),
            designer:companies!rides_designer_id_fkey (
              id,
              name
            )
          )
        `)
        .eq('user_id', userId);
      
      // Apply sorting - default to sort_order when available
      if (sortBy === 'date') {
        query = query.order('first_ride_date', { ascending: false, nullsFirst: false });
      } else if (sortBy === 'count') {
        query = query.order('ride_count', { ascending: false });
      } else if (sortBy === 'name') {
        query = query.order('created_at', { ascending: false });
      } else {
        query = query.order('sort_order', { ascending: true, nullsFirst: false });
      }
      
      const { data, error } = await query;
      if (error) throw error;
      
      let processedData = data || [];
      
      // Sort by name client-side if needed
      if (sortBy === 'name') {
        processedData.sort((a, b) => {
          const nameA = a.rides?.name || '';
          const nameB = b.rides?.name || '';
          return nameA.localeCompare(nameB);
        });
      }
      
      setCredits(processedData as UserRideCredit[]);
    } catch (error: unknown) {
      handleError(error, {
        action: 'Fetch Ride Credits',
        userId,
        metadata: { sortBy }
      });
    } finally {
      setLoading(false);
    }
  };

  const handleCreditAdded = async (newCreditId: string) => {
    try {
      // Fetch just the new credit with all necessary joins
      const { data, error } = await supabase
        .from('user_ride_credits')
        .select(`
          *,
          rides:ride_id (
            id,
            name,
            slug,
            category,
            status,
            coaster_type,
            seating_type,
            intensity_level,
            max_speed_kmh,
            max_height_meters,
            length_meters,
            inversions,
            card_image_url,
            parks:park_id (
              id,
              name,
              slug,
              park_type,
              locations:location_id (
                country,
                state_province,
                city
              )
            ),
            manufacturer:manufacturer_id (
              id,
              name
            ),
            designer:designer_id (
              id,
              name
            )
          )
        `)
        .eq('id', newCreditId)
        .single();

      if (error) throw error;

      // Type assertion for complex joined data
      const newCredit = data as unknown as UserRideCredit;

      // Add to existing array
      setCredits(prev => [...prev, newCredit]);
      setIsAddDialogOpen(false);
    } catch (error: unknown) {
      handleError(error, {
        action: 'Add Ride Credit',
        userId,
        metadata: { creditId: newCreditId }
      });
    }
  };

  const handleCreditUpdated = (creditId: string, updates: Partial<UserRideCredit>) => {
    // Optimistic update - update only the affected credit
    setCredits(prev => prev.map(c => 
      c.id === creditId ? { ...c, ...updates } : c
    ));
  };

  const handleCreditDeleted = async (creditId: string) => {
    // Store for rollback
    const deletedCredit = credits.find(c => c.id === creditId);
    
    // Optimistic removal
    setCredits(prev => prev.filter(c => c.id !== creditId));
    
    try {
      const { error } = await supabase
        .from('user_ride_credits')
        .delete()
        .eq('id', creditId)
        .eq('user_id', userId);

      if (error) throw error;
      
      toast.success('Ride credit removed');
    } catch (error: unknown) {
      handleError(error, {
        action: 'Delete Ride Credit',
        userId,
        metadata: { creditId }
      });
      
      // Rollback on error
      if (deletedCredit) {
        setCredits(prev => [...prev, deletedCredit]);
      }
    }
  };

  const handleReorder = async (creditId: string, newPosition: number) => {
    try {
      const { error } = await supabase.rpc('reorder_ride_credit', {
        p_credit_id: creditId,
        p_new_position: newPosition
      });
      
      if (error) throw error;
      
      // No refetch - optimistic update is already applied
    } catch (error: unknown) {
      handleError(error, {
        action: 'Reorder Ride Credit',
        userId,
        metadata: { creditId, newPosition }
      });
      throw error;
    }
  };

  const handleDragEnd = async (event: DragEndEvent) => {
    const { active, over } = event;
    
    if (!over || active.id === over.id) return;
    
    const oldIndex = credits.findIndex(c => c.id === String(active.id));
    const newIndex = credits.findIndex(c => c.id === String(over.id));
    
    if (oldIndex === -1 || newIndex === -1) return;
    
    // Store old order for rollback
    const oldCredits = credits;
    
    // Optimistic update
    const newCredits = arrayMove(credits, oldIndex, newIndex);
    setCredits(newCredits);
    
    try {
      await handleReorder(String(active.id), newIndex + 1);
      toast.success('Order updated');
    } catch (error: unknown) {
      handleError(error, {
        action: 'Drag Reorder Ride Credit',
        userId,
        metadata: { 
          activeId: String(active.id),
          overId: String(over.id),
          oldIndex,
          newIndex
        }
      });
      // Rollback to old order
      setCredits(oldCredits);
    }
  };

  // Memoize statistics to only recalculate when credits change
  const stats = useMemo(() => ({
    totalRides: credits.reduce((sum, c) => sum + c.ride_count, 0),
    uniqueCredits: credits.length,
    parksVisited: new Set(credits.map(c => c.rides?.parks?.id).filter(Boolean)).size,
    coasters: credits.filter(c => c.rides?.category === 'roller_coaster').length
  }), [credits]);

  // Use filtered credits for display
  const displayCredits = filteredCredits;

  if (loading) {
    return (
      <div className="space-y-4">
        {Array.from({ length: 6 }, (_, i) => (
          <Card key={i} className="animate-pulse">
            <CardContent className="p-6">
              <div className="h-32 bg-muted rounded"></div>
            </CardContent>
          </Card>
        ))}
      </div>
    );
  }

  return (
    <div className="space-y-6">
      {/* Statistics */}
      <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
        <Card>
          <CardContent className="pt-6">
            <div className="text-2xl font-bold">{stats.totalRides}</div>
            <div className="text-sm text-muted-foreground">Total Rides</div>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="pt-6">
            <div className="text-2xl font-bold">{stats.uniqueCredits}</div>
            <div className="text-sm text-muted-foreground">Unique Credits</div>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="pt-6">
            <div className="text-2xl font-bold">{stats.parksVisited}</div>
            <div className="text-sm text-muted-foreground">Parks Visited</div>
          </CardContent>
        </Card>
        <Card>
          <CardContent className="pt-6">
            <div className="text-2xl font-bold">{stats.coasters}</div>
            <div className="text-sm text-muted-foreground">Coasters</div>
          </CardContent>
        </Card>
      </div>

      {/* Main Content Area with Sidebar */}
      <div className="flex gap-6 items-start">
        {/* Left Sidebar - Desktop Only */}
        {!isMobile && (
          <aside className="w-80 flex-shrink-0">
            <div className="sticky top-4">
              <div className="rounded-lg border bg-card">
                <RideCreditFilters
                  filters={filters}
                  onFilterChange={updateFilter}
                  onClearFilters={clearFilters}
                  credits={credits}
                  activeFilterCount={activeFilterCount}
                  resultCount={displayCredits.length}
                  totalCount={credits.length}
                  compact={true}
                />
              </div>
            </div>
          </aside>
        )}

        {/* Right Content Area */}
        <div className="flex-1 min-w-0 space-y-4">
          {/* Mobile Filters - Collapsible Card */}
          {isMobile && (
            <Card>
              <CardContent className="pt-6">
                <RideCreditFilters
                  filters={filters}
                  onFilterChange={updateFilter}
                  onClearFilters={clearFilters}
                  credits={credits}
                  activeFilterCount={activeFilterCount}
                  resultCount={displayCredits.length}
                  totalCount={credits.length}
                  compact={false}
                />
              </CardContent>
            </Card>
          )}

          {/* Controls */}
          <div className="flex flex-wrap gap-4 items-center justify-between">
            <div className="flex gap-2">
              <Button onClick={() => setIsAddDialogOpen(true)}>
                <Plus className="w-4 h-4 mr-2" />
                Add Credit
              </Button>
              
              <Button 
                variant={isEditMode ? 'default' : 'outline'}
                onClick={() => setIsEditMode(!isEditMode)}
              >
                <GripVertical className="w-4 h-4 mr-2" />
                {isEditMode ? 'Done Editing' : 'Edit Order'}
              </Button>
            </div>

            <div className="flex gap-2">
              <Select value={sortBy} onValueChange={(value) => setSortBy(value as typeof sortBy)}>
                <SelectTrigger className="w-[180px]">
                  <SelectValue placeholder="Sort by" />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="custom">Custom Order</SelectItem>
                  <SelectItem value="date">Most Recent</SelectItem>
                  <SelectItem value="count">Most Ridden</SelectItem>
                  <SelectItem value="name">Ride Name</SelectItem>
                </SelectContent>
              </Select>

              <div className="flex border rounded-md">
                <Button
                  variant={viewMode === 'grid' ? 'default' : 'ghost'}
                  size="icon"
                  onClick={() => setViewMode('grid')}
                >
                  <LayoutGrid className="w-4 h-4" />
                </Button>
                <Button
                  variant={viewMode === 'list' ? 'default' : 'ghost'}
                  size="icon"
                  onClick={() => setViewMode('list')}
                >
                  <List className="w-4 h-4" />
                </Button>
              </div>
            </div>
          </div>

          {/* Credits Display */}
          {displayCredits.length === 0 ? (
            <Card>
              <CardContent className="py-12">
                <div className="text-center">
                  {credits.length === 0 ? (
                    <>
                      <h3 className="text-xl font-semibold mb-2">No Ride Credits Yet</h3>
                      <p className="text-muted-foreground mb-4">
                        Start tracking your ride experiences
                      </p>
                      <Button onClick={() => setIsAddDialogOpen(true)}>
                        <Plus className="w-4 h-4 mr-2" />
                        Add Your First Credit
                      </Button>
                    </>
                  ) : (
                    <>
                      <h3 className="text-xl font-semibold mb-2">No Results Found</h3>
                      <p className="text-muted-foreground mb-4">
                        Try adjusting your filters
                      </p>
                      <Button onClick={clearFilters} variant="outline">
                        Clear Filters
                      </Button>
                    </>
                  )}
                </div>
              </CardContent>
            </Card>
          ) : isEditMode ? (
          <DndContext
            sensors={sensors}
            collisionDetection={closestCenter}
            onDragEnd={handleDragEnd}
          >
            <SortableContext
              items={displayCredits.map(c => c.id)}
              strategy={verticalListSortingStrategy}
            >
              <div className={viewMode === 'grid' 
                ? 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4'
                : 'space-y-4'
              }>
                {displayCredits.map((credit, index) => (
                  <SortableRideCreditCard
                    key={credit.id}
                    credit={credit}
                    position={index + 1}
                    maxPosition={displayCredits.length}
                    viewMode={viewMode}
                    onUpdate={handleCreditUpdated}
                    onDelete={() => handleCreditDeleted(credit.id)}
                    onReorder={handleReorder}
                  />
                ))}
              </div>
            </SortableContext>
          </DndContext>
          ) : (
            <div className={viewMode === 'grid' 
              ? 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4'
              : 'space-y-4'
            }>
              {displayCredits.map((credit, index) => (
                <RideCreditCard
                  key={credit.id}
                  credit={credit}
                  position={index + 1}
                  viewMode={viewMode}
                  onUpdate={handleCreditUpdated}
                  onDelete={() => handleCreditDeleted(credit.id)}
                />
              ))}
            </div>
          )}
        </div>
      </div>

      {/* Add Credit Dialog */}
      <AddRideCreditDialog
        userId={userId}
        open={isAddDialogOpen}
        onOpenChange={setIsAddDialogOpen}
        onSuccess={handleCreditAdded}
      />
    </div>
  );
}
