import '../../directory/domain/employee.dart';

class LoginDeviceInfo {
  const LoginDeviceInfo({
    required this.platform,
    required this.appVersion,
    required this.deviceName,
  });

  final String platform;
  final String appVersion;
  final String deviceName;

  factory LoginDeviceInfo.fromJson(Map<String, dynamic> json) {
    return LoginDeviceInfo(
      platform: json['platform'] as String? ?? '',
      appVersion: json['appVersion'] as String? ?? '',
      deviceName: json['deviceName'] as String? ?? '',
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'platform': platform,
      'appVersion': appVersion,
      'deviceName': deviceName,
    };
  }
}

class PhoneLoginRequest {
  const PhoneLoginRequest({required this.phoneNumber, required this.device});

  final String phoneNumber;
  final LoginDeviceInfo device;

  Map<String, dynamic> toJson() {
    return {'phoneNumber': phoneNumber, 'device': device.toJson()};
  }
}

class LoginUser {
  const LoginUser({
    required this.id,
    required this.name,
    required this.phoneNumber,
    required this.tenantId,
    required this.tenantName,
    required this.tenantSlug,
    this.department,
    this.grade,
    this.position,
    this.jobTitle,
  });

  final String id;
  final String name;
  final String phoneNumber;
  final String tenantId;
  final String tenantName;
  final String tenantSlug;
  final String? department;
  final String? grade;
  final String? position;
  final String? jobTitle;

  factory LoginUser.fromJson(Map<String, dynamic> json) {
    return LoginUser(
      id: json['id'] as String? ?? '',
      name: json['name'] as String? ?? '',
      phoneNumber: json['phoneNumber'] as String? ?? '',
      tenantId: json['tenantId'] as String? ?? '',
      tenantName: json['tenantName'] as String? ?? '',
      tenantSlug: json['tenantSlug'] as String? ?? '',
      department: json['department'] as String?,
      grade: json['grade'] as String?,
      position: json['position'] as String?,
      jobTitle: json['jobTitle'] as String?,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'name': name,
      'phoneNumber': phoneNumber,
      'tenantId': tenantId,
      'tenantName': tenantName,
      'tenantSlug': tenantSlug,
      'department': department,
      'grade': grade,
      'position': position,
      'jobTitle': jobTitle,
    };
  }
}

class PhoneLoginResponse {
  const PhoneLoginResponse({
    required this.status,
    required this.token,
    required this.expiresAt,
    required this.user,
  });

  final String status;
  final String token;
  final DateTime expiresAt;
  final LoginUser user;

  factory PhoneLoginResponse.fromJson(Map<String, dynamic> json) {
    return PhoneLoginResponse(
      status: json['status'] as String? ?? '',
      token: json['token'] as String? ?? json['accessToken'] as String? ?? '',
      expiresAt: DateTime.parse(json['expiresAt'] as String),
      user: LoginUser.fromJson(json['user'] as Map<String, dynamic>? ?? {}),
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'status': status,
      'token': token,
      'expiresAt': expiresAt.toUtc().toIso8601String(),
      'user': user.toJson(),
    };
  }
}

class PhoneLoginLinkInitRequest {
  const PhoneLoginLinkInitRequest({
    required this.phoneNumber,
    required this.device,
  });

  final String phoneNumber;
  final LoginDeviceInfo device;

  Map<String, dynamic> toJson() {
    return {'phoneNumber': phoneNumber, 'device': device.toJson()};
  }
}

class PhoneLoginLinkInitResponse {
  const PhoneLoginLinkInitResponse({
    required this.status,
    required this.pendingRef,
    required this.expiresIn,
    required this.interval,
    required this.resendAfter,
    this.provider,
  });

  final String status;
  final String pendingRef;
  final int expiresIn;
  final int interval;
  final int resendAfter;
  final String? provider;

  factory PhoneLoginLinkInitResponse.fromJson(Map<String, dynamic> json) {
    return PhoneLoginLinkInitResponse(
      status: json['status'] as String? ?? '',
      pendingRef: json['pendingRef'] as String? ?? '',
      expiresIn: json['expiresIn'] as int? ?? 180,
      interval: json['interval'] as int? ?? json['pollInterval'] as int? ?? 3,
      resendAfter: json['resendAfter'] as int? ?? 30,
      provider: json['provider'] as String?,
    );
  }
}

class PhoneLoginLinkPollRequest {
  const PhoneLoginLinkPollRequest({required this.pendingRef});

  final String pendingRef;

  Map<String, dynamic> toJson() {
    return {'pendingRef': pendingRef};
  }
}

class PhoneLoginLinkPollResponse {
  const PhoneLoginLinkPollResponse({
    required this.status,
    this.code,
    this.interval,
    this.session,
  });

  final String status;
  final String? code;
  final int? interval;
  final PhoneLoginResponse? session;

  bool get isPending =>
      status == 'pending' ||
      code == 'authorization_pending' ||
      code == 'slow_down';

  bool get isExpired => code == 'expired_token';

  factory PhoneLoginLinkPollResponse.fromJson(Map<String, dynamic> json) {
    PhoneLoginResponse? session;
    if (json['session'] is Map<String, dynamic>) {
      session = PhoneLoginResponse.fromJson(
        json['session'] as Map<String, dynamic>,
      );
    } else if ((json['token'] != null || json['accessToken'] != null) &&
        json['expiresAt'] != null) {
      session = PhoneLoginResponse.fromJson(json);
    }

    return PhoneLoginLinkPollResponse(
      status: json['status'] as String? ?? '',
      code: json['code'] as String?,
      interval: json['interval'] as int? ?? json['pollInterval'] as int?,
      session: session,
    );
  }
}

class UserPermissions {
  const UserPermissions({
    required this.directory,
    required this.organization,
    required this.favoritesSync,
  });

  final bool directory;
  final bool organization;
  final bool favoritesSync;

  factory UserPermissions.fromJson(Map<String, dynamic> json) {
    return UserPermissions(
      directory: json['directory'] as bool? ?? false,
      organization: json['organization'] as bool? ?? false,
      favoritesSync: json['favoritesSync'] as bool? ?? false,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'directory': directory,
      'organization': organization,
      'favoritesSync': favoritesSync,
    };
  }
}

class CurrentUser {
  const CurrentUser({
    required this.id,
    required this.name,
    required this.phoneNumber,
    required this.email,
    required this.tenantId,
    required this.tenantName,
    required this.tenantSlug,
    required this.permissions,
    this.department,
    this.grade,
    this.position,
    this.jobTitle,
  });

  final String id;
  final String name;
  final String phoneNumber;
  final String email;
  final String tenantId;
  final String tenantName;
  final String tenantSlug;
  final UserPermissions permissions;
  final String? department;
  final String? grade;
  final String? position;
  final String? jobTitle;

  factory CurrentUser.fromJson(Map<String, dynamic> json) {
    return CurrentUser(
      id: json['id'] as String? ?? '',
      name: json['name'] as String? ?? '',
      phoneNumber: json['phoneNumber'] as String? ?? '',
      email: json['email'] as String? ?? '',
      tenantId: json['tenantId'] as String? ?? '',
      tenantName: json['tenantName'] as String? ?? '',
      tenantSlug: json['tenantSlug'] as String? ?? '',
      permissions: UserPermissions.fromJson(
        json['permissions'] as Map<String, dynamic>? ?? {},
      ),
      department: json['department'] as String?,
      grade: json['grade'] as String?,
      position: json['position'] as String?,
      jobTitle: json['jobTitle'] as String?,
    );
  }

  Employee toEmployee() {
    return Employee(
      id: id,
      name: name,
      phoneNumber: phoneNumber,
      email: email,
      tenantId: tenantId,
      tenantName: tenantName,
      tenantSlug: tenantSlug,
      department: department,
      grade: grade,
      position: position,
      jobTitle: jobTitle,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'name': name,
      'phoneNumber': phoneNumber,
      'email': email,
      'tenantId': tenantId,
      'tenantName': tenantName,
      'tenantSlug': tenantSlug,
      'department': department,
      'grade': grade,
      'position': position,
      'jobTitle': jobTitle,
      'permissions': permissions.toJson(),
    };
  }
}
