import { useMemo, useState } from 'react';
import { Pressable, ScrollView, Text, View } from 'react-native';
import { Check, Globe, Lock, X } from 'lucide-react-native';
import type { Human } from '@/api/types';
import { cn } from '@/lib/utils';
import { resolveHumanDisplay } from '@/lib/humans';
import {
  buildCustomVisibility,
  buildNetworkVisibility,
  parseVisibleTo,
} from '@/lib/stream-visibility';
import { BottomSheet } from '@/components/BottomSheet';
import { Avatar } from '@/components/Avatar';

interface VisibilityPickerSheetProps {
  open: boolean;
  onClose: () => void;
  networkId: string;
  networkName: string | undefined;
  humans: Human[];
  selfHumanId: string | undefined;
  visibleTo: string[];
  onChange: (visibleTo: string[]) => void;
}

/**
 * Touch-native visibility picker. Mirrors desktop's stream-members-overlay
 * (network-wide vs. specific people) but as a bottom sheet that commits on
 * close — the parent's `visibleTo` only updates when the user taps Done.
 */
export function VisibilityPickerSheet({
  open,
  onClose,
  networkId,
  networkName,
  humans,
  selfHumanId,
  visibleTo,
  onChange,
}: VisibilityPickerSheetProps) {
  const initial = useMemo(
    () => parseVisibleTo(visibleTo, networkId),
    [visibleTo, networkId],
  );

  const [mode, setMode] = useState<'network' | 'custom'>(initial.mode);
  const [selected, setSelected] = useState<Set<string>>(
    () => new Set(initial.mode === 'custom' ? initial.humanIds : []),
  );

  // Re-seed from the committed value each time the sheet opens fresh.
  const [prevOpen, setPrevOpen] = useState(open);
  if (open !== prevOpen) {
    setPrevOpen(open);
    if (open) {
      setMode(initial.mode);
      setSelected(new Set(initial.mode === 'custom' ? initial.humanIds : []));
    }
  }

  const others = humans.filter((h) => h.id !== selfHumanId);

  const toggle = (id: string) => {
    setSelected((prev) => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id);
      else next.add(id);
      return next;
    });
  };

  const commit = () => {
    if (mode === 'network') {
      onChange(buildNetworkVisibility(networkId));
    } else {
      const ids = selfHumanId
        ? [selfHumanId, ...Array.from(selected)]
        : Array.from(selected);
      onChange(buildCustomVisibility(ids));
    }
    onClose();
  };

  const customCount = selected.size + (selfHumanId ? 1 : 0);
  const canCommit = mode === 'network' || customCount >= 2;

  return (
    <BottomSheet open={open} onClose={onClose} maxHeight="80%">
      <View className="flex-row items-center justify-between px-5 pb-3">
        <Pressable onPress={onClose} hitSlop={12}>
          <X color="rgba(255,255,255,0.7)" size={22} />
        </Pressable>
        <Text className="text-white text-base font-semibold">Visible to</Text>
        <Pressable onPress={commit} disabled={!canCommit} hitSlop={12}>
          <Text
            className={cn(
              'text-base font-semibold',
              canCommit ? 'text-white' : 'text-white/30',
            )}
          >
            Done
          </Text>
        </Pressable>
      </View>

      <View className="px-5 pb-3">
        <View className="flex-row gap-1 bg-white/5 rounded-lg p-1">
          <ModePill
            active={mode === 'network'}
            icon={<Globe color="white" size={14} />}
            label="Everyone"
            onPress={() => setMode('network')}
          />
          <ModePill
            active={mode === 'custom'}
            icon={<Lock color="white" size={14} />}
            label="Specific people"
            onPress={() => setMode('custom')}
          />
        </View>
      </View>

      {mode === 'network' ? (
        <View className="px-5 pb-6">
          <Text className="text-white/60 text-sm">
            Everyone in {networkName ?? 'this network'} can see this stream.
          </Text>
        </View>
      ) : (
        <ScrollView contentContainerClassName="px-2 pb-4">
          {others.length === 0 ? (
            <Text className="text-white/50 text-sm px-3 py-4">
              You’re the only member of this network. Invite people on desktop,
              then come back to choose specific viewers.
            </Text>
          ) : (
            others.map((human) => {
              const display = resolveHumanDisplay(human.id, humans);
              const isSelected = selected.has(human.id);
              return (
                <Pressable
                  key={human.id}
                  onPress={() => toggle(human.id)}
                  className={cn(
                    'flex-row items-center gap-3 px-3 py-2.5 rounded-lg',
                    isSelected ? 'bg-white/10' : 'active:bg-white/5',
                  )}
                >
                  <Avatar humanId={human.id} humans={humans} size="sm" />
                  <View className="flex-1">
                    <Text
                      className="text-white text-sm font-medium"
                      numberOfLines={1}
                    >
                      {display.displayName}
                    </Text>
                    <Text className="text-white/40 text-xs" numberOfLines={1}>
                      {display.email}
                    </Text>
                  </View>
                  <View
                    className={cn(
                      'h-6 w-6 items-center justify-center rounded-full border',
                      isSelected ? 'bg-white border-white' : 'border-white/30',
                    )}
                  >
                    {isSelected ? (
                      <Check color="black" size={14} strokeWidth={3} />
                    ) : null}
                  </View>
                </Pressable>
              );
            })
          )}
        </ScrollView>
      )}
    </BottomSheet>
  );
}

function ModePill({
  active,
  icon,
  label,
  onPress,
}: {
  active: boolean;
  icon: React.ReactNode;
  label: string;
  onPress: () => void;
}) {
  return (
    <Pressable
      onPress={onPress}
      className={cn(
        'flex-1 flex-row items-center justify-center gap-1.5 rounded-md py-2',
        active ? 'bg-white/15' : '',
      )}
    >
      {icon}
      <Text
        className={cn(
          'text-xs',
          active ? 'text-white font-semibold' : 'text-white/60',
        )}
      >
        {label}
      </Text>
    </Pressable>
  );
}
