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

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

/// 사용자(User) API 응답을 표현하는 DTO.
class UserDto {
  UserDto({
    this.id,
    required this.employeeNo,
    required this.employeeName,
    this.email,
    this.mobileNo,
    this.group,
    this.isActive = true,
    this.isDeleted = false,
    this.note,
    this.forcePasswordChange = false,
    this.passwordUpdatedAt,
    this.createdAt,
    this.updatedAt,
  });

  final int? id;
  final String employeeNo;
  final String employeeName;
  final String? email;
  final String? mobileNo;
  final UserGroupDto? group;
  final bool isActive;
  final bool isDeleted;
  final String? note;
  final bool forcePasswordChange;
  final DateTime? passwordUpdatedAt;
  final DateTime? createdAt;
  final DateTime? updatedAt;

  /// JSON에서 사용자 정보를 파싱한다.
  factory UserDto.fromJson(Map<String, dynamic> json) {
    return UserDto(
      id: json['id'] as int?,
      employeeNo:
          json['employee_id'] as String? ??
          json['employee_no'] as String? ??
          '-',
      employeeName:
          json['name'] as String? ?? json['employee_name'] as String? ?? '-',
      email: json['email'] as String?,
      mobileNo: json['phone'] as String? ?? json['mobile_no'] as String?,
      group: json['group'] is Map<String, dynamic>
          ? UserGroupDto.fromJson(json['group'] as Map<String, dynamic>)
          : null,
      isActive: (json['is_active'] as bool?) ?? true,
      isDeleted: (json['is_deleted'] as bool?) ?? false,
      note: json['note'] as String?,
      forcePasswordChange: (json['force_password_change'] as bool?) ?? false,
      passwordUpdatedAt: _parseDate(json['password_updated_at']),
      createdAt: _parseDate(json['created_at']),
      updatedAt: _parseDate(json['updated_at']),
    );
  }

  /// DTO를 도메인 [UserAccount] 엔티티로 변환한다.
  UserAccount toEntity() => UserAccount(
    id: id,
    employeeNo: employeeNo,
    employeeName: employeeName,
    email: email,
    mobileNo: mobileNo,
    group: group?.toEntity(),
    isActive: isActive,
    isDeleted: isDeleted,
    note: note,
    forcePasswordChange: forcePasswordChange,
    passwordUpdatedAt: passwordUpdatedAt,
    createdAt: createdAt,
    updatedAt: updatedAt,
  );

  /// 페이징 응답을 [PaginatedResult]로 변환한다.
  static PaginatedResult<UserAccount> parsePaginated(
    Map<String, dynamic>? json,
  ) {
    final rawItems = JsonUtils.extractList(json, keys: const ['items']);
    final items = rawItems
        .map(UserDto.fromJson)
        .map((dto) => dto.toEntity())
        .toList(growable: false);
    return PaginatedResult<UserAccount>(
      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 UserGroupDto {
  UserGroupDto({required this.id, required this.groupName});

  final int id;
  final String groupName;

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

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

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