import 'dart:async';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../domain/entities/price_info.dart';
import '../../domain/entities/market_overview.dart';
import '../../domain/entities/trading_account.dart';
import '../../domain/entities/trade_order.dart';
import '../../domain/entities/kline.dart';
import '../../domain/repositories/trading_repository.dart';
import '../../data/models/trade_order_model.dart';
import '../../core/di/injection.dart';
import 'user_providers.dart';

// Repository Provider
final tradingRepositoryProvider = Provider<TradingRepository>((ref) {
  return getIt<TradingRepository>();
});

// 买入功能开关 Provider (2分钟缓存)
final buyEnabledProvider = FutureProvider<bool>((ref) async {
  final repository = ref.watch(tradingRepositoryProvider);
  final result = await repository.getBuyEnabled();

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

  return result.fold(
    (failure) => false, // 获取失败时默认关闭
    (enabled) => enabled,
  );
});

// 预种卖出限制状态 Provider (2分钟缓存，fail-open)
// 依赖当前用户 accountSequence，账号切换时自动重新请求，避免跨账号缓存污染
final sellRestrictionProvider = FutureProvider<bool>((ref) async {
  // 绑定用户身份：accountSequence 变化（登录/切换账号）时自动失效重新请求
  ref.watch(userNotifierProvider.select((s) => s.accountSequence));

  final repository = ref.watch(tradingRepositoryProvider);
  final result = await repository.getSellRestriction();

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

  return result.fold(
    (failure) => false, // 接口异常时 fail-open，允许卖出
    (restricted) => restricted,
  );
});

// K线周期选择
final selectedKlinePeriodProvider = StateProvider<String>((ref) => '1h');

// 前端显示文本 → 后端API参数 的映射
// 日历周期（1w/1M/1y）在后端按自然周一/月初/年初对齐
String _periodToApiParam(String period) {
  const periodMap = {
    '1分': '1m',
    '5分': '5m',
    '15分': '15m',
    '30分': '30m',
    '1时': '1h',
    '4时': '4h',
    '日': '1d',
    '周': '1w',   // 周K线，按周一对齐
    '月': '1M',   // 月K线，按自然月对齐
    '年': '1y',   // 年K线，按自然年对齐
  };
  return periodMap[period] ?? '1h';
}

/// K线数据状态
class KlinesState {
  final List<Kline> klines;
  final bool isLoading;
  final bool isLoadingMore;
  final bool hasMoreHistory;
  final String? error;
  final String period;

  const KlinesState({
    this.klines = const [],
    this.isLoading = false,
    this.isLoadingMore = false,
    this.hasMoreHistory = true,
    this.error,
    this.period = '1h',
  });

  KlinesState copyWith({
    List<Kline>? klines,
    bool? isLoading,
    bool? isLoadingMore,
    bool? hasMoreHistory,
    String? error,
    String? period,
  }) {
    return KlinesState(
      klines: klines ?? this.klines,
      isLoading: isLoading ?? this.isLoading,
      isLoadingMore: isLoadingMore ?? this.isLoadingMore,
      hasMoreHistory: hasMoreHistory ?? this.hasMoreHistory,
      error: error,
      period: period ?? this.period,
    );
  }
}

/// K线数据管理器 - 支持累积数据和加载更多历史
class KlinesNotifier extends StateNotifier<KlinesState> {
  final TradingRepository repository;
  Timer? _refreshTimer;

  KlinesNotifier({required this.repository}) : super(const KlinesState());

  /// 初始加载K线数据
  Future<void> loadKlines(String period) async {
    final apiPeriod = _periodToApiParam(period);

    // 如果周期变化，重置数据
    if (state.period != apiPeriod) {
      state = KlinesState(isLoading: true, period: apiPeriod);
    } else {
      state = state.copyWith(isLoading: true, error: null);
    }

    final result = await repository.getKlines(period: apiPeriod, limit: 100);

    result.fold(
      (failure) {
        state = state.copyWith(isLoading: false, error: failure.message);
      },
      (klines) {
        state = state.copyWith(
          klines: klines,
          isLoading: false,
          hasMoreHistory: true, // 默认还有更多历史，直到加载返回空数据
        );
        _startAutoRefresh(apiPeriod);
      },
    );
  }

  /// 加载更多历史数据（向左滑动到边界时触发）
  Future<void> loadMoreHistory() async {
    if (state.isLoadingMore || !state.hasMoreHistory || state.klines.isEmpty) {
      return;
    }

    state = state.copyWith(isLoadingMore: true);

    // 获取当前最早K线的时间作为before参数
    final oldestKline = state.klines.first;
    final beforeTime = oldestKline.time;

    final result = await repository.getKlines(
      period: state.period,
      limit: 100,
      before: beforeTime,
    );

    result.fold(
      (failure) {
        state = state.copyWith(isLoadingMore: false, error: failure.message);
      },
      (newKlines) {
        if (newKlines.isEmpty) {
          // 没有更多历史数据了
          state = state.copyWith(isLoadingMore: false, hasMoreHistory: false);
        } else {
          // 将新数据插入到现有数据前面（按时间顺序）
          // 需要去重，因为可能有重叠
          final existingTimes = state.klines.map((k) => k.time.millisecondsSinceEpoch).toSet();
          final uniqueNewKlines = newKlines.where(
            (k) => !existingTimes.contains(k.time.millisecondsSinceEpoch)
          ).toList();

          // 如果去重后没有新数据，说明已经没有更多历史了
          if (uniqueNewKlines.isEmpty) {
            state = state.copyWith(isLoadingMore: false, hasMoreHistory: false);
            return;
          }

          final combinedKlines = [...uniqueNewKlines, ...state.klines];
          // 按时间排序
          combinedKlines.sort((a, b) => a.time.compareTo(b.time));

          // 判断是否还有更多历史：返回数据少于100条说明到底了
          state = state.copyWith(
            klines: combinedKlines,
            isLoadingMore: false,
            hasMoreHistory: newKlines.length >= 100,
          );
        }
      },
    );
  }

  /// 刷新最新数据（不清除历史）
  Future<void> refreshLatest() async {
    if (state.klines.isEmpty) {
      return loadKlines(state.period);
    }

    final result = await repository.getKlines(period: state.period, limit: 100);

    result.fold(
      (failure) {
        // 刷新失败不影响现有数据
      },
      (newKlines) {
        if (newKlines.isEmpty) return;

        // 合并新数据到现有数据末尾
        final existingTimes = state.klines.map((k) => k.time.millisecondsSinceEpoch).toSet();
        final uniqueNewKlines = newKlines.where(
          (k) => !existingTimes.contains(k.time.millisecondsSinceEpoch)
        ).toList();

        if (uniqueNewKlines.isNotEmpty) {
          final combinedKlines = [...state.klines, ...uniqueNewKlines];
          combinedKlines.sort((a, b) => a.time.compareTo(b.time));
          state = state.copyWith(klines: combinedKlines);
        }

        // 更新最新K线的收盘价（实时更新）
        if (newKlines.isNotEmpty && state.klines.isNotEmpty) {
          final latestNew = newKlines.last;
          final latestExisting = state.klines.last;
          if (latestNew.time.millisecondsSinceEpoch == latestExisting.time.millisecondsSinceEpoch) {
            // 更新最新K线
            final updatedKlines = [...state.klines];
            updatedKlines[updatedKlines.length - 1] = latestNew;
            state = state.copyWith(klines: updatedKlines);
          }
        }
      },
    );
  }

  void _startAutoRefresh(String period) {
    _refreshTimer?.cancel();
    _refreshTimer = Timer.periodic(const Duration(minutes: 1), (_) {
      refreshLatest();
    });
  }

  @override
  void dispose() {
    _refreshTimer?.cancel();
    super.dispose();
  }
}

/// K线数据 Provider（支持累积和加载更多）
final klinesNotifierProvider = StateNotifierProvider<KlinesNotifier, KlinesState>((ref) {
  final repository = ref.watch(tradingRepositoryProvider);
  return KlinesNotifier(repository: repository);
});

// 保留原有的简单 Provider 以保持向后兼容
final klinesProvider = FutureProvider<List<Kline>>((ref) async {
  final repository = ref.watch(tradingRepositoryProvider);
  final selectedPeriod = ref.watch(selectedKlinePeriodProvider);
  final apiPeriod = _periodToApiParam(selectedPeriod);

  final result = await repository.getKlines(period: apiPeriod, limit: 100);

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

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

// 当前价格 Provider (60秒缓存 - 与销毁调度器同步，每分钟刷新一次)
final currentPriceProvider = FutureProvider<PriceInfo?>((ref) async {
  final repository = ref.watch(tradingRepositoryProvider);
  final result = await repository.getCurrentPrice();

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

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

// 市场概览 Provider (30秒缓存 - 市场数据相对稳定)
final marketOverviewProvider = FutureProvider<MarketOverview?>((ref) async {
  final repository = ref.watch(tradingRepositoryProvider);
  final result = await repository.getMarketOverview();

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

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

// 交易账户 Provider (15秒缓存 - 交易后快速更新资产)
final tradingAccountProvider = FutureProvider.family<TradingAccount?, String>(
  (ref, accountSequence) async {
    if (accountSequence.isEmpty) return null;

    final repository = ref.watch(tradingRepositoryProvider);
    final result = await repository.getTradingAccount(accountSequence);

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

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

// 订单列表 Provider (10秒缓存 - 交易后快速看到结果)
final ordersProvider = FutureProvider<OrdersPageModel?>((ref) async {
  final repository = ref.watch(tradingRepositoryProvider);
  final result = await repository.getOrders(page: 1, pageSize: 10);

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

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

// 成交记录列表 Provider（含手续费明细）
final tradesProvider = FutureProvider<TradesPageModel?>((ref) async {
  final repository = ref.watch(tradingRepositoryProvider);
  final result = await repository.getTrades(page: 1, pageSize: 50);

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

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

// 交易状态
class TradingState {
  final bool isLoading;
  final String? error;
  final Map<String, dynamic>? lastOrderResult;

  TradingState({
    this.isLoading = false,
    this.error,
    this.lastOrderResult,
  });

  TradingState copyWith({
    bool? isLoading,
    String? error,
    Map<String, dynamic>? lastOrderResult,
  }) {
    return TradingState(
      isLoading: isLoading ?? this.isLoading,
      error: error,
      lastOrderResult: lastOrderResult ?? this.lastOrderResult,
    );
  }
}

class TradingNotifier extends StateNotifier<TradingState> {
  final TradingRepository repository;

  TradingNotifier({required this.repository}) : super(TradingState());

  /// 创建买入订单
  Future<bool> buyShares(String price, String quantity) async {
    state = state.copyWith(isLoading: true, error: null);

    final result = await repository.createOrder(
      type: 'BUY',
      price: price,
      quantity: quantity,
    );

    return result.fold(
      (failure) {
        state = state.copyWith(isLoading: false, error: failure.message);
        return false;
      },
      (orderResult) {
        state = state.copyWith(isLoading: false, lastOrderResult: orderResult);
        return true;
      },
    );
  }

  /// 创建卖出订单
  Future<bool> sellShares(String price, String quantity) async {
    state = state.copyWith(isLoading: true, error: null);

    final result = await repository.createOrder(
      type: 'SELL',
      price: price,
      quantity: quantity,
    );

    return result.fold(
      (failure) {
        state = state.copyWith(isLoading: false, error: failure.message);
        return false;
      },
      (orderResult) {
        state = state.copyWith(isLoading: false, lastOrderResult: orderResult);
        return true;
      },
    );
  }

  /// 取消订单
  Future<bool> cancelOrder(String orderNo) async {
    state = state.copyWith(isLoading: true, error: null);

    final result = await repository.cancelOrder(orderNo);

    return result.fold(
      (failure) {
        state = state.copyWith(isLoading: false, error: failure.message);
        return false;
      },
      (_) {
        state = state.copyWith(isLoading: false);
        return true;
      },
    );
  }

  /// 划入积分股
  Future<bool> transferIn(String amount) async {
    state = state.copyWith(isLoading: true, error: null);

    final result = await repository.transferIn(amount);

    return result.fold(
      (failure) {
        state = state.copyWith(isLoading: false, error: failure.message);
        return false;
      },
      (_) {
        state = state.copyWith(isLoading: false);
        return true;
      },
    );
  }

  /// 划出积分股
  Future<bool> transferOut(String amount) async {
    state = state.copyWith(isLoading: true, error: null);

    final result = await repository.transferOut(amount);

    return result.fold(
      (failure) {
        state = state.copyWith(isLoading: false, error: failure.message);
        return false;
      },
      (_) {
        state = state.copyWith(isLoading: false);
        return true;
      },
    );
  }

  void clearError() {
    state = state.copyWith(error: null);
  }
}

final tradingNotifierProvider = StateNotifierProvider<TradingNotifier, TradingState>(
  (ref) => TradingNotifier(
    repository: ref.watch(tradingRepositoryProvider),
  ),
);
