// Modal filtra dla ScenesScreen: multi-select tags + studios + sort + has_playback.
// Otwarty z przycisku "Filter" w toolbarze. Lokalny state, na "Apply" callback do parenta.
import { useQuery } from '@tanstack/react-query';
import React, { useMemo, useState } from 'react';
import {
  ActivityIndicator,
  FlatList,
  Modal,
  Pressable,
  StyleSheet,
  Switch,
  Text,
  TextInput,
  View,
} from 'react-native';
import { useClient } from '../ClientContext';
import { theme } from '../theme';
import type { ScenesSort, TagCount, StudioCount, PerformerCount } from '../types';

export interface FilterState {
  tagSlugs: string[];
  studioSlugs: string[];
  performerIds: string[];
  sort: ScenesSort;
  hasPlayback: boolean;
  includeStubs: boolean;
  origin: string;
  minDurationSec: number; // 0 = bazowy próg (60s); >0 podnosi minimum (filtr na klipy-reklamy)
}

export const DEFAULT_FILTER: FilterState = {
  tagSlugs: [],
  studioSlugs: [],
  performerIds: [],
  sort: 'created_at',
  hasPlayback: true, // default: ukryj sceny bez playback linka (kompletność > świeżość)
  includeStubs: false, // default: ukryj 5-10min hqporner trailery bez release_date
  origin: '', // pusty = wszystkie źródła; substring match np. 'hqporner'
  minDurationSec: 0,
};

const SORT_OPTIONS: { value: ScenesSort; label: string }[] = [
  { value: 'created_at', label: 'newest ingest' },
  { value: 'release_date', label: 'release date' },
  { value: 'title', label: 'title' },
  { value: 'studio', label: 'studio' },
];

// Filtr długości — user-report mobilism: "short clips nowadays are mostly ads in
// disguise". "Any" = bazowy próg backendu (60s, ukrywa teasery); reszta podnosi minimum.
const DURATION_OPTIONS: { value: number; label: string }[] = [
  { value: 0, label: 'Any' },
  { value: 300, label: '5+ min' },
  { value: 600, label: '10+ min' },
  { value: 1200, label: '20+ min' },
  { value: 1800, label: '30+ min' },
];

export function ScenesFilterModal({
  visible,
  initial,
  onApply,
  onClose,
}: {
  visible: boolean;
  initial: FilterState;
  onApply: (next: FilterState) => void;
  onClose: () => void;
}) {
  const client = useClient();
  const [draft, setDraft] = useState<FilterState>(initial);
  const [tagQ, setTagQ] = useState('');
  const [studioQ, setStudioQ] = useState('');
  const [performerQ, setPerformerQ] = useState('');

  // Reset draft do initial gdy modal jest otwierany na nowo.
  React.useEffect(() => {
    if (visible) setDraft(initial);
  }, [visible, initial]);

  const tagsQuery = useQuery({
    queryKey: ['filter-tags', tagQ],
    queryFn: () => client.listTags({ q: tagQ || undefined, per_page: 200 }),
    enabled: visible,
  });

  const studiosQuery = useQuery({
    queryKey: ['filter-studios', studioQ],
    queryFn: () => client.listStudios({ q: studioQ || undefined, order: 'scene_count', per_page: 200 }),
    enabled: visible,
  });

  // Performerzy z draft (zaznaczeni) ZAWSZE muszą być widoczni — żeby user widział
  // co już ma wybrane gdy resetuje search. Łączymy listę z search-result + selected.
  const performersQuery = useQuery({
    queryKey: ['filter-performers', performerQ],
    queryFn: () => client.listPerformers({ q: performerQ || undefined, order: 'scene_count', per_page: 100 }),
    enabled: visible,
  });
  const selectedPerformersQuery = useQuery({
    queryKey: ['filter-performers-selected', draft.performerIds.join(',')],
    queryFn: async () => {
      // Backend nie ma batch-by-id; pobieramy listę top i filtrujemy. Rozwiązanie
      // tymczasowe — chip "selected" jest stabilny dopóki nazwa jest w top 200.
      const r = await client.listPerformers({ order: 'scene_count', per_page: 200 });
      return r.items.filter((p) => draft.performerIds.includes(p.id));
    },
    enabled: visible && draft.performerIds.length > 0,
  });

  const toggle = (list: string[], value: string): string[] =>
    list.includes(value) ? list.filter((s) => s !== value) : [...list, value];

  const reset = () => setDraft(DEFAULT_FILTER);
  const apply = () => onApply(draft);

  const activeCount =
    draft.tagSlugs.length +
    draft.studioSlugs.length +
    draft.performerIds.length +
    (draft.hasPlayback ? 1 : 0) +
    (draft.minDurationSec > 0 ? 1 : 0);

  return (
    <Modal visible={visible} animationType="slide" onRequestClose={onClose}>
      <View style={styles.container}>
        <View style={styles.header}>
          <Pressable onPress={onClose} hitSlop={12}>
            <Text style={styles.headerCancel}>Cancel</Text>
          </Pressable>
          <Text style={styles.headerTitle}>
            Filter {activeCount > 0 ? `(${activeCount})` : ''}
          </Text>
          <Pressable onPress={apply} hitSlop={12}>
            <Text style={styles.headerApply}>Apply</Text>
          </Pressable>
        </View>

        <FlatList
          data={[1]}
          keyExtractor={() => 'sections'}
          renderItem={() => (
            <View>
              <Section title="Sort by">
                <View style={styles.sortRow}>
                  {SORT_OPTIONS.map((opt) => (
                    <Pressable
                      key={opt.value}
                      style={[
                        styles.sortPill,
                        draft.sort === opt.value && styles.sortPillActive,
                      ]}
                      onPress={() => setDraft({ ...draft, sort: opt.value })}
                    >
                      <Text
                        style={[
                          styles.sortPillText,
                          draft.sort === opt.value && styles.sortPillTextActive,
                        ]}
                      >
                        {opt.label}
                      </Text>
                    </Pressable>
                  ))}
                </View>
              </Section>

              <Section title="Only with playback">
                <View style={styles.switchRow}>
                  <Switch
                    value={draft.hasPlayback}
                    onValueChange={(v) => setDraft({ ...draft, hasPlayback: v })}
                    trackColor={{ false: theme.border, true: theme.accent }}
                    thumbColor={theme.fg}
                  />
                </View>
              </Section>

              <Section title="Min duration">
                <View style={styles.sortRow}>
                  {DURATION_OPTIONS.map((opt) => (
                    <Pressable
                      key={opt.value}
                      style={[
                        styles.sortPill,
                        draft.minDurationSec === opt.value && styles.sortPillActive,
                      ]}
                      onPress={() => setDraft({ ...draft, minDurationSec: opt.value })}
                    >
                      <Text
                        style={[
                          styles.sortPillText,
                          draft.minDurationSec === opt.value && styles.sortPillTextActive,
                        ]}
                      >
                        {opt.label}
                      </Text>
                    </Pressable>
                  ))}
                </View>
              </Section>

              <Section title="Source / hoster">
                <TextInput
                  style={styles.search}
                  value={draft.origin}
                  onChangeText={(v) => setDraft({ ...draft, origin: v })}
                  placeholder="e.g. hqporner, porntrex, xnxx — empty = all"
                  placeholderTextColor={theme.muted}
                  autoCapitalize="none"
                  autoCorrect={false}
                />
              </Section>

              <Section title={`Tags (${draft.tagSlugs.length} selected)`}>
                <TextInput
                  style={styles.search}
                  value={tagQ}
                  onChangeText={setTagQ}
                  placeholder="search tags…"
                  placeholderTextColor={theme.muted}
                  autoCapitalize="none"
                />
                {tagsQuery.isLoading ? (
                  <ActivityIndicator color={theme.fg} style={{ margin: 12 }} />
                ) : (
                  <View style={styles.chipsRow}>
                    {(tagsQuery.data?.items ?? []).map((tag: TagCount) => {
                      const active = draft.tagSlugs.includes(tag.slug);
                      return (
                        <Pressable
                          key={tag.id}
                          style={[styles.chip, active && styles.chipActive]}
                          onPress={() =>
                            setDraft({ ...draft, tagSlugs: toggle(draft.tagSlugs, tag.slug) })
                          }
                        >
                          <Text
                            style={[
                              styles.chipText,
                              active && styles.chipTextActive,
                            ]}
                          >
                            {tag.name}
                            <Text style={styles.chipCount}> · {tag.scene_count}</Text>
                          </Text>
                        </Pressable>
                      );
                    })}
                  </View>
                )}
              </Section>

              <Section title={`Studios (${draft.studioSlugs.length} selected)`}>
                <TextInput
                  style={styles.search}
                  value={studioQ}
                  onChangeText={setStudioQ}
                  placeholder="search studios…"
                  placeholderTextColor={theme.muted}
                  autoCapitalize="none"
                />
                {studiosQuery.isLoading ? (
                  <ActivityIndicator color={theme.fg} style={{ margin: 12 }} />
                ) : (
                  <View style={styles.chipsRow}>
                    {(studiosQuery.data?.items ?? []).map((studio: StudioCount) => {
                      const active = draft.studioSlugs.includes(studio.slug);
                      return (
                        <Pressable
                          key={studio.id}
                          style={[styles.chip, active && styles.chipActive]}
                          onPress={() =>
                            setDraft({
                              ...draft,
                              studioSlugs: toggle(draft.studioSlugs, studio.slug),
                            })
                          }
                        >
                          <Text
                            style={[
                              styles.chipText,
                              active && styles.chipTextActive,
                            ]}
                          >
                            {studio.name}
                            <Text style={styles.chipCount}> · {studio.scene_count}</Text>
                          </Text>
                        </Pressable>
                      );
                    })}
                  </View>
                )}
              </Section>

              <Section title={`Performers (${draft.performerIds.length} selected)`}>
                <TextInput
                  style={styles.search}
                  value={performerQ}
                  onChangeText={setPerformerQ}
                  placeholder="search performers…"
                  placeholderTextColor={theme.muted}
                  autoCapitalize="none"
                />
                {performersQuery.isLoading ? (
                  <ActivityIndicator color={theme.fg} style={{ margin: 12 }} />
                ) : (
                  <View style={styles.chipsRow}>
                    {(() => {
                      const fromSearch = performersQuery.data?.items ?? [];
                      const fromSelected = selectedPerformersQuery.data ?? [];
                      // Merge — selected rzucamy na początek, deduplikujemy po id.
                      const seen = new Set<string>();
                      const merged: PerformerCount[] = [];
                      for (const p of [...fromSelected, ...fromSearch]) {
                        if (seen.has(p.id)) continue;
                        seen.add(p.id);
                        merged.push(p);
                      }
                      return merged.map((perf: PerformerCount) => {
                        const active = draft.performerIds.includes(perf.id);
                        return (
                          <Pressable
                            key={perf.id}
                            style={[styles.chip, active && styles.chipActive]}
                            onPress={() =>
                              setDraft({
                                ...draft,
                                performerIds: toggle(draft.performerIds, perf.id),
                              })
                            }
                          >
                            <Text
                              style={[
                                styles.chipText,
                                active && styles.chipTextActive,
                              ]}
                            >
                              {perf.canonical_name}
                              <Text style={styles.chipCount}> · {perf.scene_count}</Text>
                            </Text>
                          </Pressable>
                        );
                      });
                    })()}
                  </View>
                )}
              </Section>

              <View style={styles.resetRow}>
                <Pressable onPress={reset} style={styles.resetButton}>
                  <Text style={styles.resetText}>Reset all filters</Text>
                </Pressable>
              </View>
            </View>
          )}
        />
      </View>
    </Modal>
  );
}

function Section({ title, children }: { title: string; children: React.ReactNode }) {
  return (
    <View style={styles.section}>
      <Text style={styles.sectionTitle}>{title}</Text>
      {children}
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, backgroundColor: theme.bg },
  header: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    paddingHorizontal: 16,
    paddingVertical: 14,
    borderBottomColor: theme.border,
    borderBottomWidth: 1,
    backgroundColor: theme.card,
  },
  headerCancel: { color: theme.muted, fontSize: 15 },
  headerTitle: { color: theme.fg, fontSize: 16, fontWeight: '600' },
  headerApply: { color: theme.accent, fontSize: 15, fontWeight: '600' },
  section: {
    paddingHorizontal: 16,
    paddingVertical: 14,
    borderBottomColor: theme.border,
    borderBottomWidth: 1,
  },
  sectionTitle: {
    color: theme.muted,
    fontSize: 12,
    textTransform: 'uppercase',
    letterSpacing: 0.5,
    marginBottom: 10,
  },
  sortRow: { flexDirection: 'row', flexWrap: 'wrap', gap: 8 },
  sortPill: {
    backgroundColor: theme.card,
    borderColor: theme.border,
    borderWidth: 1,
    borderRadius: 16,
    paddingHorizontal: 12,
    paddingVertical: 6,
  },
  sortPillActive: { borderColor: theme.accent, backgroundColor: theme.bg },
  sortPillText: { color: theme.fg, fontSize: 13 },
  sortPillTextActive: { color: theme.accent, fontWeight: '600' },
  switchRow: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
  },
  switchLabel: { color: theme.fg, fontSize: 14, flex: 1 },
  search: {
    backgroundColor: theme.card,
    borderColor: theme.border,
    borderWidth: 1,
    borderRadius: 8,
    color: theme.fg,
    padding: 10,
    marginBottom: 10,
  },
  chipsRow: { flexDirection: 'row', flexWrap: 'wrap', gap: 6 },
  chip: {
    backgroundColor: theme.card,
    borderColor: theme.border,
    borderWidth: 1,
    borderRadius: 14,
    paddingHorizontal: 10,
    paddingVertical: 5,
  },
  chipActive: { borderColor: theme.accent, backgroundColor: theme.bg },
  chipText: { color: theme.fg, fontSize: 13 },
  chipTextActive: { color: theme.accent, fontWeight: '600' },
  chipCount: { color: theme.muted, fontSize: 11 },
  resetRow: { padding: 16 },
  resetButton: {
    borderColor: theme.bad,
    borderWidth: 1,
    borderRadius: 8,
    padding: 12,
    alignItems: 'center',
  },
  resetText: { color: theme.bad, fontSize: 14, fontWeight: '600' },
});
