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_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, location: location),
    ),
  );
}

void main() {
  testWidgets('offline (no transport) shows the "set up sharing" prompt',
      (tester) async {
    final cubit = OffersCubit(null);
    addTearDown(cubit.close);

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

    expect(find.text("Sharing isn't set up yet"), findsOneWidget);
    expect(find.text('Set up sharing'), 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('Set up sharing'), findsOneWidget); // offline prompt
  });

  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();

    final area = tester.widget<TextField>(find.byKey(const Key('market.area')));
    expect(area.controller!.text, hasLength(5));
    expect(area.controller!.text, matches(RegExp(r'^[0-9a-z]+$')));
  });
}
