import 'package:superport_v2/core/common/utils/json_utils.dart';

import '../../domain/entities/approval.dart';
import 'approval_audit_dto.dart';

/// 결재 상신(Submit) 요청 DTO.
class ApprovalSubmitRequestDto {
  ApprovalSubmitRequestDto({required this.approval, required this.steps});

  final ApprovalCreatePayloadDto approval;
  final List<ApprovalStepInputDto> steps;

  Map<String, dynamic> toJson() {
    return {
      'approval': approval.toJson(),
      'steps': steps.map((e) => e.toJson()).toList(growable: false),
    };
  }
}

/// 결재 재상신 요청 DTO.
class ApprovalResubmitRequestDto {
  ApprovalResubmitRequestDto({
    required this.approvalId,
    required this.actorId,
    required this.steps,
    this.note,
    this.expectedUpdatedAt,
    this.transactionExpectedUpdatedAt,
  });

  final int approvalId;
  final int actorId;
  final List<ApprovalStepInputDto> steps;
  final String? note;
  final DateTime? expectedUpdatedAt;
  final DateTime? transactionExpectedUpdatedAt;

  Map<String, dynamic> toJson() {
    final sanitizedNote = note?.trim();
    return {
      'approval_id': approvalId,
      'actor_id': actorId,
      'steps': steps.map((e) => e.toJson()).toList(growable: false),
      if (sanitizedNote != null && sanitizedNote.isNotEmpty)
        'note': sanitizedNote,
      if (expectedUpdatedAt != null)
        'expected_updated_at': expectedUpdatedAt!.toUtc().toIso8601String(),
      if (transactionExpectedUpdatedAt != null)
        'transaction_expected_updated_at': transactionExpectedUpdatedAt!
            .toUtc()
            .toIso8601String(),
    };
  }
}

/// 결재 승인/반려 요청 DTO.
class ApprovalDecisionRequestDto {
  ApprovalDecisionRequestDto({
    required this.approvalId,
    required this.actorId,
    this.note,
    this.expectedUpdatedAt,
  });

  final int approvalId;
  final int actorId;
  final String? note;
  final DateTime? expectedUpdatedAt;

  Map<String, dynamic> toJson() {
    final sanitizedNote = note?.trim();
    return {
      'approval_id': approvalId,
      'actor_id': actorId,
      if (sanitizedNote != null && sanitizedNote.isNotEmpty)
        'note': sanitizedNote,
      if (expectedUpdatedAt != null)
        'expected_updated_at': expectedUpdatedAt!.toUtc().toIso8601String(),
    };
  }
}

/// 결재 회수 요청 DTO.
class ApprovalRecallRequestDto {
  ApprovalRecallRequestDto({
    required this.approvalId,
    required this.actorId,
    this.note,
    this.expectedUpdatedAt,
    this.transactionExpectedUpdatedAt,
  });

  final int approvalId;
  final int actorId;
  final String? note;
  final DateTime? expectedUpdatedAt;
  final DateTime? transactionExpectedUpdatedAt;

  Map<String, dynamic> toJson() {
    final sanitizedNote = note?.trim();
    return {
      'approval_id': approvalId,
      'actor_id': actorId,
      if (sanitizedNote != null && sanitizedNote.isNotEmpty)
        'note': sanitizedNote,
      if (expectedUpdatedAt != null)
        'expected_updated_at': expectedUpdatedAt!.toUtc().toIso8601String(),
      if (transactionExpectedUpdatedAt != null)
        'transaction_expected_updated_at': transactionExpectedUpdatedAt!
            .toUtc()
            .toIso8601String(),
    };
  }
}

/// 결재 본문 생성 DTO.
class ApprovalCreatePayloadDto {
  ApprovalCreatePayloadDto({
    this.transactionId,
    this.templateId,
    required this.statusId,
    required this.requesterId,
    this.finalApproverId,
    this.requestedAt,
    this.decidedAt,
    this.cancelledAt,
    this.lastActionAt,
    this.title,
    this.summary,
    this.note,
    this.metadata,
  });

  final int? transactionId;
  final int? templateId;
  final int statusId;
  final int requesterId;
  final int? finalApproverId;
  final DateTime? requestedAt;
  final DateTime? decidedAt;
  final DateTime? cancelledAt;
  final DateTime? lastActionAt;
  final String? title;
  final String? summary;
  final String? note;
  final Map<String, dynamic>? metadata;

  Map<String, dynamic> toJson() {
    final sanitizedNote = note?.trim();
    final sanitizedTitle = title?.trim();
    final sanitizedSummary = summary?.trim();
    return {
      'transaction_id': transactionId,
      'template_id': templateId,
      'approval_status_id': statusId,
      'requested_by_id': requesterId,
      'final_approver_id': finalApproverId,
      if (requestedAt != null)
        'requested_at': requestedAt!.toUtc().toIso8601String(),
      if (decidedAt != null) 'decided_at': decidedAt!.toUtc().toIso8601String(),
      if (cancelledAt != null)
        'cancelled_at': cancelledAt!.toUtc().toIso8601String(),
      if (lastActionAt != null)
        'last_action_at': lastActionAt!.toUtc().toIso8601String(),
      if (sanitizedTitle != null && sanitizedTitle.isNotEmpty)
        'title': sanitizedTitle,
      if (sanitizedSummary != null && sanitizedSummary.isNotEmpty)
        'summary': sanitizedSummary,
      if (sanitizedNote != null && sanitizedNote.isNotEmpty)
        'note': sanitizedNote,
      if (metadata != null && metadata!.isNotEmpty) 'metadata': metadata,
    };
  }

  factory ApprovalCreatePayloadDto.fromSubmission(
    ApprovalSubmissionInput input,
  ) {
    return ApprovalCreatePayloadDto(
      transactionId: input.transactionId,
      templateId: input.templateId,
      statusId: input.statusId,
      requesterId: input.requesterId,
      finalApproverId: input.finalApproverId,
      requestedAt: input.requestedAt,
      decidedAt: input.decidedAt,
      cancelledAt: input.cancelledAt,
      lastActionAt: input.lastActionAt,
      title: input.title,
      summary: input.summary,
      note: input.note,
      metadata: input.metadata,
    );
  }
}

/// 결재 단계 생성 입력 DTO.
class ApprovalStepInputDto {
  ApprovalStepInputDto({
    required this.stepOrder,
    required this.approverId,
    this.note,
  });

  final int stepOrder;
  final int approverId;
  final String? note;

  factory ApprovalStepInputDto.fromDomain(ApprovalStepAssignmentItem item) {
    return ApprovalStepInputDto(
      stepOrder: item.stepOrder,
      approverId: item.approverId,
      note: item.note,
    );
  }

  Map<String, dynamic> toJson() {
    final sanitizedNote = note?.trim();
    return {
      'step_order': stepOrder,
      'approver_id': approverId,
      if (sanitizedNote != null && sanitizedNote.isNotEmpty)
        'note': sanitizedNote,
    };
  }
}

/// 감사 로그 리스트 응답 DTO.
class ApprovalAuditListDto {
  ApprovalAuditListDto({
    required this.items,
    required this.page,
    required this.pageSize,
    required this.total,
  });

  final List<ApprovalAuditDto> items;
  final int page;
  final int pageSize;
  final int total;

  factory ApprovalAuditListDto.fromJson(Map<String, dynamic>? json) {
    final rawItems = JsonUtils.extractList(json, keys: const ['items']);
    final items = rawItems
        .map((item) => ApprovalAuditDto.fromJson(item))
        .toList(growable: false);
    return ApprovalAuditListDto(
      items: items,
      page: JsonUtils.readInt(json, 'page', fallback: 1),
      pageSize: JsonUtils.readInt(json, 'page_size', fallback: items.length),
      total: JsonUtils.readInt(json, 'total', fallback: items.length),
    );
  }
}
