import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:flutter_test/flutter_test.dart';

import 'package:appsok/src/services/jenkins_client.dart';
import 'package:appsok/src/services/token_store.dart';

void main() {
  setUp(() {
    FlutterSecureStorage.setMockInitialValues({});
  });

  group('TokenStore.readSession', () {
    test('readSession returns null when config is incomplete', () async {
      final store = TokenStore();
      expect(await store.readSession(), isNull);
    });

    test('readSession returns null when only credentials are stored', () async {
      FlutterSecureStorage.setMockInitialValues({
        'jenkins.username': 'ada',
        'jenkins.apiToken': 'tok',
      });
      final store = TokenStore();
      expect(await store.readSession(), isNull);
    });

    test('readSession returns null when base url is invalid', () async {
      FlutterSecureStorage.setMockInitialValues({
        'jenkins.baseUrl': ':::not-a-url:::',
        'jenkins.username': 'ada',
        'jenkins.apiToken': 'tok',
      });
      final store = TokenStore();
      expect(await store.readSession(), isNull);
    });

    test('saveSession and readSession round trip base url and credentials',
        () async {
      final store = TokenStore();
      final session = JenkinsSessionConfig(
        baseUrl: Uri.parse('https://jenkins.example/'),
        credentials: const JenkinsCredentials(
          username: 'ada',
          apiToken: 'secret',
        ),
      );

      await store.saveSession(session);
      final result = await store.readSession();

      expect(result, isNotNull);
      expect(result!.baseUrl, Uri.parse('https://jenkins.example/'));
      expect(result.credentials.username, 'ada');
      expect(result.credentials.apiToken, 'secret');
    });

    test('clearSession removes base url and credentials', () async {
      final store = TokenStore();
      final session = JenkinsSessionConfig(
        baseUrl: Uri.parse('https://jenkins.example/'),
        credentials: const JenkinsCredentials(
          username: 'ada',
          apiToken: 'secret',
        ),
      );

      await store.saveSession(session);
      await store.clearSession();
      expect(await store.readSession(), isNull);
    });
  });

  group('TokenStore.saveSession atomicity', () {
    test('saveSession overwrites all three keys atomically', () async {
      final store = TokenStore();
      // Save first session
      await store.saveSession(
        JenkinsSessionConfig(
          baseUrl: Uri.parse('https://jenkins.first/'),
          credentials: const JenkinsCredentials(
            username: 'first',
            apiToken: 'token-first',
          ),
        ),
      );
      // Overwrite with second session
      await store.saveSession(
        JenkinsSessionConfig(
          baseUrl: Uri.parse('https://jenkins.second/'),
          credentials: const JenkinsCredentials(
            username: 'second',
            apiToken: 'token-second',
          ),
        ),
      );
      final result = await store.readSession();
      expect(result, isNotNull);
      expect(result!.baseUrl, Uri.parse('https://jenkins.second/'));
      expect(result.credentials.username, 'second');
      expect(result.credentials.apiToken, 'token-second');
    });

    test('clearSession after saveSession returns null for readSession', () async {
      final store = TokenStore();
      await store.saveSession(
        JenkinsSessionConfig(
          baseUrl: Uri.parse('https://jenkins.example/'),
          credentials: const JenkinsCredentials(
            username: 'user',
            apiToken: 'tok',
          ),
        ),
      );
      await store.clearSession();
      expect(await store.readSession(), isNull);
    });
  });

  group('TokenStore.readCredentials backward compatibility', () {
    test('readCredentials remains backward compatible', () async {
      final store = TokenStore();
      await store.saveCredentials(
        const JenkinsCredentials(username: 'grace', apiToken: 'tok2'),
      );

      final result = await store.readCredentials();
      expect(result, isNotNull);
      expect(result!.username, 'grace');
      expect(result.apiToken, 'tok2');
    });

    test('readCredentials returns null when nothing is stored', () async {
      final store = TokenStore();
      expect(await store.readCredentials(), isNull);
    });

    test('clearCredentials removes username and token', () async {
      final store = TokenStore();
      await store.saveCredentials(
        const JenkinsCredentials(username: 'grace', apiToken: 'tok2'),
      );
      await store.clearCredentials();
      expect(await store.readCredentials(), isNull);
    });
  });
}
