import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';

import '../cart/cart_state.dart';

/// Discovery filters. A class (not a record) so the many optional filters can be
/// changed one at a time via copyWith without re-listing every field.
class DiscoverFilters {
  const DiscoverFilters({
    this.q,
    this.minRating,
    this.sort = 'rating',
    this.openNow = false,
    this.priceTier,
    this.themes = const [],
    this.vibes = const [],
    this.occasions = const [],
    this.spaceFeatures = const [],
  });

  final String? q;
  final double? minRating;
  final String sort;
  final bool openNow;
  final String? priceTier;
  final List<String> themes;
  final List<String> vibes;
  final List<String> occasions;
  final List<String> spaceFeatures;

  int get activeCount =>
      (minRating != null ? 1 : 0) +
      (openNow ? 1 : 0) +
      (priceTier != null ? 1 : 0) +
      themes.length +
      vibes.length +
      occasions.length +
      spaceFeatures.length;

  DiscoverFilters copyWith({
    ValueGetter<String?>? q,
    ValueGetter<double?>? minRating,
    String? sort,
    bool? openNow,
    ValueGetter<String?>? priceTier,
    List<String>? themes,
    List<String>? vibes,
    List<String>? occasions,
    List<String>? spaceFeatures,
  }) {
    return DiscoverFilters(
      q: q != null ? q() : this.q,
      minRating: minRating != null ? minRating() : this.minRating,
      sort: sort ?? this.sort,
      openNow: openNow ?? this.openNow,
      priceTier: priceTier != null ? priceTier() : this.priceTier,
      themes: themes ?? this.themes,
      vibes: vibes ?? this.vibes,
      occasions: occasions ?? this.occasions,
      spaceFeatures: spaceFeatures ?? this.spaceFeatures,
    );
  }
}

final discoverFiltersProvider =
    StateProvider<DiscoverFilters>((_) => const DiscoverFilters());

final discoverProvider =
    FutureProvider.autoDispose<List<Map<String, dynamic>>>((ref) {
  final f = ref.watch(discoverFiltersProvider);
  return ref.watch(publicApiProvider).discover(
        city: 'تهران',
        q: f.q,
        minRating: f.minRating,
        sort: f.sort,
        openNow: f.openNow,
        priceTier: f.priceTier,
        themes: f.themes,
        vibes: f.vibes,
        occasions: f.occasions,
        spaceFeatures: f.spaceFeatures,
      );
});

/// Available themes/vibes/occasions/spaceFeatures for the filter sheet.
final discoverTaxonomyProvider =
    FutureProvider.autoDispose<Map<String, dynamic>?>((ref) {
  return ref.watch(publicApiProvider).discoverTaxonomy();
});

class DiscoverScreen extends ConsumerStatefulWidget {
  const DiscoverScreen({super.key});

  @override
  ConsumerState<DiscoverScreen> createState() => _DiscoverScreenState();
}

class _DiscoverScreenState extends ConsumerState<DiscoverScreen> {
  final _searchController = TextEditingController();

  @override
  void dispose() {
    _searchController.dispose();
    super.dispose();
  }

  void _applySearch() {
    final q = _searchController.text.trim();
    ref.read(discoverFiltersProvider.notifier).update(
          (s) => s.copyWith(q: () => q.isEmpty ? null : q),
        );
  }

  Future<void> _openFilters() async {
    await showModalBottomSheet<void>(
      context: context,
      isScrollControlled: true,
      showDragHandle: true,
      builder: (_) => const _DiscoverFilterSheet(),
    );
  }

  @override
  Widget build(BuildContext context) {
    final cafesAsync = ref.watch(discoverProvider);
    final filters = ref.watch(discoverFiltersProvider);

    return Directionality(
      textDirection: TextDirection.rtl,
      child: Scaffold(
        appBar: AppBar(
          title: const Text('کافه‌یاب میزی'),
          actions: [
            IconButton(
              icon: const Icon(Icons.qr_code_scanner),
              onPressed: () => context.push('/qr'),
            ),
          ],
        ),
        body: Column(
          children: [
            Padding(
              padding: const EdgeInsets.fromLTRB(16, 16, 16, 8),
              child: Row(
                children: [
                  Expanded(
                    child: TextField(
                      controller: _searchController,
                      decoration: InputDecoration(
                        hintText: 'کافه دنج برای کار، نزدیک من...',
                        isDense: true,
                        prefixIcon: const Icon(Icons.search),
                        suffixIcon: IconButton(
                          icon: const Icon(Icons.arrow_back),
                          onPressed: _applySearch,
                        ),
                      ),
                      textInputAction: TextInputAction.search,
                      onSubmitted: (_) => _applySearch(),
                    ),
                  ),
                  const SizedBox(width: 8),
                  Badge(
                    isLabelVisible: filters.activeCount > 0,
                    label: Text('${filters.activeCount}'),
                    child: IconButton.filledTonal(
                      icon: const Icon(Icons.tune),
                      onPressed: _openFilters,
                    ),
                  ),
                ],
              ),
            ),
            SingleChildScrollView(
              scrollDirection: Axis.horizontal,
              padding: const EdgeInsets.symmetric(horizontal: 16),
              child: Row(
                children: [
                  FilterChip(
                    label: const Text('باز است'),
                    selected: filters.openNow,
                    onSelected: (v) => ref
                        .read(discoverFiltersProvider.notifier)
                        .update((s) => s.copyWith(openNow: v)),
                  ),
                  const SizedBox(width: 8),
                  FilterChip(
                    label: const Text('همه امتیازها'),
                    selected: filters.minRating == null,
                    onSelected: (_) => ref
                        .read(discoverFiltersProvider.notifier)
                        .update((s) => s.copyWith(minRating: () => null)),
                  ),
                  for (final min in [3.0, 4.0, 4.5])
                    Padding(
                      padding: const EdgeInsets.only(right: 8),
                      child: FilterChip(
                        label: Text('★ $min+'),
                        selected: filters.minRating == min,
                        onSelected: (_) => ref
                            .read(discoverFiltersProvider.notifier)
                            .update((s) => s.copyWith(minRating: () => min)),
                      ),
                    ),
                ],
              ),
            ),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
              child: DropdownButtonFormField<String>(
                initialValue: filters.sort,
                decoration: const InputDecoration(
                  labelText: 'مرتب‌سازی',
                  isDense: true,
                ),
                items: const [
                  DropdownMenuItem(value: 'rating', child: Text('بیشترین امتیاز')),
                  DropdownMenuItem(value: 'reviews', child: Text('بیشترین نظر')),
                  DropdownMenuItem(value: 'name', child: Text('نام')),
                ],
                onChanged: (sort) {
                  if (sort == null) return;
                  ref
                      .read(discoverFiltersProvider.notifier)
                      .update((s) => s.copyWith(sort: sort));
                },
              ),
            ),
            Expanded(
              child: cafesAsync.when(
                data: (cafes) {
                  if (cafes.isEmpty) {
                    return const Center(child: Text('کافه‌ای یافت نشد'));
                  }
                  return RefreshIndicator(
                    onRefresh: () async => ref.refresh(discoverProvider.future),
                    child: ListView.separated(
                      padding: const EdgeInsets.all(16),
                      itemCount: cafes.length,
                      separatorBuilder: (_, __) => const SizedBox(height: 8),
                      itemBuilder: (context, index) =>
                          _CafeCard(cafe: cafes[index]),
                    ),
                  );
                },
                loading: () =>
                    const Center(child: CircularProgressIndicator()),
                error: (e, _) => Center(child: Text('خطا: $e')),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class _CafeCard extends StatelessWidget {
  const _CafeCard({required this.cafe});
  final Map<String, dynamic> cafe;

  @override
  Widget build(BuildContext context) {
    final slug = cafe['slug'] as String;
    final name = cafe['name'] as String? ?? slug;
    final avg = (cafe['averageRating'] as num?)?.toDouble() ?? 0;
    final count = cafe['reviewCount'] as int? ?? 0;
    final address = cafe['address'] as String?;
    final isOpen = cafe['isOpenNow'] as bool?;
    return Card(
      child: ListTile(
        title: Row(
          children: [
            Expanded(child: Text(name)),
            if (isOpen != null)
              Text(
                isOpen ? 'باز' : 'بسته',
                style: TextStyle(
                  fontSize: 12,
                  color: isOpen ? Colors.green : Colors.red,
                ),
              ),
          ],
        ),
        subtitle: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(cafe['city'] as String? ?? ''),
            if (address != null && address.isNotEmpty) Text(address),
            Text('★ ${avg.toStringAsFixed(1)} · $count نظر'),
          ],
        ),
        trailing: const Icon(Icons.chevron_left),
        onTap: () => context.push('/cafe/$slug'),
      ),
    );
  }
}

class _DiscoverFilterSheet extends ConsumerWidget {
  const _DiscoverFilterSheet();

  static const _priceTiers = [
    ('budget', 'اقتصادی'),
    ('moderate', 'متوسط'),
    ('upscale', 'لاکچری'),
    ('luxury', 'بسیار لاکچری'),
  ];

  List<({String key, String label})> _parseTax(dynamic raw) {
    if (raw is! List) return const [];
    return raw
        .map<({String key, String label})>((e) {
          if (e is Map) {
            final k = (e['key'] ?? e['value'] ?? e['id'] ?? '').toString();
            final l = (e['labelFa'] ?? e['label'] ?? e['nameFa'] ?? e['name'] ?? k)
                .toString();
            return (key: k, label: l);
          }
          final s = e.toString();
          return (key: s, label: s);
        })
        .where((t) => t.key.isNotEmpty)
        .toList();
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final filters = ref.watch(discoverFiltersProvider);
    final taxonomy = ref.watch(discoverTaxonomyProvider);
    final notifier = ref.read(discoverFiltersProvider.notifier);

    Widget chips(String title, List<({String key, String label})> items,
        List<String> selected, void Function(List<String>) onChange) {
      if (items.isEmpty) return const SizedBox.shrink();
      return Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Padding(
            padding: const EdgeInsets.fromLTRB(0, 12, 0, 6),
            child: Text(title, style: Theme.of(context).textTheme.titleSmall),
          ),
          Wrap(
            spacing: 8,
            runSpacing: 4,
            children: [
              for (final it in items)
                FilterChip(
                  label: Text(it.label),
                  selected: selected.contains(it.key),
                  onSelected: (v) {
                    final next = List<String>.from(selected);
                    if (v) {
                      next.add(it.key);
                    } else {
                      next.remove(it.key);
                    }
                    onChange(next);
                  },
                ),
            ],
          ),
        ],
      );
    }

    return Directionality(
      textDirection: TextDirection.rtl,
      child: Padding(
        padding: EdgeInsets.fromLTRB(
          16,
          0,
          16,
          16 + MediaQuery.of(context).viewInsets.bottom,
        ),
        child: SingleChildScrollView(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Row(
                children: [
                  Text('فیلترها',
                      style: Theme.of(context).textTheme.titleLarge),
                  const Spacer(),
                  if (filters.activeCount > 0)
                    TextButton(
                      onPressed: () =>
                          notifier.state = const DiscoverFilters(),
                      child: const Text('پاک کردن'),
                    ),
                ],
              ),
              SwitchListTile(
                contentPadding: EdgeInsets.zero,
                title: const Text('فقط کافه‌های باز'),
                value: filters.openNow,
                onChanged: (v) => notifier.update((s) => s.copyWith(openNow: v)),
              ),
              const Padding(
                padding: EdgeInsets.fromLTRB(0, 8, 0, 6),
                child: Text('محدوده قیمت'),
              ),
              Wrap(
                spacing: 8,
                children: [
                  for (final p in _priceTiers)
                    ChoiceChip(
                      label: Text(p.$2),
                      selected: filters.priceTier == p.$1,
                      onSelected: (v) => notifier.update(
                        (s) => s.copyWith(priceTier: () => v ? p.$1 : null),
                      ),
                    ),
                ],
              ),
              taxonomy.when(
                data: (tax) {
                  if (tax == null) return const SizedBox.shrink();
                  return Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      chips('فضا و حال‌وهوا', _parseTax(tax['themes']),
                          filters.themes,
                          (v) => notifier.update((s) => s.copyWith(themes: v))),
                      chips('وایب', _parseTax(tax['vibes']), filters.vibes,
                          (v) => notifier.update((s) => s.copyWith(vibes: v))),
                      chips('مناسبت', _parseTax(tax['occasions']),
                          filters.occasions,
                          (v) => notifier.update((s) => s.copyWith(occasions: v))),
                      chips('امکانات', _parseTax(tax['spaceFeatures']),
                          filters.spaceFeatures,
                          (v) => notifier.update(
                              (s) => s.copyWith(spaceFeatures: v))),
                    ],
                  );
                },
                loading: () => const Padding(
                  padding: EdgeInsets.all(16),
                  child: Center(child: CircularProgressIndicator()),
                ),
                error: (_, __) => const SizedBox.shrink(),
              ),
              const SizedBox(height: 16),
              SizedBox(
                width: double.infinity,
                child: FilledButton(
                  onPressed: () => Navigator.of(context).pop(),
                  child: const Text('نمایش نتایج'),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
