import 'dart:async';
import 'dart:math';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../core/error/exceptions.dart';
import '../../../../core/network/dio_client.dart';
import '../../../knowledge_base/data/datasources/kb_remote_datasource.dart';
import '../../data/datasources/akinator_remote_datasource.dart';
import '../../data/repositories/akinator_repository_impl.dart';
import 'akinator_state.dart';

class AkinatorCubit extends Cubit<AkinatorState> {
  final AkinatorRepositoryImpl _repo;
  Timer? _rateLimitTimer;

  AkinatorCubit()
      : _repo = AkinatorRepositoryImpl(
            AkinatorRemoteDatasource(DioClient.instance)),
        super(AkinatorState(
          sessionId: 'ak_${Random().nextInt(999999)}',
          messages: [
            AkinatorMessage(
              id: 'welcome',
              text: '🔮 **Akinator 2.0 — Multi-Agent Prediction Engine**\n\n'
                  'I run **4 expert analyst agents** simultaneously:\n\n'
                  '📈 **Market Data Analyst** — Live prices, ratios & returns\n'
                  '📰 **News & Sentiment Analyst** — Breaking news & market mood\n'
                  '⚠️ **Risk Assessment Analyst** — Volatility & downside risk\n'
                  '💼 **Portfolio Strategy Advisor** — Allocation & strategy\n\n'
                  '_Try: "Should I invest in AAPL?" or "What if I invested \$10K in Tesla 3 years ago?"_',
              timestamp: DateTime.now(),
            ),
          ],
        ));

  Future<void> loadKnowledgeBases() async {
    try {
      final kbs =
          await KBRemoteDatasource(DioClient.instance).getKnowledgeBases();
      emit(state.copyWith(knowledgeBases: kbs));
    } catch (_) {}
  }

  void selectKB(String? kbId) {
    emit(state.copyWith(selectedKbId: () => kbId));
  }

  void togglePanelMode() {
    emit(state.copyWith(panelMode: !state.panelMode));
  }

  Future<void> sendQuery(String text) async {
    if (text.trim().isEmpty || state.isTyping || state.isRateLimited) return;

    final userMsg = AkinatorMessage(
      id: 'user_${DateTime.now().millisecondsSinceEpoch}',
      text: text.trim(),
      isUser: true,
      timestamp: DateTime.now(),
    );

    emit(state.copyWith(
      messages: [...state.messages, userMsg],
      isTyping: true,
    ));

    try {
      final response = await _repo.predict(
        sessionId: state.sessionId,
        message: text.trim(),
        panelMode: state.panelMode,
        knowledgeBaseId: state.selectedKbId,
      );

      final botMsg = AkinatorMessage(
        id: 'bot_${DateTime.now().millisecondsSinceEpoch}',
        text: response.reply,
        confidenceScore: response.confidenceScore,
        sentimentLabel: response.sentimentLabel,
        sentimentScore: response.sentimentScore,
        critiqueNote: response.critiqueNote,
        jargonDefinitions: response.jargonDefinitions,
        memo: response.memo,
        whatifResult: response.whatifResult,
        ragUsed: response.ragUsed,
        timestamp: DateTime.now(),
      );

      emit(state.copyWith(
        messages: [...state.messages, botMsg],
        isTyping: false,
      ));
    } on RateLimitException catch (e) {
      emit(state.copyWith(isTyping: false));
      _startRateLimitCountdown(e.waitSeconds);
    } catch (e) {
      final errorMsg = AkinatorMessage(
        id: 'error_${DateTime.now().millisecondsSinceEpoch}',
        text: '❌ Error: ${e.toString()}',
        timestamp: DateTime.now(),
      );
      emit(state.copyWith(
        messages: [...state.messages, errorMsg],
        isTyping: false,
      ));
    }
  }

  void _startRateLimitCountdown(int seconds) {
    _rateLimitTimer?.cancel();
    emit(state.copyWith(rateLimitSeconds: () => seconds));

    _rateLimitTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
      final remaining = (state.rateLimitSeconds ?? 0) - 1;
      if (remaining <= 0) {
        timer.cancel();
        emit(state.copyWith(rateLimitSeconds: () => null));
      } else {
        emit(state.copyWith(rateLimitSeconds: () => remaining));
      }
    });
  }

  @override
  Future<void> close() {
    _rateLimitTimer?.cancel();
    return super.close();
  }
}