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

import '../../domain/entities/approval_draft.dart';

/// 결재 초안 단계 DTO.
class ApprovalDraftStepDto {
  ApprovalDraftStepDto({
    required this.stepOrder,
    required this.approverId,
    this.approverRole,
    this.note,
    this.isOptional = false,
  });

  final int stepOrder;
  final int approverId;
  final String? approverRole;
  final String? note;
  final bool isOptional;

  factory ApprovalDraftStepDto.fromJson(Map<String, dynamic> json) {
    return ApprovalDraftStepDto(
      stepOrder: JsonUtils.readInt(json, 'step_order', fallback: 0),
      approverId: JsonUtils.readInt(json, 'approver_id', fallback: 0),
      approverRole: _readString(json['approver_role']),
      note: _readString(json['note']),
      isOptional: json['is_optional'] is bool
          ? json['is_optional'] as bool
          : false,
    );
  }

  ApprovalDraftStep toEntity() => ApprovalDraftStep(
    stepOrder: stepOrder,
    approverId: approverId,
    approverRole: approverRole,
    note: note,
    isOptional: isOptional,
  );
}

/// 결재 초안 페이로드 DTO.
class ApprovalDraftPayloadDto {
  ApprovalDraftPayloadDto({
    this.title,
    this.summary,
    this.note,
    this.templateId,
    this.metadata,
    this.steps = const [],
  });

  final String? title;
  final String? summary;
  final String? note;
  final int? templateId;
  final Map<String, dynamic>? metadata;
  final List<ApprovalDraftStepDto> steps;

  factory ApprovalDraftPayloadDto.fromJson(Map<String, dynamic> json) {
    final steps = (json['steps'] as List<dynamic>? ?? const [])
        .whereType<Map<String, dynamic>>()
        .map(ApprovalDraftStepDto.fromJson)
        .toList(growable: false);
    final metadata = json['metadata'] is Map<String, dynamic>
        ? Map<String, dynamic>.from(json['metadata'] as Map)
        : null;
    return ApprovalDraftPayloadDto(
      title: _readString(json['title']),
      summary: _readString(json['summary']),
      note: _readString(json['note']),
      templateId: json['template_id'] as int?,
      metadata: metadata,
      steps: steps,
    );
  }

  ApprovalDraftPayload toEntity() => ApprovalDraftPayload(
    title: title,
    summary: summary,
    note: note,
    templateId: templateId,
    metadata: metadata,
    steps: steps.map((step) => step.toEntity()).toList(growable: false),
  );
}

/// 결재 초안 요약 DTO.
class ApprovalDraftSummaryDto {
  ApprovalDraftSummaryDto({
    required this.id,
    required this.requesterId,
    required this.status,
    required this.savedAt,
    this.requestId,
    this.transactionId,
    this.templateId,
    this.title,
    this.summary,
    this.expiresAt,
    this.sessionKey,
    this.stepCount = 0,
  });

  final int id;
  final int requesterId;
  final ApprovalDraftStatus status;
  final DateTime savedAt;
  final int? requestId;
  final int? transactionId;
  final int? templateId;
  final String? title;
  final String? summary;
  final DateTime? expiresAt;
  final String? sessionKey;
  final int stepCount;

  factory ApprovalDraftSummaryDto.fromJson(Map<String, dynamic> json) {
    final savedAtRaw = json['saved_at'];
    final expiresAtRaw = json['expires_at'];
    return ApprovalDraftSummaryDto(
      id: JsonUtils.readInt(json, 'id', fallback: 0),
      requesterId: JsonUtils.readInt(json, 'requester_id', fallback: 0),
      status: _parseStatus(_readString(json['status'])),
      savedAt: _parseDate(savedAtRaw) ?? DateTime.now().toUtc(),
      requestId: json['request_id'] as int?,
      transactionId: json['transaction_id'] as int?,
      templateId: json['template_id'] as int?,
      title: _readString(json['title']),
      summary: _readString(json['summary']),
      expiresAt: _parseDate(expiresAtRaw),
      sessionKey: _readString(json['session_key']),
      stepCount: JsonUtils.readInt(json, 'step_count', fallback: 0),
    );
  }

  ApprovalDraftSummary toEntity() => ApprovalDraftSummary(
    id: id,
    requesterId: requesterId,
    status: status,
    savedAt: savedAt,
    requestId: requestId,
    transactionId: transactionId,
    templateId: templateId,
    title: title,
    summary: summary,
    expiresAt: expiresAt,
    sessionKey: sessionKey,
    stepCount: stepCount,
  );
}

/// 결재 초안 상세 DTO.
class ApprovalDraftDetailDto {
  ApprovalDraftDetailDto({
    required this.id,
    required this.requesterId,
    required this.payload,
    required this.savedAt,
    this.transactionId,
    this.templateId,
    this.expiresAt,
    this.sessionKey,
  });

  final int id;
  final int requesterId;
  final ApprovalDraftPayloadDto payload;
  final DateTime savedAt;
  final int? transactionId;
  final int? templateId;
  final DateTime? expiresAt;
  final String? sessionKey;

  factory ApprovalDraftDetailDto.fromJson(Map<String, dynamic> json) {
    final payloadMap = json['payload'] is Map<String, dynamic>
        ? json['payload'] as Map<String, dynamic>
        : const <String, dynamic>{};
    return ApprovalDraftDetailDto(
      id: JsonUtils.readInt(json, 'id', fallback: 0),
      requesterId: JsonUtils.readInt(json, 'requester_id', fallback: 0),
      payload: ApprovalDraftPayloadDto.fromJson(payloadMap),
      savedAt: _parseDate(json['saved_at']) ?? DateTime.now().toUtc(),
      transactionId: json['transaction_id'] as int?,
      templateId: json['template_id'] as int?,
      expiresAt: _parseDate(json['expires_at']),
      sessionKey: _readString(json['session_key']),
    );
  }

  ApprovalDraftDetail toEntity() => ApprovalDraftDetail(
    id: id,
    requesterId: requesterId,
    payload: payload.toEntity(),
    savedAt: savedAt,
    transactionId: transactionId,
    templateId: templateId,
    expiresAt: expiresAt,
    sessionKey: sessionKey,
  );
}

class ApprovalDraftDto {
  ApprovalDraftDto._();

  static PaginatedResult<ApprovalDraftSummary> parsePaginated(
    Map<String, dynamic>? json,
  ) {
    final items = JsonUtils.extractList(json)
        .map(ApprovalDraftSummaryDto.fromJson)
        .map((dto) => dto.toEntity())
        .toList(growable: false);
    return PaginatedResult<ApprovalDraftSummary>(
      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),
    );
  }

  static ApprovalDraftDetail? parseDetail(Map<String, dynamic>? json) {
    if (json == null || json.isEmpty) {
      return null;
    }
    final map = JsonUtils.extractMap(json);
    if (map.isEmpty) {
      return null;
    }
    return ApprovalDraftDetailDto.fromJson(map).toEntity();
  }
}

String? _readString(dynamic value) {
  if (value == null) {
    return null;
  }
  if (value is String) {
    final trimmed = value.trim();
    return trimmed.isEmpty ? null : trimmed;
  }
  return value.toString();
}

DateTime? _parseDate(dynamic value) {
  if (value == null) {
    return null;
  }
  if (value is DateTime) {
    return value.toUtc();
  }
  if (value is String && value.isNotEmpty) {
    return DateTime.tryParse(value)?.toUtc();
  }
  return null;
}

ApprovalDraftStatus _parseStatus(String? value) {
  switch (value) {
    case 'expired':
      return ApprovalDraftStatus.expired;
    case 'archived':
      return ApprovalDraftStatus.archived;
    case 'active':
    default:
      return ApprovalDraftStatus.active;
  }
}
