// packages/feature_game_cardflip/lib/controllers/cardflip_controller.dart

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

class CardFlipController with ChangeNotifier {
  late CardFlipDifficulty difficulty;
  late String userId;
  late String? userName;

  List<CardItem> _cards = [];
  List<CardItem> get cards => _cards;

  CardItem? _firstFlippedCard;
  
  bool _isProcessing = false;
  bool get isProcessing => _isProcessing;

  bool _isGameCompleted = false;
  bool get isGameCompleted => _isGameCompleted;
  
  bool _isTimeOut = false;
  bool get isTimeOut => _isTimeOut;

  int _flipCount = 0;
  int get flipCount => _flipCount;

  Timer? _timer;
  int _secondsElapsed = 0;
  int _remainingTime = 0;
  int get remainingTime => _remainingTime;
  
  bool _isGameStarted = false;
  bool get isGameStarted => _isGameStarted;

  int get matchedPairsCount => _cards.where((c) => c.isMatched).length ~/ 2;
  int get totalPairsCount => _cards.length ~/ 2;

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

  void startNewGame(CardFlipDifficulty level) {
    difficulty = level;
    _flipCount = 0;
    _secondsElapsed = 0;
    _remainingTime = level.timeLimitSeconds;
    _isGameCompleted = false;
    _isTimeOut = false;
    _isProcessing = false;
    _isGameStarted = false;
    _firstFlippedCard = null;

    _generateCards();
    notifyListeners();
  }
  
  void restartGame() {
    startNewGame(difficulty);
  }

  void startGameTimer() {
    if (_isGameStarted) return;
    _isGameStarted = true;
    
    _timer?.cancel();
    _timer = Timer.periodic(const Duration(seconds: 1), (timer) {
      _secondsElapsed++;
      _remainingTime--;
      
      if (_remainingTime <= 0) {
        _timer?.cancel();
        _isTimeOut = true;
        _isGameCompleted = true;
      }
      notifyListeners();
    });
    notifyListeners();
  }

  void _generateCards() {
    final int totalCards = difficulty.totalCards;
    final int pairsCount = totalCards ~/ 2;
    List<CardItem> deck = [];
    final Random random = Random();

    if (difficulty.contentType == CardContentType.calculation) {
      // [🔥 수정] 연산 모드
      final Set<int> usedResults = {};
      
      // 레벨 4인지 확인 (한 자릿수 덧셈/뺄셈만)
      final bool isLevel4 = difficulty.levelIndex == 4;

      for (int i = 0; i < pairsCount; i++) {
        String equation;
        String answer;
        int result;

        while (true) {
          // Lv 4: 0(덧셈), 1(뺄셈)만 선택 / 그 외: 0, 1, 2(곱셈) 선택
          final int opType = isLevel4 ? random.nextInt(2) : random.nextInt(3);
          int a, b;

          if (opType == 0) { // 덧셈 (+)
            if (isLevel4) {
              // 한 자릿수 (1~9)
              a = random.nextInt(9) + 1; 
              b = random.nextInt(9) + 1;
            } else {
              // 두 자릿수 포함 (1~15)
              a = random.nextInt(15) + 1; 
              b = random.nextInt(15) + 1;
            }
            result = a + b;
            equation = "$a + $b";

          } else if (opType == 1) { // 뺄셈 (-)
            if (isLevel4) {
              // 결과가 양수이고 한 자릿수 내에서 처리되도록
              a = random.nextInt(9) + 2; // 2~10
              b = random.nextInt(a - 1) + 1;
            } else {
              a = random.nextInt(20) + 5; 
              b = random.nextInt(a - 1) + 1;
            }
            result = a - b;
            equation = "$a - $b";

          } else { // 곱셈 (*)
            // Lv 4에서는 이 블록에 들어오지 않음
            a = random.nextInt(9) + 2;
            b = random.nextInt(5) + 2;
            result = a * b;
            equation = "$a x $b";
          }

          // 정답 중복 방지
          if (!usedResults.contains(result)) {
            usedResults.add(result);
            answer = result.toString();
            break;
          }
        }

        String matchKey = "CALC_$i";
        deck.add(CardItem(id: 0, matchId: matchKey, displayContent: equation));
        deck.add(CardItem(id: 0, matchId: matchKey, displayContent: answer));
      }
    } 
    else if (difficulty.contentType == CardContentType.pairWord) {
      // 연상 모드
      var entries = CardFlipDifficulties.wordPairs.entries.toList()..shuffle();
      for (int i = 0; i < pairsCount; i++) {
        var entry = entries[i % entries.length];
        String matchKey = "PAIR_$i";
        deck.add(CardItem(id: 0, matchId: matchKey, displayContent: entry.key));
        deck.add(CardItem(id: 0, matchId: matchKey, displayContent: entry.value));
      }
    } 
    else {
      // 동일 매칭 모드
      List<String> pool = List.of(CardFlipDifficulties.emojis)..shuffle();
      for (int i = 0; i < pairsCount; i++) {
        String content;
        String matchKey = "SAME_$i";
        
        if (difficulty.contentType == CardContentType.number) {
          content = (i + 1).toString();
        } else if (difficulty.contentType == CardContentType.icon) {
          content = "ICON_$i";
        } else {
          content = pool[i % pool.length];
        }
        
        deck.add(CardItem(id: 0, matchId: matchKey, displayContent: content));
        deck.add(CardItem(id: 0, matchId: matchKey, displayContent: content));
      }
    }

    deck.shuffle(random);
    for (int i = 0; i < deck.length; i++) {
      deck[i] = CardItem(
        id: i, 
        matchId: deck[i].matchId, 
        displayContent: deck[i].displayContent
      );
    }
    _cards = deck;
  }

  void onCardTapped(CardItem card) {
    if (!_isGameStarted || _isGameCompleted || _isProcessing || card.isFaceUp || card.isMatched) return;

    card.isFaceUp = true;
    _flipCount++;
    notifyListeners();

    if (_firstFlippedCard == null) {
      _firstFlippedCard = card;
    } else {
      _isProcessing = true;
      _checkMatch(_firstFlippedCard!, card);
      _firstFlippedCard = null;
    }
  }

  void _checkMatch(CardItem card1, CardItem card2) {
    if (card1.matchId == card2.matchId) {
      card1.isMatched = true;
      card2.isMatched = true;
      _isProcessing = false;
      
      if (_cards.every((c) => c.isMatched)) {
        _isGameCompleted = true;
        _timer?.cancel();
      }
      notifyListeners();
    } else {
      Future.delayed(const Duration(milliseconds: 800), () {
        card1.isFaceUp = false;
        card2.isFaceUp = false;
        _isProcessing = false;
        notifyListeners();
      });
    }
  }

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