import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

import 'package:appsok/src/features/settings/settings_page.dart';
import 'package:appsok/src/theme/app_theme.dart';

Widget _wrap(Widget child) => MaterialApp(
  theme: AppTheme.light(),
  home: Scaffold(body: child),
);

void main() {
  group('SettingsPage web login', () {
    testWidgets('disables web login for invalid Jenkins URL', (tester) async {
      await tester.pumpWidget(_wrap(const SettingsPage()));

      final button = tester.widget<ElevatedButton>(
        find.byKey(const ValueKey('jenkins-web-login-button')),
      );
      expect(button.onPressed, isNull);

      // Empty URL — still disabled
      await tester.enterText(find.byType(TextField).first, '');
      await tester.pump();
      final buttonAfterEmpty = tester.widget<ElevatedButton>(
        find.byKey(const ValueKey('jenkins-web-login-button')),
      );
      expect(buttonAfterEmpty.onPressed, isNull);

      // Non-URL text — still disabled
      await tester.enterText(find.byType(TextField).first, 'not-a-url');
      await tester.pump();
      final buttonAfterInvalid = tester.widget<ElevatedButton>(
        find.byKey(const ValueKey('jenkins-web-login-button')),
      );
      expect(buttonAfterInvalid.onPressed, isNull);
    });

    testWidgets('calls web login launcher with normalized base URL', (
      tester,
    ) async {
      String? capturedUrl;
      await tester.pumpWidget(
        _wrap(
          SettingsPage(
            webLoginLauncher: (url) async {
              capturedUrl = url;
              return null;
            },
          ),
        ),
      );

      await tester.enterText(
        find.byType(TextField).first,
        'https://jenkins.example.com',
      );
      await tester.pump();

      final button = tester.widget<ElevatedButton>(
        find.byKey(const ValueKey('jenkins-web-login-button')),
      );
      expect(button.onPressed, isNotNull);

      await tester.tap(find.byKey(const ValueKey('jenkins-web-login-button')));
      await tester.pumpAndSettle();

      expect(capturedUrl, 'https://jenkins.example.com');
    });

    testWidgets('shows completed login user without token text', (
      tester,
    ) async {
      await tester.pumpWidget(
        _wrap(
          SettingsPage(
            webLoginLauncher: (_) async => const JenkinsWebLoginResult(
              username: 'toki',
              displayName: 'Toki Lab',
              apiToken: 'issued-token',
            ),
          ),
        ),
      );

      await tester.enterText(
        find.byType(TextField).first,
        'https://jenkins.example.com',
      );
      await tester.pump();

      await tester.tap(find.byKey(const ValueKey('jenkins-web-login-button')));
      await tester.pumpAndSettle();

      // Result label must show displayName
      expect(find.byKey(const ValueKey('web-login-result')), findsOneWidget);
      expect(find.textContaining('Toki Lab'), findsOneWidget);
      // No token-like text should appear
      expect(find.textContaining('token'), findsNothing);
      expect(find.textContaining('apiToken'), findsNothing);
    });

    testWidgets('shows token issue error when web login returns no apiToken', (
      tester,
    ) async {
      await tester.pumpWidget(
        _wrap(
          SettingsPage(
            webLoginLauncher: (_) async => const JenkinsWebLoginResult(
              username: 'toki',
              displayName: 'Toki Lab',
            ),
          ),
        ),
      );

      await tester.enterText(
        find.byType(TextField).first,
        'https://jenkins.example.com',
      );
      await tester.pump();

      await tester.tap(find.byKey(const ValueKey('jenkins-web-login-button')));
      await tester.pumpAndSettle();

      expect(find.byKey(const ValueKey('web-login-result')), findsNothing);
      expect(find.textContaining('API token 발급에 실패했습니다'), findsOneWidget);
    });

    testWidgets('clears stored credential through sessionClearer', (
      tester,
    ) async {
      var clearCalled = false;

      await tester.pumpWidget(
        _wrap(
          SettingsPage(
            sessionClearer: () async {
              clearCalled = true;
            },
          ),
        ),
      );

      await tester.tap(
        find.byKey(const ValueKey('jenkins-clear-session-button')),
      );
      await tester.pumpAndSettle();

      expect(clearCalled, isTrue);
      expect(
        find.byKey(const ValueKey('session-cleared-label')),
        findsOneWidget,
      );
      expect(find.byKey(const ValueKey('session-clear-error')), findsNothing);
    });
  });

  group('SettingsPage base URL change clears transient state', () {
    testWidgets(
      'SettingsPage clears transient login/save/clear state when base url changes',
      (tester) async {
        await tester.pumpWidget(
          _wrap(
            SettingsPage(
              webLoginLauncher: (url) async => const JenkinsWebLoginResult(
                username: 'toki',
                displayName: 'Toki Lab',
                apiToken: 'issued-token',
              ),
              tokenSaver: (baseUrl, username, apiToken) async => true,
              onSessionSaved: () {},
            ),
          ),
        );

        // Enter a valid URL and trigger web login so token-saved-label appears.
        await tester.enterText(
          find.byType(TextField).first,
          'https://jenkins.example.com',
        );
        await tester.pump();

        await tester.tap(
          find.byKey(const ValueKey('jenkins-web-login-button')),
        );
        await tester.pumpAndSettle();

        expect(find.byKey(const ValueKey('token-saved-label')), findsOneWidget);

        // Change URL — all transient labels must be cleared.
        await tester.enterText(
          find.byType(TextField).first,
          'https://jenkins2.example.com',
        );
        await tester.pump();

        expect(find.byKey(const ValueKey('token-saved-label')), findsNothing);
        expect(find.byKey(const ValueKey('web-login-result')), findsNothing);
        expect(find.byKey(const ValueKey('token-save-error')), findsNothing);
        expect(
          find.byKey(const ValueKey('session-cleared-label')),
          findsNothing,
        );
      },
    );
  });
}
