import type { PhotosSectionId } from './shared';
import type { TimelineFilter } from './usePhotosData';
import { useCallback, useMemo, useRef, useState } from 'react';
import { Trash2 } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { useClient } from 'hooks/useClient';
import { AssetViewer } from './AssetViewer';
import { SelectionBar } from './SelectionBar';
import { TimelineGrid } from './TimelineGrid';
import { useAssetActions } from './useAssetActions';
import { useBucketAssets, useTimeBuckets } from './usePhotosData';
import { useSelection } from './useSelection';

// Timeline, Favorites, Archive and Trash are the same screen with a different filter — which is also true in
// Immich, and is why the bucket API takes the filter as query params rather than having four endpoints.

const FILTERS: Partial<Record<PhotosSectionId, TimelineFilter>> = {
  timeline: { visibility: 'timeline', withPartners: true, withStacked: true },
  favorites: { isFavorite: true, withStacked: true },
  archive: { visibility: 'archive', withStacked: true },
  trash: { isTrashed: true },
};

const TITLES: Partial<Record<PhotosSectionId, string>> = {
  timeline: 'Photos',
  favorites: 'Favorites',
  archive: 'Archive',
  trash: 'Trash',
};

type TimelineSectionProps = { section: PhotosSectionId };

export const TimelineSection = ({ section }: TimelineSectionProps) => {
  const { token } = useClient();
  const scrollRef = useRef<HTMLDivElement | null>(null);
  const [loaded, setLoaded] = useState<string[]>([]);
  const { emptyTrash } = useAssetActions();

  const filter = FILTERS[section] ?? FILTERS.timeline!;
  const inTrash = section === 'trash';

  const { data: buckets, isLoading } = useTimeBuckets(filter);
  const assetsByBucket = useBucketAssets(filter, loaded);

  const orderedIds = useMemo(
    () => (buckets ?? []).flatMap((bucket) => (assetsByBucket[bucket.timeBucket] ?? []).map((asset) => asset.id)),
    [buckets, assetsByBucket],
  );
  const selection = useSelection(orderedIds);

  const onBucketVisible = useCallback((bucket: string) => {
    setLoaded((prev) => (prev.includes(bucket) ? prev : [...prev, bucket]));
  }, []);

  const total = (buckets ?? []).reduce((sum, bucket) => sum + bucket.count, 0);

  return (
    <div className="flex h-full flex-col">
      {selection.isSelecting ? (
        <SelectionBar selection={selection} inTrash={inTrash} archived={section === 'archive'} />
      ) : (
        <header className="flex items-center gap-2 border-b px-3 py-2">
          <h1 className="text-sm font-semibold">{TITLES[section] ?? 'Photos'}</h1>
          <span className="text-xs text-muted-foreground">{total.toLocaleString()} items</span>
          <div className="flex-1" />
          {inTrash && total > 0 && (
            <Button
              variant="ghost"
              size="sm"
              onClick={() => window.confirm(`Permanently delete ${total} items?`) && emptyTrash.mutate()}
            >
              <Trash2 className="mr-1.5 h-4 w-4" />
              Empty trash
            </Button>
          )}
        </header>
      )}

      <div ref={scrollRef} className="min-h-0 flex-1 overflow-y-auto px-2 pt-2">
        {isLoading && <p className="p-4 text-sm text-muted-foreground">Loading…</p>}
        {!isLoading && total === 0 && <p className="p-4 text-sm text-muted-foreground">Nothing here.</p>}
        <TimelineGrid
          buckets={buckets ?? []}
          assetsByBucket={assetsByBucket}
          onBucketVisible={onBucketVisible}
          token={token}
          selection={selection}
          scrollRef={scrollRef}
        />
      </div>

      <AssetViewer ids={orderedIds} token={token} inTrash={inTrash} />
    </div>
  );
};
