/// Address Repository Implementation
///
/// Implements address repository with online-only API calls.
library;

import 'package:worker/features/account/data/datasources/address_remote_datasource.dart';
import 'package:worker/features/account/data/models/address_model.dart';
import 'package:worker/features/account/domain/entities/address.dart';
import 'package:worker/features/account/domain/repositories/address_repository.dart';

/// Address Repository Implementation
///
/// Online-only implementation - all operations go directly to API.
/// No local caching or offline support.
class AddressRepositoryImpl implements AddressRepository {
  final AddressRemoteDataSource _remoteDataSource;

  AddressRepositoryImpl({
    required AddressRemoteDataSource remoteDataSource,
  }) : _remoteDataSource = remoteDataSource;

  @override
  Future<List<Address>> getAddresses({bool? isDefault}) async {
    _debugPrint('Getting addresses...');

    try {
      final addressModels = await _remoteDataSource.getAddresses(
        isDefault: isDefault,
      );

      final addresses = addressModels.map((model) => model.toEntity()).toList();

      _debugPrint('Retrieved ${addresses.length} addresses');
      return addresses;
    } catch (e) {
      _debugPrint('Error getting addresses: $e');
      rethrow;
    }
  }

  @override
  Future<Address> createAddress(Address address) async {
    _debugPrint('Creating address: ${address.addressTitle}');

    try {
      // Create model with empty name (API will generate)
      final addressModel = AddressModel.fromEntity(address).copyWith(
        name: '', // Empty name indicates creation
      );

      final savedModel = await _remoteDataSource.saveAddress(addressModel);

      _debugPrint('Address created: ${savedModel.name}');
      return savedModel.toEntity();
    } catch (e) {
      _debugPrint('Error creating address: $e');
      rethrow;
    }
  }

  @override
  Future<Address> updateAddress(Address address) async {
    _debugPrint('Updating address: ${address.name}');

    try {
      final addressModel = AddressModel.fromEntity(address);
      final savedModel = await _remoteDataSource.saveAddress(addressModel);

      _debugPrint('Address updated: ${savedModel.name}');
      return savedModel.toEntity();
    } catch (e) {
      _debugPrint('Error updating address: $e');
      rethrow;
    }
  }

  @override
  Future<void> deleteAddress(String name) async {
    _debugPrint('Deleting address: $name');

    try {
      await _remoteDataSource.deleteAddress(name);
      _debugPrint('Address deleted: $name');
    } catch (e) {
      _debugPrint('Error deleting address: $e');
      rethrow;
    }
  }

  @override
  Future<void> setDefaultAddress(String name) async {
    _debugPrint('Setting default address: $name');

    try {
      // Get all addresses
      final addresses = await getAddresses();

      // Find the address to set as default
      final targetAddress = addresses.firstWhere(
        (addr) => addr.name == name,
        orElse: () => throw Exception('Address not found: $name'),
      );

      // Update the target address to be default
      await updateAddress(targetAddress.copyWith(isDefault: true));

      // Update other addresses to not be default
      for (final addr in addresses) {
        if (addr.name != name && addr.isDefault) {
          await updateAddress(addr.copyWith(isDefault: false));
        }
      }

      _debugPrint('Default address set: $name');
    } catch (e) {
      _debugPrint('Error setting default address: $e');
      rethrow;
    }
  }

  /// Debug print helper
  void _debugPrint(String message) {
    // ignore: avoid_print
    print('[AddressRepository] $message');
  }
}

/// Extension to create a copy with modifications (since AddressModel is not freezed)
extension _AddressModelCopyWith on AddressModel {
  AddressModel copyWith({
    String? name,
    String? addressTitle,
    String? addressLine1,
    String? phone,
    String? email,
    String? fax,
    String? taxCode,
    String? cityCode,
    String? wardCode,
    bool? isDefault,
    String? cityName,
    String? wardName,
  }) {
    return AddressModel(
      name: name ?? this.name,
      addressTitle: addressTitle ?? this.addressTitle,
      addressLine1: addressLine1 ?? this.addressLine1,
      phone: phone ?? this.phone,
      email: email ?? this.email,
      fax: fax ?? this.fax,
      taxCode: taxCode ?? this.taxCode,
      cityCode: cityCode ?? this.cityCode,
      wardCode: wardCode ?? this.wardCode,
      isDefault: isDefault ?? this.isDefault,
      cityName: cityName ?? this.cityName,
      wardName: wardName ?? this.wardName,
    );
  }
}
