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

import 'package:superport_v2/core/network/api_error.dart';
import 'package:superport_v2/core/network/failure.dart';

void main() {
  group('FailureParser', () {
    test('ApiException에서 메시지·필드 오류를 추출한다', () {
      final requestOptions = RequestOptions(path: '/test');
      final dioException = DioException(
        requestOptions: requestOptions,
        type: DioExceptionType.badResponse,
        response: Response<dynamic>(
          requestOptions: requestOptions,
          statusCode: 422,
          data: {
            'error': {
              'message': '입력값을 확인해 주세요.',
              'details': [
                {'field': 'quantity', 'message': '수량은 1 이상 입력해야 합니다.'},
                {'field': 'general', 'message': '재고 상태가 출고 불가 상태입니다.'},
              ],
            },
          },
        ),
      );

      final exception = ApiException(
        code: ApiErrorCode.unprocessableEntity,
        message: '요청 처리 중 오류가 발생했습니다.',
        statusCode: 422,
        cause: dioException,
      );

      final failure = Failure.from(exception);

      expect(failure.message, '입력값을 확인해 주세요.');
      expect(failure.fieldErrors['quantity'], isNotNull);
      expect(failure.fieldErrors['quantity'], contains('수량은 1 이상 입력해야 합니다.'));
      final description = failure.describe();
      expect(description, contains('입력값을 확인해 주세요.'));
      expect(description, contains('quantity: 수량은 1 이상 입력해야 합니다.'));
      expect(description, contains('재고 상태가 출고 불가 상태입니다.'));
    });

    test('일반 Exception은 접두사를 제거한 메시지를 반환한다', () {
      final exception = Exception('네트워크 오류');

      final failure = Failure.from(exception);

      expect(failure.message, '네트워크 오류');
      expect(failure.describe(), '네트워크 오류');
    });

    test('필드 오류만 존재해도 describe에 요약이 포함된다', () {
      final exception = ApiException(
        code: ApiErrorCode.badRequest,
        message: '잘못된 요청입니다.',
        details: {
          'approval_id': ['결재 ID를 입력하세요.'],
          'step_order': ['단계 순서를 입력하세요.'],
        },
      );

      final failure = Failure.from(exception);

      expect(failure.fieldErrors.keys, contains('approval_id'));
      final summary = failure.describe();
      expect(summary, contains('approval_id: 결재 ID를 입력하세요.'));
      expect(summary, contains('step_order: 단계 순서를 입력하세요.'));
    });
  });

  test('권한 오류에서 코드·메시지·세부 정보를 추출한다', () {
    final requestOptions = RequestOptions(
      path: '/stock-transactions/42/approve',
    );
    final dioException = DioException(
      requestOptions: requestOptions,
      type: DioExceptionType.badResponse,
      response: Response<dynamic>(
        requestOptions: requestOptions,
        statusCode: 403,
        data: {
          'error': {
            'code': 'permission_denied',
            'message': '승인 권한이 없습니다.',
            'reasons': ['결재 관리자만 승인할 수 있습니다.'],
            'context': {'resource': 'stock-transactions', 'action': 'approve'},
          },
        },
      ),
    );

    final failure = Failure.from(dioException);

    expect(failure.code, ApiErrorCode.forbidden);
    expect(failure.message, '승인 권한이 없습니다.');
    expect(failure.reasons, contains('결재 관리자만 승인할 수 있습니다.'));
    expect(failure.fieldErrors['action'], isNotNull);
    expect(failure.fieldErrors['action'], contains('approve'));
    final description = failure.describe();
    expect(description, contains('승인 권한이 없습니다.'));
    expect(description, contains('action: approve'));
  });
}
