import 'dart:async';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../domain/entities/share_account.dart';
import '../../domain/entities/global_state.dart';
import '../../domain/entities/planting_record.dart';
import '../../domain/entities/batch_mining_record.dart';
import '../../domain/repositories/mining_repository.dart';
import '../../domain/usecases/mining/get_share_account.dart';
import '../../domain/usecases/mining/get_global_state.dart';
import '../../core/di/injection.dart';

final miningRepositoryProvider = Provider<MiningRepository>((ref) {
  return getIt<MiningRepository>();
});

// Use Cases Providers
final getShareAccountUseCaseProvider = Provider<GetShareAccount>((ref) {
  return getIt<GetShareAccount>();
});

final getGlobalStateUseCaseProvider = Provider<GetGlobalState>((ref) {
  return getIt<GetGlobalState>();
});

// State Providers - 使用 keepAlive 缓存数据，避免重复请求
final shareAccountProvider = FutureProvider.family<ShareAccount?, String>(
  (ref, accountSequence) async {
    // 空字符串不请求
    if (accountSequence.isEmpty) return null;

    final useCase = ref.watch(getShareAccountUseCaseProvider);
    final result = await useCase(accountSequence);

    // 保持 provider 活跃，避免每次 rebuild 都重新请求
    ref.keepAlive();

    // 5 分钟后自动失效，允许刷新
    final timer = Timer(const Duration(minutes: 5), () {
      ref.invalidateSelf();
    });
    ref.onDispose(() => timer.cancel());

    return result.fold(
      (failure) => throw Exception(failure.message),
      (account) => account,
    );
  },
);

final globalStateProvider = FutureProvider<GlobalState?>((ref) async {
  final useCase = ref.watch(getGlobalStateUseCaseProvider);
  final result = await useCase();

  // 保持 provider 活跃
  ref.keepAlive();

  // 5 分钟后自动失效
  final timer = Timer(const Duration(minutes: 5), () {
    ref.invalidateSelf();
  });
  ref.onDispose(() => timer.cancel());

  return result.fold(
    (failure) => throw Exception(failure.message),
    (state) => state,
  );
});

final currentPriceProvider = Provider<String>((ref) {
  final globalState = ref.watch(globalStateProvider);
  return globalState.when(
    data: (state) => state?.currentPrice ?? '0',
    loading: () => '0',
    error: (_, __) => '0',
  );
});

/// 挖矿记录请求参数
class MiningRecordsParams {
  final String accountSequence;
  final int page;
  final int pageSize;

  const MiningRecordsParams({
    required this.accountSequence,
    this.page = 1,
    this.pageSize = 10,
  });

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is MiningRecordsParams &&
          runtimeType == other.runtimeType &&
          accountSequence == other.accountSequence &&
          page == other.page &&
          pageSize == other.pageSize;

  @override
  int get hashCode => accountSequence.hashCode ^ page.hashCode ^ pageSize.hashCode;
}

/// 挖矿记录 Provider
final miningRecordsProvider = FutureProvider.family<MiningRecordsPage?, MiningRecordsParams>(
  (ref, params) async {
    if (params.accountSequence.isEmpty) {
      return null;
    }

    final repository = ref.watch(miningRepositoryProvider);
    final result = await repository.getMiningRecords(
      params.accountSequence,
      page: params.page,
      pageSize: params.pageSize,
    );

    ref.keepAlive();
    final timer = Timer(const Duration(minutes: 5), () {
      ref.invalidateSelf();
    });
    ref.onDispose(() => timer.cancel());

    return result.fold(
      (failure) => throw Exception(failure.message),
      (records) => records,
    );
  },
);

/// 参与记录请求参数
class PlantingRecordsParams {
  final String accountSequence;
  final int page;
  final int pageSize;

  const PlantingRecordsParams({
    required this.accountSequence,
    this.page = 1,
    this.pageSize = 10,
  });

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is PlantingRecordsParams &&
          runtimeType == other.runtimeType &&
          accountSequence == other.accountSequence &&
          page == other.page &&
          pageSize == other.pageSize;

  @override
  int get hashCode => accountSequence.hashCode ^ page.hashCode ^ pageSize.hashCode;
}

/// 参与记录 Provider
final plantingRecordsProvider = FutureProvider.family<PlantingLedgerPage?, PlantingRecordsParams>(
  (ref, params) async {
    if (params.accountSequence.isEmpty) {
      return null;
    }

    final repository = ref.watch(miningRepositoryProvider);
    final result = await repository.getPlantingLedger(
      params.accountSequence,
      page: params.page,
      pageSize: params.pageSize,
    );

    ref.keepAlive();
    final timer = Timer(const Duration(minutes: 5), () {
      ref.invalidateSelf();
    });
    ref.onDispose(() => timer.cancel());

    return result.fold(
      (failure) => throw Exception(failure.message),
      (ledger) => ledger,
    );
  },
);

/// 批量补发记录请求参数
class BatchMiningRecordsParams {
  final String accountSequence;
  final int page;
  final int pageSize;

  const BatchMiningRecordsParams({
    required this.accountSequence,
    this.page = 1,
    this.pageSize = 20,
  });

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is BatchMiningRecordsParams &&
          runtimeType == other.runtimeType &&
          accountSequence == other.accountSequence &&
          page == other.page &&
          pageSize == other.pageSize;

  @override
  int get hashCode => accountSequence.hashCode ^ page.hashCode ^ pageSize.hashCode;
}

/// 批量补发记录 Provider
final batchMiningRecordsProvider = FutureProvider.family<BatchMiningRecordsPage?, BatchMiningRecordsParams>(
  (ref, params) async {
    if (params.accountSequence.isEmpty) {
      return null;
    }

    final repository = ref.watch(miningRepositoryProvider);
    final result = await repository.getBatchMiningRecords(
      params.accountSequence,
      page: params.page,
      pageSize: params.pageSize,
    );

    ref.keepAlive();
    final timer = Timer(const Duration(minutes: 5), () {
      ref.invalidateSelf();
    });
    ref.onDispose(() => timer.cancel());

    return result.fold(
      (failure) => throw Exception(failure.message),
      (records) => records,
    );
  },
);

/// 检查用户是否有批量补发记录的 Provider
final hasBatchMiningRecordsProvider = FutureProvider.family<bool, String>(
  (ref, accountSequence) async {
    if (accountSequence.isEmpty) {
      return false;
    }

    final repository = ref.watch(miningRepositoryProvider);
    final result = await repository.getBatchMiningRecords(
      accountSequence,
      page: 1,
      pageSize: 1,
    );

    ref.keepAlive();
    final timer = Timer(const Duration(minutes: 10), () {
      ref.invalidateSelf();
    });
    ref.onDispose(() => timer.cancel());

    return result.fold(
      (failure) => false,
      (records) => records.total > 0,
    );
  },
);
