import 'package:flutter_test/flutter_test.dart';

import 'package:superport_v2/features/approvals/data/dtos/approval_request_dto.dart';
import 'package:superport_v2/features/approvals/domain/entities/approval.dart';

void main() {
  group('ApprovalSubmitRequestDto', () {
    test('toJson은 상신 본문과 단계를 직렬화한다', () {
      final submission = ApprovalSubmissionInput(
        transactionId: 1001,
        templateId: 55,
        statusId: 7,
        requesterId: 22,
        finalApproverId: 99,
        requestedAt: DateTime.utc(2025, 1, 1, 9, 30),
        lastActionAt: DateTime.utc(2025, 1, 3, 8, 15),
        title: '  결재 제목  ',
        summary: '  결재 요약  ',
        note: '  비고  ',
        metadata: const {'channel': 'web'},
        steps: [
          ApprovalStepAssignmentItem(
            stepOrder: 1,
            approverId: 300,
            note: ' 1차 ',
          ),
        ],
      );

      final dto = ApprovalSubmitRequestDto(
        approval: ApprovalCreatePayloadDto.fromSubmission(submission),
        steps: submission.steps
            .map(ApprovalStepInputDto.fromDomain)
            .toList(growable: false),
      );

      final json = dto.toJson();
      expect(json['approval'], isA<Map<String, dynamic>>());
      expect(json['steps'], isA<List<dynamic>>());
      final approvalJson = json['approval'] as Map<String, dynamic>;
      expect(approvalJson['transaction_id'], 1001);
      expect(approvalJson['template_id'], 55);
      expect(approvalJson['approval_status_id'], 7);
      expect(approvalJson['requested_by_id'], 22);
      expect(approvalJson['final_approver_id'], 99);
      expect(
        approvalJson['requested_at'],
        DateTime.utc(2025, 1, 1, 9, 30).toIso8601String(),
      );
      expect(approvalJson.containsKey('decided_at'), isFalse);
      expect(
        approvalJson['last_action_at'],
        DateTime.utc(2025, 1, 3, 8, 15).toIso8601String(),
      );
      expect(approvalJson['title'], '결재 제목');
      expect(approvalJson['summary'], '결재 요약');
      expect(approvalJson['note'], '비고');
      expect(approvalJson['metadata'], {'channel': 'web'});

      final steps = json['steps'] as List<dynamic>;
      expect(steps, hasLength(1));
      final stepJson = steps.first as Map<String, dynamic>;
      expect(stepJson['step_order'], 1);
      expect(stepJson['approver_id'], 300);
      expect(stepJson['note'], '1차');
    });
  });

  group('ApprovalResubmitRequestDto', () {
    test('toJson은 옵션 필드와 타임스탬프를 포함한다', () {
      final dto = ApprovalResubmitRequestDto(
        approvalId: 700,
        actorId: 123,
        steps: [
          ApprovalStepInputDto(stepOrder: 1, approverId: 45, note: '  의견 '),
        ],
        note: '  재상신 ',
        expectedUpdatedAt: DateTime.utc(2025, 2, 1, 10, 0),
        transactionExpectedUpdatedAt: DateTime.utc(2025, 2, 1, 11, 0),
      );

      final json = dto.toJson();
      expect(json['approval_id'], 700);
      expect(json['actor_id'], 123);
      expect(json['note'], '재상신');
      expect(
        json['expected_updated_at'],
        DateTime.utc(2025, 2, 1, 10, 0).toIso8601String(),
      );
      expect(
        json['transaction_expected_updated_at'],
        DateTime.utc(2025, 2, 1, 11, 0).toIso8601String(),
      );
      final steps = json['steps'] as List<dynamic>;
      expect(steps, hasLength(1));
      expect((steps.first as Map<String, dynamic>)['note'], '의견');
    });
  });

  group('ApprovalRecallRequestDto', () {
    test('회수 요청은 메모가 없으면 note를 누락한다', () {
      final dto = ApprovalRecallRequestDto(
        approvalId: 501,
        actorId: 88,
        expectedUpdatedAt: DateTime.utc(2025, 3, 1, 12, 0),
        transactionExpectedUpdatedAt: DateTime.utc(2025, 3, 1, 13, 0),
      );

      final json = dto.toJson();
      expect(json['approval_id'], 501);
      expect(json['actor_id'], 88);
      expect(json.containsKey('note'), isFalse);
      expect(
        json['expected_updated_at'],
        DateTime.utc(2025, 3, 1, 12, 0).toIso8601String(),
      );
      expect(
        json['transaction_expected_updated_at'],
        DateTime.utc(2025, 3, 1, 13, 0).toIso8601String(),
      );
    });
  });

  group('ApprovalDecisionRequestDto', () {
    test('toJson은 비어 있는 메모를 포함하지 않는다', () {
      final dto = ApprovalDecisionRequestDto(
        approvalId: 301,
        actorId: 44,
        note: '  ',
      );

      final json = dto.toJson();
      expect(json['approval_id'], 301);
      expect(json['actor_id'], 44);
      expect(json.containsKey('note'), isFalse);
    });
  });
}
