/// Integration tests for Finance Workflow API (Pure Dart - no Flutter binding)
library finance_workflow_api_test;

import 'dart:convert';
import 'package:test/test.dart';
import 'package:http/http.dart' as http;

import 'helpers/test_config.dart';
import 'helpers/auth_helper.dart';

void main() {
  late http.Client client;
  late AuthHelper authHelper;

  setUpAll(() async {
    print('\n╔═══════════════════════════════════════════════╗');
    print('║  Finance Workflow Integration Tests (API)    ║');
    print('╚═══════════════════════════════════════════════╝\n');

    client = http.Client();
    authHelper = AuthHelper(client);

    print('→ Authenticating as ${TestConfig.testOrgAdminUsername}...');
    final authenticated = await authHelper.authenticateAsOrgAdmin();

    if (!authenticated) {
      print('✗ Authentication FAILED');
      throw Exception('Authentication failed - check Keycloak and credentials');
    }

    print('✓ Authentication successful\n');
  });

  tearDownAll(() {
    client.close();
    print('\n╔═══════════════════════════════════════════════╗');
    print('║  Integration Tests Completed                  ║');
    print('╚═══════════════════════════════════════════════╝\n');
  });

  group('Finance Workflow - Approvals API', () {
    test('GET /api/finance/approvals/pending - List pending approvals', () async {
      print('\n[TEST] GET pending approvals...');

      final url = Uri.parse('${TestConfig.apiBaseUrl}/api/finance/approvals/pending')
          .replace(queryParameters: {'organizationId': TestConfig.testOrganizationId});

      final response = await client.get(url, headers: authHelper.getAuthHeaders());

      expect(response.statusCode, equals(200), reason: 'HTTP 200 OK expected');

      final List<dynamic> approvals = json.decode(response.body);
      expect(approvals, isA<List>());

      print('  ✓ Status: ${response.statusCode}');
      print('  ✓ Approvals found: ${approvals.length}');

      await Future.delayed(Duration(milliseconds: TestConfig.delayBetweenTests));
    });

    test('GET /api/finance/approvals/{id} - Get approval by ID', () async {
      print('\n[TEST] GET approval by ID...');

      // First, get list of approvals
      final listUrl = Uri.parse('${TestConfig.apiBaseUrl}/api/finance/approvals/pending')
          .replace(queryParameters: {'organizationId': TestConfig.testOrganizationId});

      final listResponse = await client.get(listUrl, headers: authHelper.getAuthHeaders());
      expect(listResponse.statusCode, equals(200));

      final List<dynamic> approvals = json.decode(listResponse.body);

      if (approvals.isEmpty) {
        print('  ⚠ No pending approvals - test skipped');
        return;
      }

      final approvalId = approvals.first['id'];

      // Get specific approval
      final url = Uri.parse('${TestConfig.apiBaseUrl}/api/finance/approvals/$approvalId');
      final response = await client.get(url, headers: authHelper.getAuthHeaders());

      expect(response.statusCode, equals(200));

      final approval = json.decode(response.body);
      expect(approval['id'], equals(approvalId));

      print('  ✓ Status: ${response.statusCode}');
      print('  ✓ Approval ID: ${approval['id']}');

      await Future.delayed(Duration(milliseconds: TestConfig.delayBetweenTests));
    });
  });

  group('Finance Workflow - Budgets API', () {
    String? createdBudgetId;

    test('GET /api/finance/budgets - List budgets', () async {
      print('\n[TEST] GET budgets list...');

      final url = Uri.parse('${TestConfig.apiBaseUrl}/api/finance/budgets')
          .replace(queryParameters: {'organizationId': TestConfig.testOrganizationId});

      final response = await client.get(url, headers: authHelper.getAuthHeaders());

      expect(response.statusCode, equals(200));

      final List<dynamic> budgets = json.decode(response.body);
      expect(budgets, isA<List>());

      print('  ✓ Status: ${response.statusCode}');
      print('  ✓ Budgets found: ${budgets.length}');

      await Future.delayed(Duration(milliseconds: TestConfig.delayBetweenTests));
    });

    test('POST /api/finance/budgets - Create budget', () async {
      print('\n[TEST] POST create budget...');

      final url = Uri.parse('${TestConfig.apiBaseUrl}/api/finance/budgets');

      final timestamp = DateTime.now().millisecondsSinceEpoch;
      final requestBody = {
        'name': 'Budget Integration Test $timestamp',
        'description': 'Budget created by automated integration test',
        'organizationId': TestConfig.testOrganizationId,
        'period': 'ANNUAL',
        'year': DateTime.now().year,
        'lines': [
          {
            'category': 'CONTRIBUTIONS',
            'name': 'Member Contributions',
            'amountPlanned': 1000000.0,
            'description': 'Monthly member contributions',
          },
          {
            'category': 'SAVINGS',
            'name': 'Savings Deposits',
            'amountPlanned': 500000.0,
            'description': 'Member savings deposits',
          },
        ],
      };

      final response = await client.post(
        url,
        headers: authHelper.getAuthHeaders(),
        body: json.encode(requestBody),
      );

      expect(response.statusCode, inInclusiveRange(200, 201));

      final budget = json.decode(response.body);
      expect(budget['id'], isNotNull);
      expect(budget['name'], contains('Budget Integration Test'));

      createdBudgetId = budget['id'];

      print('  ✓ Status: ${response.statusCode}');
      print('  ✓ Budget created: ${budget['id']}');
      print('  ✓ Budget name: ${budget['name']}');

      await Future.delayed(Duration(milliseconds: TestConfig.delayBetweenTests));
    });

    test('GET /api/finance/budgets/{id} - Get budget by ID', () async {
      print('\n[TEST] GET budget by ID...');

      String budgetId;

      if (createdBudgetId != null) {
        budgetId = createdBudgetId!;
      } else {
        // Fetch any existing budget
        final listUrl = Uri.parse('${TestConfig.apiBaseUrl}/api/finance/budgets')
            .replace(queryParameters: {'organizationId': TestConfig.testOrganizationId});

        final listResponse = await client.get(listUrl, headers: authHelper.getAuthHeaders());
        expect(listResponse.statusCode, equals(200));

        final List<dynamic> budgets = json.decode(listResponse.body);
        if (budgets.isEmpty) {
          print('  ⚠ No budgets found - test skipped');
          return;
        }

        budgetId = budgets.first['id'];
      }

      final url = Uri.parse('${TestConfig.apiBaseUrl}/api/finance/budgets/$budgetId');
      final response = await client.get(url, headers: authHelper.getAuthHeaders());

      expect(response.statusCode, equals(200));

      final budget = json.decode(response.body);
      expect(budget['id'], equals(budgetId));
      expect(budget['lines'], isNotNull);

      print('  ✓ Status: ${response.statusCode}');
      print('  ✓ Budget ID: ${budget['id']}');
      print('  ✓ Budget name: ${budget['name']}');
      print('  ✓ Budget lines: ${budget['lines'].length}');

      await Future.delayed(Duration(milliseconds: TestConfig.delayBetweenTests));
    });
  });

  group('Finance Workflow - Negative Tests', () {
    test('GET nonexistent approval - Should return 404', () async {
      print('\n[TEST] GET nonexistent approval (expect 404)...');

      final fakeId = '00000000-0000-0000-0000-000000000000';
      final url = Uri.parse('${TestConfig.apiBaseUrl}/api/finance/approvals/$fakeId');

      final response = await client.get(url, headers: authHelper.getAuthHeaders());

      expect(response.statusCode, equals(404));

      print('  ✓ Status: ${response.statusCode} (404 as expected)');

      await Future.delayed(Duration(milliseconds: TestConfig.delayBetweenTests));
    });

    test('GET nonexistent budget - Should return 404', () async {
      print('\n[TEST] GET nonexistent budget (expect 404)...');

      final fakeId = '00000000-0000-0000-0000-000000000000';
      final url = Uri.parse('${TestConfig.apiBaseUrl}/api/finance/budgets/$fakeId');

      final response = await client.get(url, headers: authHelper.getAuthHeaders());

      expect(response.statusCode, equals(404));

      print('  ✓ Status: ${response.statusCode} (404 as expected)');

      await Future.delayed(Duration(milliseconds: TestConfig.delayBetweenTests));
    });

    test('POST budget without auth - Should return 401', () async {
      print('\n[TEST] POST budget without authentication (expect 401)...');

      final url = Uri.parse('${TestConfig.apiBaseUrl}/api/finance/budgets');
      final requestBody = {
        'name': 'Unauthorized Budget',
        'organizationId': TestConfig.testOrganizationId,
        'period': 'ANNUAL',
        'year': 2026,
        'lines': [],
      };

      final response = await client.post(
        url,
        headers: {'Content-Type': 'application/json'},
        body: json.encode(requestBody),
      );

      expect(response.statusCode, equals(401));

      print('  ✓ Status: ${response.statusCode} (401 as expected)');

      await Future.delayed(Duration(milliseconds: TestConfig.delayBetweenTests));
    });
  });
}
