// packages/feature_game_sequence/lib/controllers/sequence_game_controller.dart

import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
import '../models/sequence_models.dart';

enum SequenceGameState {
  idle,       
  presenting, 
  postDelay,  
  input,      
  processing, 
  completed,  
}

class SequenceGameController with ChangeNotifier {
  late SequenceDifficulty difficulty;
  late String userId;
  late String? userName;

  SequenceGameState _currentState = SequenceGameState.idle;
  SequenceGameState get currentState => _currentState;

  List<SequenceButtonId> _currentSequence = [];
  List<SequenceButtonId> get currentSequence => _currentSequence;
  List<SequenceButtonId> _userInput = [];
  List<SequenceButtonId> get userInput => _userInput;
  
  late List<String> _activeSymbolPool;
  List<String> get activeSymbolPool => _activeSymbolPool; 

  int _currentSequenceLength = 0;
  int get currentSequenceLength => _currentSequenceLength;
  
  int _maxAchievedLength = 0;
  int get maxAchievedLength => _maxAchievedLength;
  
  int _roundsCompleted = 0;
  int get roundsCompleted => _roundsCompleted;
  
  int _roundsFailed = 0;
  int get roundsFailed => _roundsFailed;
  
  SequenceButtonId? _activePresentationId;
  SequenceButtonId? get activePresentationId => _activePresentationId;
  
  bool _isLastInputCorrect = true;
  bool get isLastInputCorrect => _isLastInputCorrect;
  
  bool _showFeedback = false;
  bool get showFeedback => _showFeedback;

  Timer? _scoreTimer;
  Timer? _roundTimer;
  double _remainingRoundTime = 0.0;
  double get remainingRoundTime => _remainingRoundTime;
  
  int _secondsElapsed = 0;
  int get secondsElapsed => _secondsElapsed;

  int _presentationStep = 0;
  int get presentationStep => _presentationStep;
  
  set presentationStep(int step) {
    _presentationStep = step;
    notifyListeners();
  }
  
  final Random _random = Random();

  String getSymbolForId(SequenceButtonId id) {
    if (id.index >= _activeSymbolPool.length) {
      return '?'; 
    }
    return _activeSymbolPool[id.index];
  }

  void setUserInfo(String userId, String? userName) {
    this.userId = userId;
    this.userName = userName;
  }

  void startNewGame(SequenceDifficulty level) {
    difficulty = level;
    _currentSequence.clear();
    _userInput.clear();
    _currentSequenceLength = level.initialLength;
    _maxAchievedLength = level.initialLength - 1; 
    _currentState = SequenceGameState.idle;
    _secondsElapsed = 0;
    _roundsCompleted = 0;
    _roundsFailed = 0;
    _showFeedback = false;
    _activePresentationId = null;
    _presentationStep = 0;
    
    _initializeSymbolPool();
    
    WidgetsBinding.instance.addPostFrameCallback((_) {
      _startPresentationPhase();
    });
    notifyListeners();
  }
  
  void restartGame() {
      startNewGame(difficulty);
  }

  void setActivePresentation(SequenceButtonId? id) {
    _activePresentationId = id;
    notifyListeners();
  }

  // 🔽 [🔥 수정] 레벨 10 이상만 믹스, 나머지는 단일 테마
  void _initializeSymbolPool() {
    if (difficulty.levelIndex >= 10) {
      // Lv 10+: 모든 풀을 합치고 섞음 (Mixed)
      final List<String> allSymbols = [
        ...SequenceDifficulties.getSymbolPool(SequenceContentPool.number),
        ...SequenceDifficulties.getSymbolPool(SequenceContentPool.letter),
        ...SequenceDifficulties.getSymbolPool(SequenceContentPool.koreanChar),
        ...SequenceDifficulties.getSymbolPool(SequenceContentPool.emoji),
        // (단어는 길이가 길어 혼합 시 시각적 밸런스를 위해 제외하거나 포함 가능. 여기선 제외)
      ];
      _activeSymbolPool = (allSymbols..shuffle()).sublist(0, difficulty.buttonsCount); 
    } else {
      // Lv 1~9: 지정된 단일 풀 사용
      _activeSymbolPool = SequenceDifficulties.getSymbolPool(difficulty.contentPoolType);
    }
  }


  void _startPresentationPhase() {
    _roundTimer?.cancel();
    _currentState = SequenceGameState.presenting;
    _presentationStep = 0;
    _generateNextSequence();
    notifyListeners();
  }

  void _generateNextSequence() {
    _currentSequence.clear();
    final int maxIndex = difficulty.buttonsCount;
    for (int i = 0; i < _currentSequenceLength; i++) {
      final int randIndex = _random.nextInt(maxIndex);
      _currentSequence.add(SequenceButtonId.values[randIndex]);
    }
  }
  
  void runPostPresentationDelay() {
    _currentState = SequenceGameState.postDelay; 
    notifyListeners();
    
    Future.delayed(const Duration(milliseconds: 1000), () {
        if (currentState == SequenceGameState.postDelay) {
            startInputPhase();
        }
    });
  }

  void startInputPhase() {
    _startScoreTimer(); 

    _userInput.clear();
    _currentState = SequenceGameState.input;
    _startRoundTimer();
    notifyListeners();
  }

  void _startRoundTimer() {
    _roundTimer?.cancel();
    _remainingRoundTime = difficulty.roundTimeLimit;
    _roundTimer = Timer.periodic(const Duration(milliseconds: 100), (timer) {
      if (_remainingRoundTime <= 0) {
        _roundTimer?.cancel();
        _roundsFailed++;
        _handleFeedbackAndTermination();
      } else {
        _remainingRoundTime -= 0.1;
        notifyListeners();
      }
    });
  }

  void _startScoreTimer() {
    _scoreTimer?.cancel();
    _scoreTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
      _secondsElapsed++;
    });
  }

  void recordUserInput(SequenceButtonId inputId) {
    if (_currentState != SequenceGameState.input || _showFeedback) return;
    
    _userInput.add(inputId);
    _currentState = SequenceGameState.processing;
    notifyListeners();
    
    Future.delayed(const Duration(milliseconds: 100), () {
        _checkUserInput();
    });
  }

  void _checkUserInput() {
    if (_currentState != SequenceGameState.processing) return;
    
    final int inputLength = _userInput.length;
    final int currentInputIndex = inputLength - 1;
    
    if (_userInput[currentInputIndex] != _currentSequence[currentInputIndex]) {
      _roundsFailed++;
      _isLastInputCorrect = false;
      _handleFeedbackAndTermination();
      return;
    }
    
    _isLastInputCorrect = true;
    
    if (inputLength == _currentSequenceLength) {
      _roundsCompleted++;
      _maxAchievedLength = _currentSequenceLength;
      
      _handleFeedbackAndNextRound();
      return;
    }
    
    _currentState = SequenceGameState.input;
    notifyListeners();
  }

  void _handleFeedbackAndTermination() {
    _stopAllTimers();
    _showFeedback = true;
    notifyListeners();
    
    Future.delayed(const Duration(seconds: 1), () {
        _stopAllTimers();
        _currentState = SequenceGameState.completed;
        _showFeedback = false;
        notifyListeners();
    });
  }

  void _handleFeedbackAndNextRound() {
    _roundTimer?.cancel();
    _showFeedback = true;
    notifyListeners();
    
    Future.delayed(const Duration(milliseconds: 1000), () {
        _showFeedback = false;
        
        if (_currentSequenceLength < difficulty.maxGameLength) {
          _currentSequenceLength++;
        } else {
          _stopAllTimers();
          _currentState = SequenceGameState.completed;
          notifyListeners();
          return;
        }
        
        _startPresentationPhase();
    });
  }

  void _stopAllTimers() {
      _scoreTimer?.cancel();
      _roundTimer?.cancel();
  }
  
  @override
  void dispose() {
    _stopAllTimers();
    super.dispose();
  }
}