import { useCallback, useEffect, useMemo } from 'react';
import { createPortal } from 'react-dom';
import { X, UserPlus, Globe, Users, Lock } from 'lucide-react';
import { HumanAvatar } from '@/components/human-avatar';
import { ScrollArea } from '@/components/ui/scroll-area';
import { KeyHint } from '@/components/key-hint';
import {
  buildCustomVisibility,
  buildNetworkVisibility,
  parseVisibleTo,
} from '@/lib/stream-visibility';
import { updateParticleVisibleTo } from '@/lib/firestore-particles';
import { toFirestoreDocPath, type ParticlePath } from '@/lib/particle-path';
import { useNetwork } from '@/hooks/use-networks';
import { cn, getInitials } from '@/lib/utils';
import { resolveHumanDisplay } from '@/lib/humans';
import type { Particle } from '@/api/types';
import { useSuspendPlayback } from '@/hooks/use-suspend-playback';

interface StreamMembersOverlayProps {
  networkId: string;
  streamPath: ParticlePath;
  streamParticle: Particle & { type: 'stream' };
  isCreator: boolean;
  onClose: () => void;
}

export function StreamMembersOverlay({
  networkId,
  streamPath,
  streamParticle,
  isCreator,
  onClose,
}: StreamMembersOverlayProps) {
  useSuspendPlayback(true, 'stream-members');

  const network = useNetwork(networkId);
  const humans = network?.humans ?? [];
  const creatorId = streamParticle.created_by_human_id;
  const visibility = useMemo(
    () => parseVisibleTo(streamParticle.visible_to, networkId),
    [streamParticle.visible_to, networkId],
  );

  const docPath = useMemo(() => toFirestoreDocPath(streamPath), [streamPath]);

  const memberIds =
    visibility.mode === 'network'
      ? humans.map((h) => h.id)
      : visibility.humanIds;
  const memberSet = new Set(memberIds);
  const availableToAdd = humans.filter((h) => !memberSet.has(h.id));

  const setNetworkWide = useCallback(() => {
    void updateParticleVisibleTo(docPath, buildNetworkVisibility(networkId));
  }, [docPath, networkId]);

  const setCustomOnlyCreator = useCallback(() => {
    void updateParticleVisibleTo(docPath, buildCustomVisibility([creatorId]));
  }, [docPath, creatorId]);

  const removeMember = useCallback(
    (id: string) => {
      if (visibility.mode !== 'custom') return;
      if (id === creatorId) return;
      const next = visibility.humanIds.filter((x) => x !== id);
      if (next.length === 0) return;
      void updateParticleVisibleTo(docPath, buildCustomVisibility(next));
    },
    [docPath, creatorId, visibility],
  );

  const addMember = useCallback(
    (id: string) => {
      if (visibility.mode !== 'custom') return;
      void updateParticleVisibleTo(
        docPath,
        buildCustomVisibility([...visibility.humanIds, id]),
      );
    },
    [docPath, visibility],
  );

  useEffect(() => {
    const handler = (e: KeyboardEvent) => {
      if (e.key === 'Escape') {
        e.preventDefault();
        e.stopPropagation();
        onClose();
      }
    };
    window.addEventListener('keydown', handler, { capture: true });
    return () =>
      window.removeEventListener('keydown', handler, { capture: true });
  }, [onClose]);

  return createPortal(
    <div className="fixed inset-0 z-[100]">
      <div
        className="bg-scrim/60 absolute inset-0 backdrop-blur-sm"
        onClick={onClose}
      />
      <div className="bg-popover/95 text-popover-foreground border-border absolute left-1/2 top-1/2 flex max-h-[80vh] w-full max-w-sm -translate-x-1/2 -translate-y-1/2 flex-col overflow-hidden rounded-2xl border p-6 shadow-2xl backdrop-blur-xl">
        {/* Header */}
        <div className="mb-4 flex items-center justify-between">
          <h2 className="text-sm font-semibold">Members</h2>
          <KeyHint
            keys="Esc"
            onClick={onClose}
            title="Close (or press Esc)"
            className="text-muted-foreground text-xs"
          >
            to close
          </KeyHint>
        </div>

        {/* Visibility */}
        <section className="mb-4">
          <h3 className="text-muted-foreground mb-2 text-[10px] font-medium uppercase tracking-widest">
            Visibility
          </h3>
          {isCreator ? (
            <div className="bg-muted grid grid-cols-2 gap-1 rounded-lg p-1">
              <VisibilityPill
                active={visibility.mode === 'network'}
                icon={<Globe className="size-3.5" />}
                label="Network-wide"
                onClick={setNetworkWide}
              />
              <VisibilityPill
                active={visibility.mode === 'custom'}
                icon={<Lock className="size-3.5" />}
                label="Specific people"
                onClick={setCustomOnlyCreator}
              />
            </div>
          ) : (
            <div className="text-foreground flex items-center gap-2 text-sm">
              {visibility.mode === 'network' ? (
                <>
                  <Globe className="text-muted-foreground size-3.5" />
                  <span>Everyone in {network?.name ?? 'network'}</span>
                </>
              ) : (
                <>
                  <Lock className="text-muted-foreground size-3.5" />
                  <span>{memberIds.length} specific people</span>
                </>
              )}
            </div>
          )}
        </section>

        {/* Member list */}
        <section className="flex min-h-0 flex-1 flex-col">
          <h3 className="text-muted-foreground mb-2 text-[10px] font-medium uppercase tracking-widest">
            {visibility.mode === 'network' ? 'Has access' : 'People'}{' '}
            <span className="text-muted-foreground ml-1">
              {memberIds.length}
            </span>
          </h3>
          <ScrollArea className="min-h-0 flex-1">
            <ul className="flex flex-col gap-0.5 pr-2">
              {memberIds.map((id) => {
                const display = resolveHumanDisplay(id, humans);
                const isCreatorRow = id === creatorId;
                const canRemove =
                  isCreator && visibility.mode === 'custom' && !isCreatorRow;
                return (
                  <li
                    key={id}
                    className="text-foreground group flex items-center gap-2.5 rounded px-2 py-1.5 text-sm"
                  >
                    <HumanAvatar
                      size="sm"
                      avatarObjectId={display.avatarObjectId}
                      initials={display.initials}
                      fallbackClassName="text-[10px]"
                    />
                    <span
                      className={cn(
                        'flex-1 truncate',
                        !display.exists && 'text-muted-foreground italic',
                      )}
                    >
                      {display.displayName}
                    </span>
                    {isCreatorRow && (
                      <span className="text-muted-foreground text-[10px] uppercase tracking-wider">
                        Creator
                      </span>
                    )}
                    {canRemove && (
                      <button
                        type="button"
                        onClick={() => removeMember(id)}
                        className="text-muted-foreground hover:bg-accent hover:text-foreground rounded p-1 opacity-0 transition-opacity group-hover:opacity-100"
                        aria-label={`Remove ${display.displayName}`}
                      >
                        <X className="size-3.5" />
                      </button>
                    )}
                  </li>
                );
              })}
            </ul>
          </ScrollArea>
        </section>

        {/* Add */}
        {isCreator &&
          visibility.mode === 'custom' &&
          availableToAdd.length > 0 && (
            <section className="border-border mt-4 border-t pt-4">
              <h3 className="text-muted-foreground mb-2 flex items-center gap-1.5 text-[10px] font-medium uppercase tracking-widest">
                <UserPlus className="size-3" />
                Add people
              </h3>
              <ScrollArea className="max-h-32">
                <ul className="flex flex-col gap-0.5 pr-2">
                  {availableToAdd.map((human) => (
                    <li key={human.id}>
                      <button
                        type="button"
                        onClick={() => addMember(human.id)}
                        className={cn(
                          'text-foreground hover:bg-accent flex w-full items-center gap-2.5 rounded px-2 py-1.5 text-left text-sm transition-colors',
                        )}
                      >
                        <HumanAvatar
                          size="sm"
                          avatarObjectId={human.avatar_object_id}
                          initials={getInitials(human.email)}
                          fallbackClassName="text-[10px]"
                        />
                        <span className="flex-1 truncate">
                          {human.email_prefix}
                        </span>
                        <UserPlus className="text-muted-foreground size-3.5" />
                      </button>
                    </li>
                  ))}
                </ul>
              </ScrollArea>
            </section>
          )}

        {isCreator &&
          visibility.mode === 'custom' &&
          availableToAdd.length === 0 && (
            <p className="text-muted-foreground mt-4 text-center text-xs">
              <Users className="mr-1 inline size-3" />
              Everyone in the network is already a member
            </p>
          )}
      </div>
    </div>,
    document.body,
  );
}

function VisibilityPill({
  active,
  icon,
  label,
  onClick,
}: {
  active: boolean;
  icon: React.ReactNode;
  label: string;
  onClick: () => void;
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={cn(
        'flex items-center justify-center gap-1.5 rounded-md px-2 py-1.5 text-xs transition-colors',
        active
          ? 'bg-background text-foreground shadow-sm'
          : 'text-muted-foreground hover:text-foreground',
      )}
    >
      {icon}
      {label}
    </button>
  );
}
