import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:tane/i18n/strings.g.dart';
import 'package:tane/services/coarse_location.dart';
import 'package:tane/services/social_connection.dart';
import 'package:tane/services/social_service.dart';
import 'package:tane/services/social_settings.dart';
import 'package:tane/state/offers_cubit.dart';
import 'package:tane/ui/market_screen.dart';

import '../support/test_support.dart';

// NOTE: discovery/offer-list rendering is covered by offers_cubit_test.dart
// (plain `test` + pumpEventQueue). We deliberately do NOT drive discovery
// through `testWidgets` here: the transient "searching" CircularProgressIndicator
// never settles under pumpAndSettle and hangs the runner. These widget tests
// only cover the offline/setup paths, which have no live stream.

/// A location provider returning a fixed coarse position.
class FakeLocation implements CoarseLocationProvider {
  FakeLocation(this.lat, this.lon);
  final double lat;
  final double lon;
  @override
  Future<({double lat, double lon})?> currentCoarseLatLon() async =>
      (lat: lat, lon: lon);
}

Widget _wrapBody(OffersCubit cubit) {
  LocaleSettings.setLocaleSync(AppLocale.en);
  return TranslationProvider(
    child: MaterialApp(
      locale: AppLocale.en.flutterLocale,
      supportedLocales: AppLocaleUtils.supportedLocales,
      localizationsDelegates: const [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      home: Scaffold(
        body: BlocProvider.value(
          value: cubit,
          child: MarketBody(onConfigure: () {}),
        ),
      ),
    ),
  );
}

Widget _wrapMarket(SocialService social, SocialSettings settings,
    {CoarseLocationProvider? location}) {
  LocaleSettings.setLocaleSync(AppLocale.en);
  return TranslationProvider(
    child: MaterialApp(
      locale: AppLocale.en.flutterLocale,
      supportedLocales: AppLocaleUtils.supportedLocales,
      localizationsDelegates: const [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      home: MarketScreen(
        social: social,
        settings: settings,
        connection: SocialConnection(social: social, settings: settings),
        location: location,
      ),
    ),
  );
}

void main() {
  testWidgets('offline (no transport) shows the "can\'t reach servers" state',
      (tester) async {
    final cubit = OffersCubit(null);
    addTearDown(cubit.close);

    await tester.pumpWidget(_wrapBody(cubit));
    await tester.pumpAndSettle();

    expect(find.textContaining("Can't reach the community servers"),
        findsOneWidget);
  });

  testWidgets('MarketScreen with no relays configured degrades to offline',
      (tester) async {
    final social = await SocialService.fromRootSeedHex('00' * 32);
    final settings = SocialSettings(InMemorySecretStore());
    await settings.setRelayUrls(const []); // offline: don't hit the network

    await tester.pumpWidget(_wrapMarket(social, settings));
    await tester.pumpAndSettle();

    expect(find.text('Seeds near you'), findsOneWidget); // app bar title
    expect(find.text('Retry'), findsOneWidget); // can't-reach state offers retry
  });

  testWidgets('the range selector persists the chosen search precision',
      (tester) async {
    final social = await SocialService.fromRootSeedHex('00' * 32);
    final settings = SocialSettings(InMemorySecretStore());
    await settings.setRelayUrls(const []); // offline: don't hit the network

    await tester.pumpWidget(_wrapMarket(social, settings));
    await tester.pumpAndSettle();

    await tester.tap(find.byKey(const Key('market.config')));
    await tester.pumpAndSettle();

    // Defaults to the wide "Around here" (precision 4); narrow to "My region".
    expect(await settings.searchPrecision(), 4);
    await tester.tap(find.text('My region'));
    await tester.pumpAndSettle();
    await tester.tap(find.byKey(const Key('market.save')));
    await tester.pumpAndSettle();

    expect(await settings.searchPrecision(), 3);
  });

  testWidgets('"use my location" fills the area with a coarse geohash',
      (tester) async {
    final social = await SocialService.fromRootSeedHex('00' * 32);
    final settings = SocialSettings(InMemorySecretStore());
    await settings.setRelayUrls(const []); // offline: don't hit the network

    await tester.pumpWidget(
      _wrapMarket(social, settings, location: FakeLocation(41.39, 2.16)),
    );
    await tester.pumpAndSettle();

    await tester.tap(find.byKey(const Key('market.config')));
    await tester.pumpAndSettle();
    await tester.tap(find.byKey(const Key('market.useLocation')));
    await tester.pumpAndSettle();

    // The area status flips to "set" once a coarse location is captured.
    expect(find.textContaining('Your area is set'), findsOneWidget);
  });
}
