import { useMemo, useRef, useState } from 'react';
import { Link, useSearchParams } from 'react-router';
import { ArrowLeft } 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 { PERSON_PARAM, personThumbUrl } from './shared';
import { useBucketAssets, usePeople, usePerson, useTimeBuckets } from './usePhotosData';
import { useSelection } from './useSelection';

// Faces. The wall of people, and one person's photos behind `?person=<id>`.
//
// A person's photos come from the same bucketed timeline endpoint with `personId` set, so a face with 12,000
// photos loads the same way the main timeline does rather than as one enormous response.

export const PeopleSection = () => {
  const [params] = useSearchParams();
  const personId = params.get(PERSON_PARAM);
  return personId ? <PersonDetailView personId={personId} /> : <PeopleListView />;
};

const PeopleListView = () => {
  const { token } = useClient();
  const { data, isLoading } = usePeople();

  // Immich hides unnamed faces behind a toggle; the named ones are what anyone actually browses by.
  const [showUnnamed, setShowUnnamed] = useState(false);
  const people = useMemo(
    () => (data?.people ?? []).filter((person) => showUnnamed || person.name),
    [data, showUnnamed],
  );

  return (
    <div className="flex h-full flex-col">
      <header className="flex items-center gap-2 border-b px-3 py-2">
        <h1 className="text-sm font-semibold">People</h1>
        <span className="text-xs text-muted-foreground">{people.length}</span>
        <div className="flex-1" />
        <Button variant="ghost" size="sm" onClick={() => setShowUnnamed((value) => !value)}>
          {showUnnamed ? 'Hide unnamed' : 'Show unnamed'}
        </Button>
      </header>

      <div className="min-h-0 flex-1 overflow-y-auto p-3">
        {isLoading && <p className="text-sm text-muted-foreground">Loading…</p>}
        {!isLoading && people.length === 0 && (
          <p className="text-sm text-muted-foreground">
            No people yet — Immich populates this as faces are recognised.
          </p>
        )}

        <div className="grid grid-cols-[repeat(auto-fill,minmax(110px,1fr))] gap-4">
          {people.map((person) => (
            <Link key={person.id} to={`?${PERSON_PARAM}=${person.id}`} className="group text-center">
              <img
                src={personThumbUrl(person.id, token)}
                alt=""
                loading="lazy"
                className="mx-auto aspect-square w-full rounded-full object-cover ring-1 ring-white/10 transition group-hover:ring-primary"
              />
              <span className="mt-2 block truncate text-sm">{person.name || 'Unnamed'}</span>
            </Link>
          ))}
        </div>
      </div>
    </div>
  );
};

const PersonDetailView = ({ personId }: { personId: string }) => {
  const { token } = useClient();
  const [params] = useSearchParams();
  const scrollRef = useRef<HTMLDivElement | null>(null);
  const [loaded, setLoaded] = useState<string[]>([]);

  const { data: person } = usePerson(personId);
  const filter = useMemo(() => ({ personId }), [personId]);
  const { data: buckets } = 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 back = (() => {
    const next = new URLSearchParams(params);
    next.delete(PERSON_PARAM);
    const search = next.toString();
    return search ? `?${search}` : '?';
  })();

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

  return (
    <div className="flex h-full flex-col">
      {selection.isSelecting ? (
        <SelectionBar selection={selection} />
      ) : (
        <header className="flex items-center gap-2 border-b px-3 py-2">
          <Button asChild variant="ghost" size="icon" title="Back to people">
            <Link to={back}>
              <ArrowLeft className="h-4 w-4" />
            </Link>
          </Button>
          <img src={personThumbUrl(personId, token)} alt="" className="h-7 w-7 rounded-full object-cover" />
          <h1 className="truncate text-sm font-semibold">{person?.name || 'Unnamed'}</h1>
          <span className="text-xs text-muted-foreground">{total.toLocaleString()} items</span>
        </header>
      )}

      <div ref={scrollRef} className="min-h-0 flex-1 overflow-y-auto px-2 pt-2">
        <TimelineGrid
          buckets={buckets ?? []}
          assetsByBucket={assetsByBucket}
          onBucketVisible={(bucket) => setLoaded((prev) => (prev.includes(bucket) ? prev : [...prev, bucket]))}
          token={token}
          selection={selection}
          scrollRef={scrollRef}
        />
      </div>

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