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

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

/// 그룹별 메뉴 권한을 표현하는 DTO.
class GroupPermissionDto {
  GroupPermissionDto({
    this.id,
    required this.group,
    required this.menu,
    this.canCreate = false,
    this.canRead = true,
    this.canUpdate = false,
    this.canDelete = false,
    this.isActive = true,
    this.isDeleted = false,
    this.note,
    this.createdAt,
    this.updatedAt,
  });

  final int? id;
  final GroupPermissionGroupDto group;
  final GroupPermissionMenuDto menu;
  final bool canCreate;
  final bool canRead;
  final bool canUpdate;
  final bool canDelete;
  final bool isActive;
  final bool isDeleted;
  final String? note;
  final DateTime? createdAt;
  final DateTime? updatedAt;

  /// JSON에서 권한 정보를 파싱한다.
  factory GroupPermissionDto.fromJson(Map<String, dynamic> json) {
    return GroupPermissionDto(
      id: json['id'] as int?,
      group: GroupPermissionGroupDto.fromJson(
        (json['group'] as Map<String, dynamic>? ?? const {}),
      ),
      menu: GroupPermissionMenuDto.fromJson(
        (json['menu'] as Map<String, dynamic>? ?? const {}),
      ),
      canCreate: (json['can_create'] as bool?) ?? false,
      canRead: (json['can_read'] as bool?) ?? true,
      canUpdate: (json['can_update'] as bool?) ?? false,
      canDelete: (json['can_delete'] as bool?) ?? false,
      isActive: (json['is_active'] as bool?) ?? true,
      isDeleted: (json['is_deleted'] as bool?) ?? false,
      note: json['note'] as String?,
      createdAt: _parseDate(json['created_at']),
      updatedAt: _parseDate(json['updated_at']),
    );
  }

  /// DTO를 도메인 [GroupPermission] 엔티티로 변환한다.
  GroupPermission toEntity() => GroupPermission(
    id: id,
    group: group.toEntity(),
    menu: menu.toEntity(),
    canCreate: canCreate,
    canRead: canRead,
    canUpdate: canUpdate,
    canDelete: canDelete,
    isActive: isActive,
    isDeleted: isDeleted,
    note: note,
    createdAt: createdAt,
    updatedAt: updatedAt,
  );

  /// 페이징 응답을 [PaginatedResult]로 변환한다.
  static PaginatedResult<GroupPermission> parsePaginated(
    Map<String, dynamic>? json,
  ) {
    final items = (json?['items'] as List<dynamic>? ?? [])
        .whereType<Map<String, dynamic>>()
        .map(GroupPermissionDto.fromJson)
        .map((dto) => dto.toEntity())
        .toList();
    return PaginatedResult<GroupPermission>(
      items: items,
      page: json?['page'] as int? ?? 1,
      pageSize: json?['page_size'] as int? ?? items.length,
      total: json?['total'] as int? ?? items.length,
    );
  }
}

/// 권한 설정에 포함된 그룹 정보를 담는 DTO.
class GroupPermissionGroupDto {
  GroupPermissionGroupDto({required this.id, required this.groupName});

  final int id;
  final String groupName;

  /// JSON에서 그룹 정보를 파싱한다.
  factory GroupPermissionGroupDto.fromJson(Map<String, dynamic> json) {
    return GroupPermissionGroupDto(
      id: json['id'] as int? ?? json['group_id'] as int,
      groupName:
          json['group_name'] as String? ?? json['name'] as String? ?? '-',
    );
  }

  /// DTO를 [GroupPermissionGroup] 엔티티로 변환한다.
  GroupPermissionGroup toEntity() =>
      GroupPermissionGroup(id: id, groupName: groupName);
}

/// 권한 대상 메뉴 정보를 담는 DTO.
class GroupPermissionMenuDto {
  GroupPermissionMenuDto({
    required this.id,
    required this.menuCode,
    required this.menuName,
    this.path,
  });

  final int id;
  final String menuCode;
  final String menuName;
  final String? path;

  /// JSON에서 메뉴 정보를 파싱한다.
  factory GroupPermissionMenuDto.fromJson(Map<String, dynamic> json) {
    final fallbackName =
        json['menu_name'] as String? ?? json['name'] as String? ?? '-';
    final code =
        json['menu_code'] as String? ?? json['code'] as String? ?? fallbackName;
    return GroupPermissionMenuDto(
      id: json['id'] as int? ?? json['menu_id'] as int,
      menuCode: code,
      menuName: fallbackName,
      path: (json['path'] ?? json['route_path']) as String?,
    );
  }

  /// DTO를 [GroupPermissionMenu] 엔티티로 변환한다.
  GroupPermissionMenu toEntity() => GroupPermissionMenu(
    id: id,
    menuCode: menuCode,
    menuName: menuName,
    path: path,
  );
}

/// 문자열/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;
}
