import { useState, useMemo, useRef, useEffect } from 'react';
import { Plus, MapPin, Phone, Mail, Tag, AlignLeft } from 'lucide-react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner';
import api, { getErrorMessage } from '@/lib/api';
import type { Location } from '@/types';
import { Button } from '@/components/ui/button';
import { EmptyState } from '@/components/ui/empty-state';
import {
  EntityTable,
  EntityDetailPanel,
  CategoryFilterBar,
  type ColumnDef,
  type PanelField,
} from '@/components/shared';
import { useTableVisibility } from '@/hooks/useTableVisibility';
import { useCategoryOrder } from '@/hooks/useCategoryOrder';
import LocationForm from './LocationForm';

export default function LocationsPage() {
  const queryClient = useQueryClient();

  const [selectedLocationId, setSelectedLocationId] = useState<number | null>(null);
  const [showForm, setShowForm] = useState(false);
  const [editingLocation, setEditingLocation] = useState<Location | null>(null);
  const [activeFilters, setActiveFilters] = useState<string[]>([]);
  const [showPinned, setShowPinned] = useState(true);
  const [search, setSearch] = useState('');
  const [sortKey, setSortKey] = useState<string>('name');
  const [sortDir, setSortDir] = useState<'asc' | 'desc'>('asc');

  const tableRef = useRef<HTMLDivElement>(null);
  const panelOpen = selectedLocationId !== null;
  const visibilityMode = useTableVisibility(tableRef as React.RefObject<HTMLElement>, panelOpen);

  const { data: locations = [], isLoading } = useQuery({
    queryKey: ['locations'],
    queryFn: async () => {
      const { data } = await api.get<Location[]>('/locations');
      return data;
    },
  });

  const deleteMutation = useMutation({
    mutationFn: async () => {
      await api.delete(`/locations/${selectedLocationId}`);
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['locations'] });
      queryClient.invalidateQueries({ queryKey: ['dashboard'] });
      queryClient.invalidateQueries({ queryKey: ['upcoming'] });
      toast.success('Location deleted');
      setSelectedLocationId(null);
    },
    onError: (error) => {
      toast.error(getErrorMessage(error, 'Failed to delete location'));
    },
  });

  // Toggle frequent mutation
  const toggleFrequentMutation = useMutation({
    mutationFn: async (loc: Location) => {
      await api.put(`/locations/${loc.id}`, { is_frequent: !loc.is_frequent });
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['locations'] });
    },
    onError: (error) => {
      toast.error(getErrorMessage(error, 'Failed to update frequent'));
    },
  });

  const allCategories = useMemo(
    () => Array.from(new Set(locations.map((l) => l.category).filter(Boolean))).sort(),
    [locations]
  );

  const { orderedCategories, reorder: reorderCategories } = useCategoryOrder('locations', allCategories);

  const sortedLocations = useMemo(() => {
    return [...locations].sort((a, b) => {
      const aVal = String(a[sortKey as keyof Location] ?? '');
      const bVal = String(b[sortKey as keyof Location] ?? '');
      const cmp = aVal.localeCompare(bVal);
      return sortDir === 'asc' ? cmp : -cmp;
    });
  }, [locations, sortKey, sortDir]);

  const frequentLocations = useMemo(
    () => sortedLocations.filter((l) => l.is_frequent),
    [sortedLocations]
  );

  const filteredLocations = useMemo(
    () =>
      sortedLocations.filter((l) => {
        if (showPinned && l.is_frequent) return false;
        if (activeFilters.length > 0 && !activeFilters.includes(l.category)) return false;
        if (search) {
          const q = search.toLowerCase();
          if (
            !l.name.toLowerCase().includes(q) &&
            !(l.address?.toLowerCase().includes(q)) &&
            !(l.category?.toLowerCase().includes(q))
          )
            return false;
        }
        return true;
      }),
    [sortedLocations, activeFilters, search, showPinned]
  );

  // Build row groups for the table — ordered by custom category order
  const groups = useMemo(() => {
    if (activeFilters.length <= 1) {
      const label = activeFilters.length === 1 ? activeFilters[0] : 'All';
      return [{ label, rows: filteredLocations }];
    }
    return orderedCategories
      .filter((cat) => activeFilters.includes(cat))
      .map((cat) => ({
        label: cat,
        rows: filteredLocations.filter((l) => l.category === cat),
      }))
      .filter((g) => g.rows.length > 0);
  }, [activeFilters, filteredLocations, orderedCategories]);

  const selectedLocation = useMemo(
    () => locations.find((l) => l.id === selectedLocationId) ?? null,
    [locations, selectedLocationId]
  );

  const handleSort = (key: string) => {
    if (sortKey === key) {
      setSortDir((d) => (d === 'asc' ? 'desc' : 'asc'));
    } else {
      setSortKey(key);
      setSortDir('asc');
    }
  };

  const handleRowClick = (id: number) => {
    setSelectedLocationId((prev) => (prev === id ? null : id));
  };

  const handleEdit = () => {
    if (!selectedLocation) return;
    setEditingLocation(selectedLocation);
    setShowForm(true);
  };

  // Escape key closes detail panel
  useEffect(() => {
    if (!panelOpen) return;
    const handler = (e: KeyboardEvent) => {
      if (e.key === 'Escape') setSelectedLocationId(null);
    };
    document.addEventListener('keydown', handler);
    return () => document.removeEventListener('keydown', handler);
  }, [panelOpen]);

  const handleCloseForm = () => {
    setShowForm(false);
    setEditingLocation(null);
  };

  const handleToggleCategory = (cat: string) => {
    setActiveFilters((prev) =>
      prev.includes(cat) ? prev.filter((c) => c !== cat) : [...prev, cat]
    );
  };
  const selectAllCategories = () => {
    const allSelected = orderedCategories.every((c) => activeFilters.includes(c));
    setActiveFilters(allSelected ? [] : [...orderedCategories]);
  };

  const columns: ColumnDef<Location>[] = [
    {
      key: 'name',
      label: 'Location',
      sortable: true,
      visibilityLevel: 'essential',
      render: (l) => (
        <div className="flex items-center gap-2.5">
          <div className="p-1 rounded-md bg-accent/10 shrink-0">
            <MapPin
              className="h-3.5 w-3.5"
              style={{ color: 'hsl(var(--accent-color))' }}
            />
          </div>
          <span className="font-medium truncate">{l.name}</span>
        </div>
      ),
    },
    {
      key: 'address',
      label: 'Address',
      sortable: true,
      visibilityLevel: 'essential',
      render: (l) => <span className="text-muted-foreground truncate">{l.address}</span>,
    },
    {
      key: 'contact_number',
      label: 'Contact',
      sortable: false,
      visibilityLevel: 'filtered',
      render: (l) => (
        <span className="text-muted-foreground">{l.contact_number || '—'}</span>
      ),
    },
    {
      key: 'email',
      label: 'Email',
      sortable: true,
      visibilityLevel: 'filtered',
      render: (l) => (
        <span className="text-muted-foreground truncate">{l.email || '—'}</span>
      ),
    },
    {
      key: 'category',
      label: 'Category',
      sortable: true,
      visibilityLevel: 'all',
      render: (l) =>
        l.category && l.category.toLowerCase() !== 'other' ? (
          <span
            className="px-2 py-0.5 text-xs rounded"
            style={{
              backgroundColor: 'hsl(var(--accent-color) / 0.1)',
              color: 'hsl(var(--accent-color))',
            }}
          >
            {l.category}
          </span>
        ) : (
          <span className="text-muted-foreground">—</span>
        ),
    },
  ];

  const panelFields: PanelField[] = [
    { label: 'Contact Number', key: 'contact_number', copyable: true, icon: Phone },
    { label: 'Email', key: 'email', copyable: true, icon: Mail },
    { label: 'Category', key: 'category', icon: Tag },
    { label: 'Address', key: 'address', copyable: true, icon: MapPin, fullWidth: true },
    { label: 'Notes', key: 'notes', multiline: true, icon: AlignLeft, fullWidth: true },
  ];

  const renderPanel = () => (
    <EntityDetailPanel<Location>
      item={selectedLocation}
      fields={panelFields}
      onEdit={handleEdit}
      onDelete={() => deleteMutation.mutate()}
      deleteLoading={deleteMutation.isPending}
      onClose={() => setSelectedLocationId(null)}
      renderHeader={(l) => (
        <div className="flex items-center gap-3">
          <div className="p-2 rounded-lg bg-accent/10">
            <MapPin
              className="h-5 w-5"
              style={{ color: 'hsl(var(--accent-color))' }}
            />
          </div>
          <div className="min-w-0">
            <h3 className="font-heading text-lg font-semibold truncate">{l.name}</h3>
            <span className="text-xs text-muted-foreground">{l.category}</span>
          </div>
        </div>
      )}
      getUpdatedAt={(l) => l.updated_at}
      getValue={(l, key) => {
        const val = l[key as keyof Location];
        if (val == null || val === '') return undefined;
        if (typeof val === 'boolean') return undefined;
        return String(val);
      }}
      isFavourite={selectedLocation?.is_frequent}
      onToggleFavourite={() => selectedLocation && toggleFrequentMutation.mutate(selectedLocation)}
      favouriteLabel="frequent"
    />
  );

  return (
    <div className="flex flex-col h-full animate-fade-in">
      {/* Header */}
      <div className="border-b bg-card px-6 h-16 flex items-center gap-4 shrink-0">
        <h1 className="font-heading text-2xl font-bold tracking-tight">Locations</h1>

        <div className="flex-1 min-w-0">
          <CategoryFilterBar
            categories={orderedCategories}
            activeFilters={activeFilters}
            pinnedLabel="Frequent"
            showPinned={showPinned}
            onToggleAll={() => setActiveFilters([])}
            onTogglePinned={() => setShowPinned((v) => !v)}
            onToggleCategory={handleToggleCategory}
            onSelectAllCategories={selectAllCategories}
            onReorderCategories={reorderCategories}
            searchValue={search}
            onSearchChange={setSearch}
          />
        </div>

        <Button onClick={() => setShowForm(true)} size="sm" aria-label="Add location">
          <Plus className="mr-2 h-4 w-4" />
          Add Location
        </Button>
      </div>

      {/* Body */}
      <div className="flex-1 overflow-hidden flex flex-col">
        <div className="flex-1 overflow-hidden flex">
          {/* Table */}
          <div
            ref={tableRef}
            className={`overflow-y-auto transition-all duration-300 ease-[cubic-bezier(0.16,1,0.3,1)] ${
              panelOpen ? 'w-full lg:w-[55%]' : 'w-full'
            }`}
          >
            <div className="px-6 pb-6 pt-5">
              {isLoading ? (
                <EntityTable<Location>
                  columns={columns}
                  groups={[]}
                  pinnedRows={[]}
                  pinnedLabel="Frequent"
                  showPinned={false}
                  selectedId={null}
                  onRowClick={() => {}}
                  sortKey={sortKey}
                  sortDir={sortDir}
                  onSort={handleSort}
                  visibilityMode={visibilityMode}
                  loading={true}
                />
              ) : locations.length === 0 ? (
                <EmptyState
                  icon={MapPin}
                  title="No locations yet"
                  description="Add locations to organise your favourite places, workspaces, and more."
                  actionLabel="Add Location"
                  onAction={() => setShowForm(true)}
                />
              ) : (
                <EntityTable<Location>
                  columns={columns}
                  groups={groups}
                  pinnedRows={frequentLocations}
                  pinnedLabel="Frequent"
                  showPinned={showPinned}
                  selectedId={selectedLocationId}
                  onRowClick={handleRowClick}
                  sortKey={sortKey}
                  sortDir={sortDir}
                  onSort={handleSort}
                  visibilityMode={visibilityMode}
                />
              )}
            </div>
          </div>

          {/* Detail panel (desktop) */}
          <div
            className={`overflow-hidden transition-all duration-300 ease-[cubic-bezier(0.16,1,0.3,1)] ${
              panelOpen ? 'hidden lg:block lg:w-[45%]' : 'w-0 opacity-0'
            }`}
          >
            {renderPanel()}
          </div>
        </div>
      </div>

      {/* Mobile detail panel overlay */}
      {panelOpen && selectedLocation && (
        <div
          className="lg:hidden fixed inset-0 z-50 bg-background/80 backdrop-blur-sm"
          onClick={() => setSelectedLocationId(null)}
        >
          <div
            className="fixed inset-y-0 right-0 w-full sm:w-[400px] bg-card border-l border-border shadow-lg"
            onClick={(e) => e.stopPropagation()}
          >
            {renderPanel()}
          </div>
        </div>
      )}

      {showForm && (
        <LocationForm
          location={editingLocation}
          categories={allCategories}
          onClose={handleCloseForm}
        />
      )}
    </div>
  );
}
