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 { getErrorMessage } 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 {
  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);

  // 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,
            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('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 || []) as any[];
      
      // 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);
    } catch (error) {
      console.error('Error fetching ride credits:', error);
      toast.error(getErrorMessage(error));
    } 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;

      // Add to existing array
      setCredits(prev => [...prev, data as any]);
      setIsAddDialogOpen(false);
    } catch (error) {
      console.error('Error fetching new credit:', error);
      toast.error(getErrorMessage(error));
    }
  };

  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) {
      console.error('Error deleting credit:', error);
      toast.error(getErrorMessage(error));
      
      // 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) {
      console.error('Error reordering credit:', error);
      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) {
      toast.error(getErrorMessage(error));
      // 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>

      {/* Filters */}
      <Card>
        <CardContent className="pt-6">
          <RideCreditFilters
            filters={filters}
            onFilterChange={updateFilter}
            onClearFilters={clearFilters}
            credits={credits}
            activeFilterCount={activeFilterCount}
            resultCount={displayCredits.length}
            totalCount={credits.length}
          />
        </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>
      )}

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