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

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

/// 결재 템플릿 API 응답을 표현하는 DTO.
class ApprovalTemplateDto {
  ApprovalTemplateDto({
    required this.id,
    required this.code,
    required this.name,
    this.description,
    required this.isActive,
    this.note,
    this.createdBy,
    this.createdAt,
    this.updatedAt,
    this.steps = const [],
  });

  final int id;
  final String code;
  final String name;
  final String? description;
  final bool isActive;
  final String? note;
  final ApprovalTemplateAuthorDto? createdBy;
  final DateTime? createdAt;
  final DateTime? updatedAt;
  final List<ApprovalTemplateStepDto> steps;

  /// JSON을 [ApprovalTemplateDto]로 파싱한다.
  factory ApprovalTemplateDto.fromJson(Map<String, dynamic> json) {
    return ApprovalTemplateDto(
      id: json['id'] as int? ?? 0,
      code: json['template_code'] as String? ?? json['code'] as String? ?? '-',
      name: json['template_name'] as String? ?? json['name'] as String? ?? '-',
      description: json['description'] as String?,
      note: json['note'] as String?,
      isActive: (json['is_active'] as bool?) ?? true,
      createdBy: json['created_by'] is Map<String, dynamic>
          ? ApprovalTemplateAuthorDto.fromJson(
              json['created_by'] as Map<String, dynamic>,
            )
          : null,
      createdAt: _parseDate(json['created_at']),
      updatedAt: _parseDate(json['updated_at']),
      steps: (json['steps'] as List<dynamic>? ?? [])
          .whereType<Map<String, dynamic>>()
          .map(ApprovalTemplateStepDto.fromJson)
          .toList(),
    );
  }

  /// DTO를 [ApprovalTemplate]으로 변환한다.
  ApprovalTemplate toEntity({bool includeSteps = true}) {
    return ApprovalTemplate(
      id: id,
      code: code,
      name: name,
      description: description,
      note: note,
      isActive: isActive,
      createdBy: createdBy?.toEntity(),
      createdAt: createdAt,
      updatedAt: updatedAt,
      steps: includeSteps ? steps.map((e) => e.toEntity()).toList() : const [],
    );
  }

  /// 페이징 응답을 파싱해 [PaginatedResult]를 반환한다.
  static PaginatedResult<ApprovalTemplate> parsePaginated(
    Map<String, dynamic>? json, {
    bool includeSteps = false,
  }) {
    final rawItems = JsonUtils.extractList(json, keys: const ['items']);
    final items = rawItems
        .map(ApprovalTemplateDto.fromJson)
        .map((dto) => dto.toEntity(includeSteps: includeSteps))
        .toList(growable: false);
    return PaginatedResult<ApprovalTemplate>(
      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),
    );
  }
}

/// 템플릿 작성자 DTO.
class ApprovalTemplateAuthorDto {
  ApprovalTemplateAuthorDto({
    required this.id,
    required this.employeeNo,
    required this.name,
  });

  final int id;
  final String employeeNo;
  final String name;

  factory ApprovalTemplateAuthorDto.fromJson(Map<String, dynamic> json) {
    return ApprovalTemplateAuthorDto(
      id: json['id'] as int? ?? json['employee_id'] as int? ?? 0,
      employeeNo: json['employee_no'] as String? ?? '-',
      name: json['employee_name'] as String? ?? json['name'] as String? ?? '-',
    );
  }

  /// DTO를 [ApprovalTemplateAuthor]로 변환한다.
  ApprovalTemplateAuthor toEntity() {
    return ApprovalTemplateAuthor(id: id, employeeNo: employeeNo, name: name);
  }
}

/// 템플릿 단계 DTO.
class ApprovalTemplateStepDto {
  ApprovalTemplateStepDto({
    this.id,
    required this.stepOrder,
    required this.approver,
    this.note,
  });

  final int? id;
  final int stepOrder;
  final ApprovalTemplateApproverDto approver;
  final String? note;

  factory ApprovalTemplateStepDto.fromJson(Map<String, dynamic> json) {
    return ApprovalTemplateStepDto(
      id: json['id'] as int?,
      stepOrder: json['step_order'] as int? ?? 0,
      approver: ApprovalTemplateApproverDto.fromJson(
        (json['approver'] as Map<String, dynamic>? ?? const {}),
      ),
      note: json['note'] as String?,
    );
  }

  /// DTO를 [ApprovalTemplateStep]으로 변환한다.
  ApprovalTemplateStep toEntity() {
    return ApprovalTemplateStep(
      id: id,
      stepOrder: stepOrder,
      approver: approver.toEntity(),
      note: note,
    );
  }
}

/// 템플릿 승인자 DTO.
class ApprovalTemplateApproverDto {
  ApprovalTemplateApproverDto({
    required this.id,
    required this.employeeNo,
    required this.name,
  });

  final int id;
  final String employeeNo;
  final String name;

  factory ApprovalTemplateApproverDto.fromJson(Map<String, dynamic> json) {
    return ApprovalTemplateApproverDto(
      id: json['id'] as int? ?? json['approver_id'] as int? ?? 0,
      employeeNo: json['employee_no'] as String? ?? '-',
      name: json['employee_name'] as String? ?? json['name'] as String? ?? '-',
    );
  }

  /// DTO를 [ApprovalTemplateApprover]로 변환한다.
  ApprovalTemplateApprover toEntity() {
    return ApprovalTemplateApprover(id: id, employeeNo: employeeNo, name: name);
  }
}

/// 문자열/DateTime을 파싱해 [DateTime]으로 반환한다.
DateTime? _parseDate(Object? value) {
  if (value == null) return null;
  if (value is DateTime) return value;
  if (value is String) return DateTime.tryParse(value);
  return null;
}
