/**
 * Bottom sheet z filtrami movies — sort + year range + has_playback + genres + studios.
 *
 * Genres i studios używają `/tags?for_movies=1&only_with_content=1` i
 * `/studios?for_movies=1&only_with_content=1` żeby pokazać tylko taksonomie
 * faktycznie wybrane przez movies (ze stake'iem mirror playback). Multi-select
 * przez chipy; backend wspiera comma-separated.
 */
import { useQuery } from '@tanstack/react-query';
import React, { useState } from 'react';
import {
  ActivityIndicator,
  KeyboardAvoidingView,
  Modal,
  Platform,
  Pressable,
  ScrollView,
  StyleSheet,
  Switch,
  Text,
  TextInput,
  TouchableOpacity,
  View,
} from 'react-native';

import { useClient } from '../ClientContext';
import { theme } from '../theme';
import type { MoviesSort } from '../types';

export interface MovieFilters {
  sort: MoviesSort;
  year_from: number | null;
  year_to: number | null;
  has_playback: boolean;
  tag_slugs: string[];
  studio_slugs: string[];
  performer_ids: string[];
}

export const DEFAULT_MOVIE_FILTERS: MovieFilters = {
  sort: 'created_at',
  year_from: null,
  year_to: null,
  has_playback: false,
  tag_slugs: [],
  studio_slugs: [],
  performer_ids: [],
};

const SORT_OPTIONS: { value: MoviesSort; label: string }[] = [
  { value: 'created_at', label: 'Newest first' },
  { value: 'release_year', label: 'Release year' },
  { value: 'release_date', label: 'Date added' },
  { value: 'rating', label: 'Highest rated' },
  { value: 'title', label: 'Title (A→Z)' },
];

interface Props {
  visible: boolean;
  value: MovieFilters;
  onChange: (next: MovieFilters) => void;
  onClose: () => void;
}

export function MovieFiltersSheet({ visible, value, onChange, onClose }: Props) {
  const client = useClient();
  // Local edit state — applied dopiero przy "Apply", żeby user mógł cofnąć
  // zmiany przez backdrop tap bez efektu dla query.
  const [draft, setDraft] = useState<MovieFilters>(value);
  const [yearFromText, setYearFromText] = useState(
    value.year_from?.toString() ?? '',
  );
  const [yearToText, setYearToText] = useState(value.year_to?.toString() ?? '');

  React.useEffect(() => {
    if (visible) {
      setDraft(value);
      setYearFromText(value.year_from?.toString() ?? '');
      setYearToText(value.year_to?.toString() ?? '');
    }
  }, [visible, value]);

  // Genres — top 40 tagów ZE WSKAZANIEM movies (for_movies=1) + filter pustych
  // (only_with_content=1). Cache 5 min — taksonomie wolno się zmieniają.
  const tagsQuery = useQuery({
    queryKey: ['movie-genres'],
    queryFn: () =>
      client.listTags({
        order: 'popular',
        for_movies: true,
        only_with_content: true,
        per_page: 40,
      }),
    enabled: visible,
    staleTime: 5 * 60 * 1000,
  });

  // Studios — top 40 movie-studios. Wystarczy dla typowych wybor; gdy user chce
  // konkretny rzadziej widziany, search-by-q dodamy później.
  const studiosQuery = useQuery({
    queryKey: ['movie-studios'],
    queryFn: () =>
      client.listStudios({
        order: 'scene_count',
        for_movies: true,
        only_with_content: true,
        per_page: 40,
      }),
    enabled: visible,
    staleTime: 5 * 60 * 1000,
  });

  const toggleTag = (slug: string) => {
    setDraft((d) => ({
      ...d,
      tag_slugs: d.tag_slugs.includes(slug)
        ? d.tag_slugs.filter((s) => s !== slug)
        : [...d.tag_slugs, slug],
    }));
  };

  const toggleStudio = (slug: string) => {
    setDraft((d) => ({
      ...d,
      studio_slugs: d.studio_slugs.includes(slug)
        ? d.studio_slugs.filter((s) => s !== slug)
        : [...d.studio_slugs, slug],
    }));
  };

  // Performers — long-tail, więc search-by-q (nie top-N jak studia/genres). `pnames`
  // zapamiętuje id→imię z wyników, żeby zaznaczone chipy pokazywały nazwę.
  const [perfQ, setPerfQ] = useState('');
  const [pnames, setPnames] = useState<Record<string, string>>({});
  const performersQuery = useQuery({
    queryKey: ['movie-perf-search', perfQ],
    queryFn: () => client.listPerformers({ q: perfQ, order: 'scene_count', per_page: 30 }),
    enabled: visible && perfQ.trim().length > 0,
  });
  React.useEffect(() => {
    const items = performersQuery.data?.items;
    if (!items?.length) return;
    setPnames((m) => {
      const next = { ...m };
      for (const p of items) next[p.id] = p.canonical_name;
      return next;
    });
  }, [performersQuery.data]);

  const togglePerformer = (id: string, name: string) => {
    setPnames((m) => ({ ...m, [id]: name }));
    setDraft((d) => ({
      ...d,
      performer_ids: d.performer_ids.includes(id)
        ? d.performer_ids.filter((x) => x !== id)
        : [...d.performer_ids, id],
    }));
  };

  const apply = () => {
    const yf = parseInt(yearFromText, 10);
    const yt = parseInt(yearToText, 10);
    onChange({
      ...draft,
      year_from: Number.isFinite(yf) && yf >= 1900 ? yf : null,
      year_to: Number.isFinite(yt) && yt >= 1900 ? yt : null,
    });
    onClose();
  };

  const reset = () => {
    setDraft(DEFAULT_MOVIE_FILTERS);
    setYearFromText('');
    setYearToText('');
  };

  return (
    <Modal
      visible={visible}
      transparent
      animationType="slide"
      onRequestClose={onClose}
    >
      <KeyboardAvoidingView
        style={styles.backdrop}
        behavior={Platform.OS === 'ios' ? 'padding' : undefined}
      >
        <Pressable style={styles.backdropTap} onPress={onClose} />
        <View style={styles.sheet}>
          <View style={styles.header}>
            <Text style={styles.title}>Filters</Text>
            <TouchableOpacity onPress={reset}>
              <Text style={styles.reset}>Reset</Text>
            </TouchableOpacity>
          </View>

          <ScrollView
            style={styles.body}
            contentContainerStyle={{ paddingBottom: 8 }}
            keyboardShouldPersistTaps="handled"
          >
            <Text style={styles.label}>Sort by</Text>
            <View style={styles.sortRow}>
              {SORT_OPTIONS.map((opt) => {
                const active = draft.sort === opt.value;
                return (
                  <TouchableOpacity
                    key={opt.value}
                    style={[styles.chip, active && styles.chipActive]}
                    onPress={() => setDraft({ ...draft, sort: opt.value })}
                  >
                    <Text style={[styles.chipText, active && styles.chipTextActive]}>
                      {opt.label}
                    </Text>
                  </TouchableOpacity>
                );
              })}
            </View>

            <Text style={styles.label}>Release year</Text>
            <View style={styles.yearRow}>
              <TextInput
                style={[styles.input, { flex: 1 }]}
                value={yearFromText}
                onChangeText={setYearFromText}
                placeholder="from"
                placeholderTextColor={theme.mutedDim}
                keyboardType="number-pad"
                maxLength={4}
              />
              <Text style={styles.dash}>—</Text>
              <TextInput
                style={[styles.input, { flex: 1 }]}
                value={yearToText}
                onChangeText={setYearToText}
                placeholder="to"
                placeholderTextColor={theme.mutedDim}
                keyboardType="number-pad"
                maxLength={4}
              />
            </View>

            <Text style={styles.label}>
              Genres {draft.tag_slugs.length > 0 ? `(${draft.tag_slugs.length})` : ''}
            </Text>
            {tagsQuery.isLoading ? (
              <ActivityIndicator color={theme.muted} style={{ marginVertical: 8 }} />
            ) : tagsQuery.data && tagsQuery.data.items.length > 0 ? (
              <View style={styles.chipRow}>
                {tagsQuery.data.items.map((t) => {
                  const active = draft.tag_slugs.includes(t.slug);
                  return (
                    <TouchableOpacity
                      key={t.id}
                      style={[styles.chip, active && styles.chipActive]}
                      onPress={() => toggleTag(t.slug)}
                    >
                      <Text style={[styles.chipText, active && styles.chipTextActive]}>
                        {t.name}
                        {t.scene_count > 0 ? ` · ${t.scene_count}` : ''}
                      </Text>
                    </TouchableOpacity>
                  );
                })}
              </View>
            ) : (
              <Text style={styles.empty}>no genres yet</Text>
            )}

            <Text style={styles.label}>
              Studios {draft.studio_slugs.length > 0 ? `(${draft.studio_slugs.length})` : ''}
            </Text>
            {studiosQuery.isLoading ? (
              <ActivityIndicator color={theme.muted} style={{ marginVertical: 8 }} />
            ) : studiosQuery.data && studiosQuery.data.items.length > 0 ? (
              <View style={styles.chipRow}>
                {studiosQuery.data.items.map((s) => {
                  const active = draft.studio_slugs.includes(s.slug);
                  return (
                    <TouchableOpacity
                      key={s.id}
                      style={[styles.chip, active && styles.chipActive]}
                      onPress={() => toggleStudio(s.slug)}
                    >
                      <Text style={[styles.chipText, active && styles.chipTextActive]}>
                        {s.name}
                        {s.scene_count > 0 ? ` · ${s.scene_count}` : ''}
                      </Text>
                    </TouchableOpacity>
                  );
                })}
              </View>
            ) : (
              <Text style={styles.empty}>no studios yet</Text>
            )}

            <Text style={styles.label}>
              Performers {draft.performer_ids.length > 0 ? `(${draft.performer_ids.length})` : ''}
            </Text>
            {draft.performer_ids.length > 0 ? (
              <View style={styles.chipRow}>
                {draft.performer_ids.map((id) => (
                  <TouchableOpacity
                    key={id}
                    style={[styles.chip, styles.chipActive]}
                    onPress={() => togglePerformer(id, pnames[id] || '')}
                  >
                    <Text style={[styles.chipText, styles.chipTextActive]}>
                      {pnames[id] || 'performer'} ✕
                    </Text>
                  </TouchableOpacity>
                ))}
              </View>
            ) : null}
            <TextInput
              style={[styles.input, { marginTop: 8 }]}
              value={perfQ}
              onChangeText={setPerfQ}
              placeholder="search performers…"
              placeholderTextColor={theme.mutedDim}
              autoCapitalize="none"
              autoCorrect={false}
            />
            {perfQ.trim().length > 0 ? (
              performersQuery.isLoading ? (
                <ActivityIndicator color={theme.muted} style={{ marginVertical: 8 }} />
              ) : (
                <View style={[styles.chipRow, { marginTop: 8 }]}>
                  {(performersQuery.data?.items ?? [])
                    .filter((p) => !draft.performer_ids.includes(p.id))
                    .map((p) => (
                      <TouchableOpacity
                        key={p.id}
                        style={styles.chip}
                        onPress={() => togglePerformer(p.id, p.canonical_name)}
                      >
                        <Text style={styles.chipText}>
                          {p.canonical_name}
                          {p.scene_count > 0 ? ` · ${p.scene_count}` : ''}
                        </Text>
                      </TouchableOpacity>
                    ))}
                </View>
              )
            ) : null}

            <View style={styles.toggleRow}>
              <Text style={styles.toggleLabel}>Only with playback</Text>
              <Switch
                value={draft.has_playback}
                onValueChange={(v) => setDraft({ ...draft, has_playback: v })}
                thumbColor={draft.has_playback ? theme.accent : theme.muted}
                trackColor={{ true: theme.accentDeep, false: theme.border }}
              />
            </View>
          </ScrollView>

          <View style={styles.btnRow}>
            <TouchableOpacity
              style={[styles.btn, styles.btnCancel]}
              onPress={onClose}
            >
              <Text style={styles.btnText}>Cancel</Text>
            </TouchableOpacity>
            <TouchableOpacity
              style={[styles.btn, styles.btnApply]}
              onPress={apply}
            >
              <Text style={styles.btnText}>Apply</Text>
            </TouchableOpacity>
          </View>
        </View>
      </KeyboardAvoidingView>
    </Modal>
  );
}

export function isDefaultFilters(f: MovieFilters): boolean {
  return (
    f.sort === DEFAULT_MOVIE_FILTERS.sort &&
    f.year_from === null &&
    f.year_to === null &&
    !f.has_playback &&
    f.tag_slugs.length === 0 &&
    f.studio_slugs.length === 0 &&
    f.performer_ids.length === 0
  );
}

const styles = StyleSheet.create({
  backdrop: {
    flex: 1,
    backgroundColor: 'rgba(0,0,0,0.6)',
    justifyContent: 'flex-end',
  },
  backdropTap: { flex: 1 },
  sheet: {
    backgroundColor: theme.bgElevated,
    borderTopLeftRadius: 20,
    borderTopRightRadius: 20,
    padding: 20,
    paddingBottom: 20,
    maxHeight: '88%',
  },
  body: { maxHeight: '85%' },
  header: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 12,
  },
  title: { color: theme.fg, fontSize: 18, fontWeight: '600' },
  reset: { color: theme.accent, fontSize: 14 },
  label: {
    color: theme.muted,
    fontSize: 12,
    fontWeight: '600',
    textTransform: 'uppercase',
    letterSpacing: 0.5,
    marginBottom: 8,
    marginTop: 12,
  },
  sortRow: { flexDirection: 'row', flexWrap: 'wrap', gap: 8 },
  chipRow: { flexDirection: 'row', flexWrap: 'wrap', gap: 6 },
  chip: {
    paddingHorizontal: 12,
    paddingVertical: 7,
    borderRadius: 18,
    borderWidth: 1,
    borderColor: theme.border,
    backgroundColor: theme.card,
  },
  chipActive: {
    backgroundColor: theme.accentDeep,
    borderColor: theme.accent,
  },
  chipText: { color: theme.muted, fontSize: 12 },
  chipTextActive: { color: theme.fg, fontWeight: '600' },
  empty: { color: theme.mutedDim, fontSize: 12, fontStyle: 'italic', marginVertical: 4 },
  yearRow: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 12,
  },
  dash: { color: theme.muted, fontSize: 16 },
  input: {
    backgroundColor: theme.card,
    borderColor: theme.border,
    borderWidth: 1,
    borderRadius: 8,
    color: theme.fg,
    paddingHorizontal: 12,
    paddingVertical: 10,
    fontSize: 14,
  },
  toggleRow: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    paddingVertical: 8,
    marginTop: 12,
  },
  toggleLabel: { color: theme.fg, fontSize: 14 },
  btnRow: { flexDirection: 'row', gap: 12, marginTop: 12 },
  btn: {
    flex: 1,
    paddingVertical: 12,
    borderRadius: 8,
    alignItems: 'center',
  },
  btnCancel: {
    backgroundColor: theme.card,
    borderColor: theme.border,
    borderWidth: 1,
  },
  btnApply: { backgroundColor: theme.accent },
  btnText: { color: theme.fg, fontSize: 15, fontWeight: '600' },
});
