import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../services/stt_service.dart';
import '../services/gemini_service.dart';
import '../services/firestore_service.dart';
import '../services/voice_commands_service.dart';
import '../models/decision_log.dart';
import '../models/ayuel_response.dart';
import '../models/user_profile.dart';
import '../models/preferences.dart';
import 'voice_state.dart';
import 'package:uuid/uuid.dart';
import '../services/tts_service.dart';
import 'package:flutter/services.dart';
import 'dart:async';

// State to hold everything
class VoiceSessionState {
  final VoiceState state;
  final String transcript;
  final AyuelResponse? response;
  final String? error;
  final String? logId;
  final Duration? timerDuration;
  final List<Map<String, String>> history;

  VoiceSessionState({
    this.state = VoiceState.idle,
    this.transcript = "",
    this.response,
    this.error,
    this.logId,
    this.timerDuration,
    this.history = const [],
  });

  VoiceSessionState copyWith({
    VoiceState? state,
    String? transcript,
    AyuelResponse? response,
    String? error,
    String? logId,
    Duration? timerDuration,
    List<Map<String, String>>? history,
  }) {
    return VoiceSessionState(
      state: state ?? this.state,
      transcript: transcript ?? this.transcript,
      response: response ?? this.response,
      error: error ?? this.error,
      logId: logId ?? this.logId,
      timerDuration: timerDuration ?? this.timerDuration,
      history: history ?? this.history,
    );
  }
}

class VoiceControllerNotifier extends Notifier<VoiceSessionState> {
  @override
  VoiceSessionState build() {
    return VoiceSessionState();
  }

  void startListening() async {
    final stt = ref.read(sttServiceProvider);
    state = state.copyWith(
      state: VoiceState.listening,
      transcript: "",
      error: null,
      response: null,
      logId: null,
      // Keep timerDuration if running? Or reset? Let's keep it.
    );

    await stt.startListening(
      onResult: (text) {
        state = state.copyWith(transcript: text);
      },
      onStatus: (status) {
        if (status == "error_unavailable") {
          state = state.copyWith(
            state: VoiceState.error,
            error: "Microphone unavailable",
          );
        }
      },
    );
  }

  Timer? _proactiveTimer;

  void startProactiveMonitoring() {
    _proactiveTimer?.cancel();
    // Set for 2 hours
    _proactiveTimer = Timer(const Duration(hours: 2), _triggerNudge);
    print("⏰ Proactive monitoring started (2 hours)");
  }

  void _triggerNudge() async {
    final prefs = ref.read(preferencesProvider).value;
    // Check if nudges are enabled
    if (prefs?.gentleNudges != true) return;

    // Only interrupt if Idle or Monitoring
    if (state.state != VoiceState.idle &&
        state.state != VoiceState.monitoring) {
      _rescheduleProactiveTimer();
      return;
    }

    print("🌟 Triggering Proactive Nudge");

    final nudgeResponse = AyuelResponse(
      category: "SelfCare",
      title: "Energy Check-in",
      suggestion:
          "You've been focused for a while. Want to do a quick 2-minute energy check-in?",
      why: "Regular check-ins prevent burnout.",
      actions: [
        AyuelAction(label: "Check Energy", type: "confirm"),
        AyuelAction(label: "Not now", type: "defer"),
      ],
    );

    // Speak it
    final tts = ref.read(ttsServiceProvider);
    await tts.speak(nudgeResponse.suggestion);

    // Show it as a response card
    state = state.copyWith(state: VoiceState.speaking, response: nudgeResponse);
  }

  void _rescheduleProactiveTimer() {
    _proactiveTimer?.cancel();
    _proactiveTimer = Timer(const Duration(minutes: 15), _triggerNudge);
  }

  // Public method for testing
  void testProactiveNudge() {
    _triggerNudge();
  }

  void stopListeningAndThink(String currentEnergy) async {
    // Reset proactive timer on interaction
    startProactiveMonitoring();

    final stt = ref.read(sttServiceProvider);
    await stt.stopListening();

    // If transcript is empty, abort
    if (state.transcript.trim().isEmpty) {
      state = state.copyWith(state: VoiceState.idle);
      return;
    }

    _processRequest(state.transcript, currentEnergy);
  }

  void submitTextRequest(String text, String currentEnergy) {
    state = state.copyWith(transcript: text);
    _processRequest(text, currentEnergy);
  }

  void _processRequest(String text, String currentEnergy) async {
    state = state.copyWith(state: VoiceState.thinking);

    // Check for quick voice commands first
    final commandsService = VoiceCommandsService();
    final command = commandsService.detectCommand(text);

    if (command != null) {
      // Execute command instantly (no AI call needed)
      print('🚀 Quick command detected: ${command.id}');

      // Special case for testing Nudge
      if (command.id == 'test_nudge') {
        testProactiveNudge();
        return;
      }

      // Special case for Daily Brief
      if (command.id == 'daily_brief') {
        _processWithGemini(
          "Generate a structured morning briefing based on my profile. 1. Predicted Energy. 2. Focus Areas. 3. Motivational Quote. Keep it encouraging.",
          currentEnergy,
          displayText: text,
        );
        return;
      }

      // Small delay for natural feel
      await Future.delayed(const Duration(milliseconds: 300));

      final response = command.execute(text);

      // Update History
      final newHistory = List<Map<String, String>>.from(state.history);
      newHistory.add({'role': 'user', 'content': text});
      newHistory.add({'role': 'model', 'content': response.suggestion});
      if (newHistory.length > 8)
        newHistory.removeRange(0, newHistory.length - 8);

      state = state.copyWith(
        state: VoiceState.speaking,
        response: response,
        history: newHistory,
      );

      // Log the command execution
      _logDecision(text, response, currentEnergy);
      return;
    }

    _processWithGemini(text, currentEnergy);
  }

  void _processWithGemini(
    String text,
    String currentEnergy, {
    String? displayText,
  }) async {
    // Get User Context
    final userProfileAsync = ref.read(userProfileProvider);
    final userPrefsAsync = ref.read(preferencesProvider);

    final profile = userProfileAsync.value ?? UserProfile(uid: 'unknown');
    final prefs = userPrefsAsync.value ?? AppPreferences();

    final gemini = ref.read(geminiServiceProvider);
    final response = await gemini.getSuggestion(
      transcript: text,
      profile: profile,
      prefs: prefs,
      energyLevel: currentEnergy,
      history: state.history,
    );

    final userContent = displayText ?? text;

    // Update History
    final newHistory = List<Map<String, String>>.from(state.history);
    newHistory.add({'role': 'user', 'content': userContent});
    newHistory.add({'role': 'model', 'content': response.suggestion});
    if (newHistory.length > 8) newHistory.removeRange(0, newHistory.length - 8);

    state = state.copyWith(
      state: VoiceState.speaking,
      response: response,
      history: newHistory,
    );

    // Log it
    _logDecision(userContent, response, currentEnergy);
  }

  void confirmAction(AyuelAction action) async {
    final firestore = ref.read(firestoreServiceProvider);
    if (state.logId != null) {
      await firestore.updateDecisionAction(state.logId!, action.label);
    }

    if (action.type == 'timer') {
      // Parse duration from label? Or generic?
      // "Start 5m timer" -> 5 minutes.
      // Simple parsing:
      int minutes = 5;
      final RegExp regExp = RegExp(r'(\d+)\s*m');
      final match = regExp.firstMatch(action.label);
      if (match != null) {
        minutes = int.parse(match.group(1)!);
      }

      _startTimer(Duration(minutes: minutes));
      // Do NOT reset UI, showing timer instead
    } else if (action.type == 'regenerate') {
      reset();
    } else {
      reset();
    }
  }

  void _startTimer(Duration duration) {
    state = state.copyWith(
      timerDuration: duration,
      state: VoiceState.idle,
      response: null,
    );
  }

  void timerFinished() {
    print("🔴 timerFinished - resetting state");
    state = state.copyWith(
      timerDuration: null,
      response: null,
      state: VoiceState.idle,
    );
    final tts = ref.read(ttsServiceProvider);
    tts.speak("Time's up! Great job.");
    // Auto-restart monitoring
    startMonitoring();
  }

  void stopTimer() {
    print("🔴 stopTimer called - resetting state");
    state = state.copyWith(
      timerDuration: null,
      response: null,
      state: VoiceState.idle,
    );
    startMonitoring();
  }

  void cancel() async {
    final stt = ref.read(sttServiceProvider);
    await stt.cancel();
    state = state.copyWith(
      state: VoiceState.idle,
      transcript: "",
      response: null,
      logId: null,
    );
  }

  void startMonitoring() async {
    // Only start if idle or already monitoring (restart)
    if (state.state != VoiceState.idle && state.state != VoiceState.monitoring)
      return;

    final stt = ref.read(sttServiceProvider);
    // Only update state if not already monitoring (to avoid flicker)
    if (state.state != VoiceState.monitoring) {
      state = state.copyWith(state: VoiceState.monitoring, transcript: "");
    }

    await stt.startListening(
      listenFor: const Duration(minutes: 5), // Restart periodically
      pauseFor: const Duration(seconds: 4), // Silence confirms command end
      onResult: (text) {
        if (state.state == VoiceState.monitoring) {
          if (_containsWakeWord(text)) {
            print("🚀 Wake Word Detected: $text");
            HapticFeedback.mediumImpact();
            // Clear previous transcript segments
            state = state.copyWith(state: VoiceState.listening, transcript: "");
          }
        } else if (state.state == VoiceState.listening) {
          // In listening mode, we capture the command
          state = state.copyWith(transcript: text);
        }
      },
      onStatus: (status) {
        if (status == "done" || status == "notListening") {
          if (state.state == VoiceState.listening) {
            // End of command detected via silence
            if (state.transcript.isNotEmpty) {
              print("🚀 Auto-submitting command: ${state.transcript}");
              // Default energy to "Okay" for hands-free
              stopListeningAndThink("Okay");
            } else {
              // Nothing said? back to monitor
              startMonitoring();
            }
          } else if (state.state == VoiceState.monitoring) {
            // Restart monitoring loop
            startMonitoring();
          }
        }
      },
    );
  }

  bool _containsWakeWord(String text) {
    final t = text.toLowerCase();
    // Phonetic variations of "Hey Ayuel"
    return t.contains("hey ayuel") ||
        t.contains("hey i will") ||
        t.contains("hey are you") ||
        t.contains("hey a yule") ||
        t.contains("hi ayuel") ||
        t.contains("hey oil");
  }

  void reset() {
    state = state.copyWith(
      state: VoiceState.idle,
      transcript: "",
      response: null,
      logId: null,
      timerDuration: null,
    );
    // Restart monitoring after reset
    startMonitoring();
  }

  void _logDecision(String transcript, AyuelResponse response, String energy) {
    final firestore = ref.read(firestoreServiceProvider);
    final newId = const Uuid().v4();

    state = state.copyWith(logId: newId); // Track ID

    final log = DecisionLog(
      id: newId,
      createdAt: DateTime.now(),
      transcript: transcript,
      category: response.category,
      responseTitle: response.title,
      suggestion: response.suggestion,
      why: response.why,
      actions: response.actions,
      energy: energy,
    );
    firestore.logDecision(log);
  }
}

final voiceControllerProvider =
    NotifierProvider<VoiceControllerNotifier, VoiceSessionState>(() {
      return VoiceControllerNotifier();
    });
