import { useState, useMemo } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import toast from 'react-hot-toast';
import { api } from '@/lib/api';
import {
  Plus,
  Search,
  X,
  Filter,
  RefreshCw,
  Plane,
  AlertTriangle,
  Clock,
  ChevronDown,
  ChevronRight,
  Link2,
} from 'lucide-react';
import { FlightForm, FlightFormData } from '@/components/FlightForm';
import { FlightCard } from '@/components/FlightCard';
import { TableSkeleton } from '@/components/Skeleton';
import { ErrorMessage } from '@/components/ErrorMessage';
import { FilterModal } from '@/components/FilterModal';
import { FilterChip } from '@/components/FilterChip';
import { useDebounce } from '@/hooks/useDebounce';
import { useFlights, useFlightBudget, useRefreshActiveFlights } from '@/hooks/useFlights';
import { Flight, Journey } from '@/types';
import { groupFlightsIntoJourneys } from '@/lib/journeyUtils';

type JourneyGroup = {
  key: string;
  label: string;
  icon: typeof AlertTriangle;
  journeys: Journey[];
  color: string;
  defaultCollapsed?: boolean;
};

function getJourneyEta(j: Journey): string {
  // Use the current/last segment's best available arrival time
  const seg = j.flights[j.currentSegmentIndex] || j.flights[j.flights.length - 1];
  return seg.estimatedArrival || seg.scheduledArrival || '';
}

function getJourneyDeparture(j: Journey): string {
  // Use the first non-landed segment's departure, or first segment
  for (const f of j.flights) {
    if (f.status?.toLowerCase() !== 'landed' && !f.actualArrival) {
      return f.estimatedDeparture || f.scheduledDeparture || '';
    }
  }
  return j.flights[0]?.scheduledDeparture || j.flights[0]?.flightDate || '';
}

function getJourneyMaxDelay(j: Journey): number {
  return Math.max(...j.flights.map(f => Math.max(f.arrivalDelay || 0, f.departureDelay || 0)));
}

function groupJourneys(journeys: Journey[]): JourneyGroup[] {
  const now = new Date();
  const twoHoursFromNow = new Date(now.getTime() + 2 * 60 * 60 * 1000);
  const fourHoursFromNow = new Date(now.getTime() + 4 * 60 * 60 * 1000);

  const groups: JourneyGroup[] = [
    { key: 'alerts', label: 'Alerts', icon: AlertTriangle, journeys: [], color: 'text-red-500' },
    { key: 'connection-risk', label: 'Connection Risk', icon: Link2, journeys: [], color: 'text-orange-500' },
    { key: 'arriving', label: 'Arriving Soon', icon: Plane, journeys: [], color: 'text-purple-500' },
    { key: 'active', label: 'In Flight', icon: Plane, journeys: [], color: 'text-purple-500' },
    { key: 'departing', label: 'Departing Soon', icon: Clock, journeys: [], color: 'text-blue-500' },
    { key: 'scheduled', label: 'Scheduled', icon: Clock, journeys: [], color: 'text-muted-foreground' },
    { key: 'completed', label: 'Completed', icon: Plane, journeys: [], color: 'text-emerald-500', defaultCollapsed: true },
  ];

  for (const journey of journeys) {
    const status = journey.effectiveStatus;

    // Connection risk: any journey with layover risk (separate from alerts)
    if (journey.hasLayoverRisk) {
      groups[1].journeys.push(journey);
      // Also place in the appropriate status group below (don't continue)
    }

    // Alerts: cancelled, diverted, incident
    if (status === 'cancelled' || status === 'diverted' || status === 'incident') {
      groups[0].journeys.push(journey);
      continue;
    }

    // Completed: all segments landed
    if (status === 'landed') {
      groups[6].journeys.push(journey);
      continue;
    }

    const eta = getJourneyEta(journey);
    const departure = getJourneyDeparture(journey);

    // Arriving soon: active journey with final arrival within 2h
    if (status === 'active' && eta && new Date(eta) <= twoHoursFromNow) {
      groups[2].journeys.push(journey);
      continue;
    }

    // In flight: active
    if (status === 'active') {
      groups[3].journeys.push(journey);
      continue;
    }

    // Departing soon: next departure within 4h
    if (departure && new Date(departure) <= fourHoursFromNow && new Date(departure) >= now) {
      groups[4].journeys.push(journey);
      continue;
    }

    // Everything else is scheduled
    groups[5].journeys.push(journey);
  }

  // Sort within groups
  groups[0].journeys.sort((a, b) => getJourneyMaxDelay(b) - getJourneyMaxDelay(a));
  groups[1].journeys.sort((a, b) => {
    // Worst risk first: missed > critical > warning
    const riskOrder = { missed: 0, critical: 1, warning: 2, ok: 3, none: 4 };
    const worstA = Math.min(...a.layovers.map(l => riskOrder[l.risk] ?? 4));
    const worstB = Math.min(...b.layovers.map(l => riskOrder[l.risk] ?? 4));
    return worstA - worstB;
  });
  groups[2].journeys.sort((a, b) => getJourneyEta(a).localeCompare(getJourneyEta(b)));
  groups[3].journeys.sort((a, b) => getJourneyEta(a).localeCompare(getJourneyEta(b)));
  groups[4].journeys.sort((a, b) => getJourneyDeparture(a).localeCompare(getJourneyDeparture(b)));
  groups[5].journeys.sort((a, b) => getJourneyDeparture(a).localeCompare(getJourneyDeparture(b)));
  groups[6].journeys.sort((a, b) => {
    const lastA = a.flights[a.flights.length - 1];
    const lastB = b.flights[b.flights.length - 1];
    const arrA = lastA.actualArrival || lastA.scheduledArrival || '';
    const arrB = lastB.actualArrival || lastB.scheduledArrival || '';
    return arrB.localeCompare(arrA); // Most recent first
  });

  return groups;
}

function BudgetIndicator() {
  const { data: budget } = useFlightBudget();
  if (!budget) return null;

  const percent = Math.round((budget.used / budget.limit) * 100);
  const barColor = percent > 80 ? 'bg-red-500' : percent > 50 ? 'bg-amber-500' : 'bg-emerald-500';
  const textColor = percent > 80 ? 'text-red-600 dark:text-red-400' : 'text-muted-foreground';

  return (
    <div className="flex items-center gap-3 px-3 py-2 bg-muted/50 rounded-lg border border-border">
      <div className="text-xs">
        <span className={`font-medium ${textColor}`}>{budget.remaining}</span>
        <span className="text-muted-foreground">/{budget.limit} API calls</span>
      </div>
      <div className="w-20 h-2 bg-muted rounded-full overflow-hidden">
        <div
          className={`h-full ${barColor} rounded-full transition-all`}
          style={{ width: `${percent}%` }}
        />
      </div>
    </div>
  );
}

export function FlightList() {
  const queryClient = useQueryClient();
  const [showForm, setShowForm] = useState(false);
  const [editingFlight, setEditingFlight] = useState<Flight | null>(null);
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [collapsedGroups, setCollapsedGroups] = useState<Set<string>>(new Set(['completed']));

  // Search and filter state
  const [searchTerm, setSearchTerm] = useState('');
  const [selectedStatuses, setSelectedStatuses] = useState<string[]>([]);
  const [filterModalOpen, setFilterModalOpen] = useState(false);

  const debouncedSearchTerm = useDebounce(searchTerm, 300);

  const { data: flights, isLoading, isError, error, refetch } = useFlights();
  const refreshActiveMutation = useRefreshActiveFlights();

  const createMutation = useMutation({
    mutationFn: async (data: FlightFormData) => {
      await api.post('/flights', data);
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['flights'] });
      setShowForm(false);
      setIsSubmitting(false);
      toast.success('Flight created successfully');
    },
    onError: (error: any) => {
      setIsSubmitting(false);
      toast.error(error.response?.data?.message || 'Failed to create flight');
    },
  });

  const updateMutation = useMutation({
    mutationFn: async ({ id, data }: { id: string; data: FlightFormData }) => {
      await api.patch(`/flights/${id}`, data);
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['flights'] });
      setShowForm(false);
      setEditingFlight(null);
      setIsSubmitting(false);
      toast.success('Flight updated successfully');
    },
    onError: (error: any) => {
      setIsSubmitting(false);
      toast.error(error.response?.data?.message || 'Failed to update flight');
    },
  });

  const deleteMutation = useMutation({
    mutationFn: async (id: string) => {
      await api.delete(`/flights/${id}`);
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['flights'] });
      toast.success('Flight deleted successfully');
    },
    onError: (error: any) => {
      toast.error(error.response?.data?.message || 'Failed to delete flight');
    },
  });

  // Filter flights, then group into journeys
  const filteredFlights = useMemo(() => {
    if (!flights) return [];

    return flights.filter((flight) => {
      const matchesSearch = debouncedSearchTerm === '' ||
        flight.flightNumber.toLowerCase().includes(debouncedSearchTerm.toLowerCase()) ||
        flight.vip?.name?.toLowerCase().includes(debouncedSearchTerm.toLowerCase()) ||
        flight.departureAirport.toLowerCase().includes(debouncedSearchTerm.toLowerCase()) ||
        flight.arrivalAirport.toLowerCase().includes(debouncedSearchTerm.toLowerCase()) ||
        flight.airlineName?.toLowerCase().includes(debouncedSearchTerm.toLowerCase());

      const matchesStatus = selectedStatuses.length === 0 ||
        (flight.status && selectedStatuses.includes(flight.status.toLowerCase()));

      return matchesSearch && matchesStatus;
    });
  }, [flights, debouncedSearchTerm, selectedStatuses]);

  // Group filtered flights into journeys - if any segment of a journey matches search,
  // we include the full journey (all segments for that VIP)
  const journeys = useMemo(() => {
    if (!flights || filteredFlights.length === 0) return [];

    // Get VIP IDs that have at least one matching flight
    const matchingVipIds = new Set(filteredFlights.map(f => f.vipId));

    // Build journeys from ALL flights for matching VIPs (so we don't lose segments)
    const allMatchingFlights = flights.filter(f => matchingVipIds.has(f.vipId));
    return groupFlightsIntoJourneys(allMatchingFlights);
  }, [flights, filteredFlights]);

  const journeyGroups = useMemo(() => groupJourneys(journeys), [journeys]);

  const toggleGroup = (key: string) => {
    setCollapsedGroups(prev => {
      const next = new Set(prev);
      if (next.has(key)) {
        next.delete(key);
      } else {
        next.add(key);
      }
      return next;
    });
  };

  const handleStatusToggle = (status: string) => {
    setSelectedStatuses((prev) =>
      prev.includes(status) ? prev.filter((s) => s !== status) : [...prev, status]
    );
  };

  const handleClearFilters = () => {
    setSearchTerm('');
    setSelectedStatuses([]);
  };

  const handleRemoveStatusFilter = (status: string) => {
    setSelectedStatuses((prev) => prev.filter((s) => s !== status));
  };

  const getFilterLabel = (value: string) => {
    const labels: Record<string, string> = {
      'scheduled': 'Scheduled',
      'active': 'Active / In Flight',
      'landed': 'Landed',
      'cancelled': 'Cancelled',
      'diverted': 'Diverted',
      'incident': 'Incident',
    };
    return labels[value] || value;
  };

  const handleAdd = () => {
    setEditingFlight(null);
    setShowForm(true);
  };

  const handleEdit = (flight: Flight) => {
    setEditingFlight(flight);
    setShowForm(true);
  };

  const handleDelete = (flight: Flight) => {
    if (confirm(`Delete flight ${flight.flightNumber}? This action cannot be undone.`)) {
      deleteMutation.mutate(flight.id);
    }
  };

  const handleSubmit = (data: FlightFormData) => {
    setIsSubmitting(true);
    if (editingFlight) {
      updateMutation.mutate({ id: editingFlight.id, data });
    } else {
      createMutation.mutate(data);
    }
  };

  const handleCancel = () => {
    setShowForm(false);
    setEditingFlight(null);
    setIsSubmitting(false);
  };

  // Stats based on all journeys (not just filtered)
  const allJourneys = useMemo(() => {
    if (!flights) return [];
    return groupFlightsIntoJourneys(flights);
  }, [flights]);

  const stats = useMemo(() => {
    if (!allJourneys.length) return { active: 0, delayed: 0, connectionRisk: 0, landed: 0, total: 0 };
    return {
      active: allJourneys.filter(j => j.effectiveStatus === 'active').length,
      delayed: allJourneys.filter(j => j.flights.some(f => (f.arrivalDelay || f.departureDelay || 0) > 15)).length,
      connectionRisk: allJourneys.filter(j => j.hasLayoverRisk).length,
      landed: allJourneys.filter(j => j.effectiveStatus === 'landed').length,
      total: allJourneys.length,
    };
  }, [allJourneys]);

  if (isLoading) {
    return (
      <div>
        <div className="flex justify-between items-center mb-6">
          <h1 className="text-3xl font-bold text-foreground">Flight Tracking</h1>
        </div>
        <TableSkeleton rows={8} />
      </div>
    );
  }

  if (isError) {
    return (
      <ErrorMessage
        title="Failed to load flights"
        message={(error as any)?.message || 'An error occurred while loading flights'}
        onRetry={() => refetch()}
      />
    );
  }

  return (
    <div>
      {/* Header */}
      <div className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 mb-6">
        <div>
          <h1 className="text-3xl font-bold text-foreground">Flight Tracking</h1>
          {allJourneys.length > 0 && (
            <div className="flex items-center gap-4 mt-1 text-sm text-muted-foreground">
              <span>{stats.total} journeys</span>
              {stats.active > 0 && (
                <span className="flex items-center gap-1">
                  <span className="w-2 h-2 rounded-full bg-purple-500 animate-pulse" />
                  {stats.active} in flight
                </span>
              )}
              {stats.connectionRisk > 0 && (
                <span className="flex items-center gap-1">
                  <span className="w-2 h-2 rounded-full bg-orange-500" />
                  {stats.connectionRisk} at risk
                </span>
              )}
              {stats.delayed > 0 && (
                <span className="flex items-center gap-1">
                  <span className="w-2 h-2 rounded-full bg-amber-500" />
                  {stats.delayed} delayed
                </span>
              )}
              <span>{stats.landed} landed</span>
            </div>
          )}
        </div>

        <div className="flex items-center gap-3">
          <BudgetIndicator />
          {allJourneys.length > 0 && (
            <button
              onClick={() => refreshActiveMutation.mutate()}
              disabled={refreshActiveMutation.isPending}
              className="inline-flex items-center px-3 py-2 border border-border rounded-md text-sm text-foreground bg-card hover:bg-accent transition-colors disabled:opacity-50"
            >
              <RefreshCw className={`h-4 w-4 mr-2 ${refreshActiveMutation.isPending ? 'animate-spin' : ''}`} />
              Refresh Active
            </button>
          )}
          <button
            onClick={handleAdd}
            className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-primary hover:bg-primary/90 transition-colors"
          >
            <Plus className="h-4 w-4 mr-2" />
            Add Flight
          </button>
        </div>
      </div>

      {/* Search and Filter */}
      {allJourneys.length > 0 && (
        <div className="bg-card shadow-soft border border-border rounded-lg p-4 mb-6">
          <div className="flex gap-3">
            <div className="flex-1 relative">
              <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-5 w-5 text-muted-foreground pointer-events-none" />
              <input
                type="text"
                placeholder="Search by flight number, VIP, airline, or airport..."
                value={searchTerm}
                onChange={(e) => setSearchTerm(e.target.value)}
                className="w-full pl-10 pr-4 py-2.5 border border-input rounded-md focus:ring-primary focus:border-primary text-base bg-background transition-colors"
                style={{ minHeight: '44px' }}
              />
            </div>
            <button
              onClick={() => setFilterModalOpen(true)}
              className="inline-flex items-center px-4 py-2 border border-border rounded-md text-foreground bg-card hover:bg-accent font-medium transition-colors"
              style={{ minHeight: '44px' }}
            >
              <Filter className="h-5 w-5 mr-2" />
              Filters
              {selectedStatuses.length > 0 && (
                <span className="ml-2 inline-flex items-center justify-center px-2 py-0.5 text-xs font-bold leading-none text-white bg-primary rounded-full">
                  {selectedStatuses.length}
                </span>
              )}
            </button>
          </div>

          {selectedStatuses.length > 0 && (
            <div className="flex flex-wrap gap-2 mt-3 pt-3 border-t border-border">
              <span className="text-sm text-muted-foreground py-1.5">Active filters:</span>
              {selectedStatuses.map((status) => (
                <FilterChip
                  key={status}
                  label={getFilterLabel(status)}
                  onRemove={() => handleRemoveStatusFilter(status)}
                />
              ))}
            </div>
          )}

          <div className="flex items-center justify-between mt-3 pt-3 border-t border-border">
            <div className="text-sm text-muted-foreground">
              Showing <span className="font-medium text-foreground">{journeys.length}</span> of <span className="font-medium text-foreground">{allJourneys.length}</span> journeys
            </div>
            {(searchTerm || selectedStatuses.length > 0) && (
              <button
                onClick={handleClearFilters}
                className="inline-flex items-center px-3 py-1.5 text-sm text-muted-foreground hover:text-foreground hover:bg-accent rounded-md transition-colors"
              >
                <X className="h-4 w-4 mr-1" />
                Clear All
              </button>
            )}
          </div>
        </div>
      )}

      {/* Journey Groups */}
      {allJourneys.length > 0 ? (
        <div className="space-y-6">
          {journeyGroups.map((group) => {
            if (group.journeys.length === 0) return null;
            const isCollapsed = collapsedGroups.has(group.key);
            const Icon = group.icon;

            return (
              <div key={group.key}>
                {/* Group header */}
                <button
                  onClick={() => toggleGroup(group.key)}
                  className="flex items-center gap-2 mb-3 w-full text-left group"
                >
                  {isCollapsed ? (
                    <ChevronRight className="w-4 h-4 text-muted-foreground" />
                  ) : (
                    <ChevronDown className="w-4 h-4 text-muted-foreground" />
                  )}
                  <Icon className={`w-4 h-4 ${group.color}`} />
                  <span className={`text-sm font-semibold uppercase tracking-wider ${group.color}`}>
                    {group.label}
                  </span>
                  <span className="text-xs text-muted-foreground font-normal">
                    ({group.journeys.length})
                  </span>
                  <div className="flex-1 border-t border-border/50 ml-2" />
                </button>

                {/* Journey cards */}
                {!isCollapsed && (
                  <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
                    {group.journeys.map((journey) => (
                      <FlightCard
                        key={journey.vipId}
                        journey={journey.isMultiSegment ? journey : undefined}
                        flight={journey.isMultiSegment ? undefined : journey.flights[0]}
                        onEdit={handleEdit}
                        onDelete={handleDelete}
                      />
                    ))}
                  </div>
                )}
              </div>
            );
          })}
        </div>
      ) : (
        <div className="bg-card shadow-soft border border-border rounded-lg p-12 text-center">
          <Plane className="h-12 w-12 text-muted-foreground/50 mx-auto mb-4" />
          <p className="text-muted-foreground mb-4">No flights tracked yet.</p>
          <button
            onClick={handleAdd}
            className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-primary hover:bg-primary/90 transition-colors"
          >
            <Plus className="h-4 w-4 mr-2" />
            Add Your First Flight
          </button>
        </div>
      )}

      {showForm && (
        <FlightForm
          flight={editingFlight}
          onSubmit={handleSubmit}
          onCancel={handleCancel}
          isSubmitting={isSubmitting}
        />
      )}

      <FilterModal
        isOpen={filterModalOpen}
        onClose={() => setFilterModalOpen(false)}
        filterGroups={[
          {
            label: 'Flight Status',
            options: [
              { value: 'scheduled', label: 'Scheduled' },
              { value: 'active', label: 'Active / In Flight' },
              { value: 'landed', label: 'Landed' },
              { value: 'cancelled', label: 'Cancelled' },
              { value: 'diverted', label: 'Diverted' },
              { value: 'incident', label: 'Incident' },
            ],
            selectedValues: selectedStatuses,
            onToggle: handleStatusToggle,
          },
        ]}
        onClear={handleClearFilters}
        onApply={() => {}}
      />
    </div>
  );
}
