import BaseService from './BaseService.js';
import TaxiGameState from '../models/taxi/taxiGameState.js';
import TaxiLevelStats from '../models/taxi/taxiLevelStats.js';
import User from '../models/community/user.js';

class TaxiService extends BaseService {
  constructor() {
    super();
  }

  // Hilfsmethode: Konvertiere hashedId zu userId
  async getUserIdFromHashedId(hashedUserId) {
    const user = await User.findOne({ where: { hashedId: hashedUserId } });
    if (!user) {
      throw new Error('User not found');
    }
    return user.id;
  }

  // Spielstand abrufen
  async getGameState(hashedUserId) {
    try {
      const userId = await this.getUserIdFromHashedId(hashedUserId);

      let gameState = await TaxiGameState.findOne({
        where: { userId }
      });

      if (!gameState) {
        // Erstelle neuen Spielstand
        gameState = await TaxiGameState.create({
          userId,
          currentLevel: 1,
          totalScore: 0,
          totalMoney: 0,
          totalPassengersDelivered: 0,
          unlockedLevels: [1],
          achievements: [] 
        });
      }

      return {
        currentLevel: gameState.currentLevel,
        totalScore: gameState.totalScore,
        totalMoney: gameState.totalMoney,
        totalPassengersDelivered: gameState.totalPassengersDelivered,
        unlockedLevels: gameState.unlockedLevels,
        achievements: gameState.achievements
      };
    } catch (error) {
      console.error('Error getting taxi game state:', error);
      throw error;
    }
  }

  // Spielstand speichern
  async saveGameState(hashedUserId, gameData) {
    try {
      const userId = await this.getUserIdFromHashedId(hashedUserId);
      const { level, score, money, passengersDelivered, fuel } = gameData;

      const [gameState, created] = await TaxiGameState.findOrCreate({
        where: { userId },
        defaults: {
          userId,
          currentLevel: level || 1,
          totalScore: score || 0,
          totalMoney: money || 0,
          totalPassengersDelivered: passengersDelivered || 0,
          unlockedLevels: [1],
          achievements: []
        }
      });

      if (!created) {
        // Aktualisiere bestehenden Spielstand
        await gameState.update({
          currentLevel: Math.max(gameState.currentLevel, level || 1),
          totalScore: Math.max(gameState.totalScore, score || 0),
          totalMoney: Math.max(gameState.totalMoney, money || 0),
          totalPassengersDelivered: Math.max(gameState.totalPassengersDelivered, passengersDelivered || 0)
        });
      }

      return {
        currentLevel: gameState.currentLevel,
        totalScore: gameState.totalScore,
        totalMoney: gameState.totalMoney,
        totalPassengersDelivered: gameState.totalPassengersDelivered,
        unlockedLevels: gameState.unlockedLevels,
        achievements: gameState.achievements
      };
    } catch (error) {
      console.error('Error saving taxi game state:', error);
      throw error;
    }
  }

  // Level-Statistiken abrufen
  async getLevelStats(hashedUserId, level) {
    try {
      const userId = await this.getUserIdFromHashedId(hashedUserId);
      const stats = await TaxiLevelStats.findOne({
        where: { userId, level }
      });

      if (!stats) {
        return {
          level,
          bestScore: 0,
          bestMoney: 0,
          bestPassengersDelivered: 0,
          timesPlayed: 0,
          completed: false
        };
      }

      return {
        level: stats.level,
        bestScore: stats.bestScore,
        bestMoney: stats.bestMoney,
        bestPassengersDelivered: stats.bestPassengersDelivered,
        timesPlayed: stats.timesPlayed,
        completed: stats.completed
      };
    } catch (error) {
      console.error('Error getting level stats:', error);
      throw error;
    }
  }

  // Bestenliste abrufen
  async getLeaderboard(type = 'score', limit = 10) {
    try {
      let orderBy;
      switch (type) {
        case 'money':
          orderBy = [['totalMoney', 'DESC']];
          break;
        case 'passengers':
          orderBy = [['totalPassengersDelivered', 'DESC']];
          break;
        case 'level':
          orderBy = [['currentLevel', 'DESC']];
          break;
        default:
          orderBy = [['totalScore', 'DESC']];
      }

      const leaderboard = await TaxiGameState.findAll({
        order: orderBy,
        limit: parseInt(limit),
        include: [{
          model: User,
          attributes: ['username', 'id']
        }]
      });

      return leaderboard.map((entry, index) => ({
        rank: index + 1,
        username: entry.User.username,
        userId: entry.User.id,
        score: entry.totalScore,
        money: entry.totalMoney,
        passengers: entry.totalPassengersDelivered,
        level: entry.currentLevel
      }));
    } catch (error) {
      console.error('Error getting leaderboard:', error);
      throw error;
    }
  }

  // Spiel beenden und Punkte verarbeiten
  async finishGame(hashedUserId, gameData) {
    try {
      const userId = await this.getUserIdFromHashedId(hashedUserId);
      const { finalScore, finalMoney, passengersDelivered, level } = gameData;

      // Aktualisiere Spielstand
      const gameState = await this.saveGameState(userId, {
        level,
        score: finalScore,
        money: finalMoney,
        passengersDelivered
      });

      // Aktualisiere Level-Statistiken
      await this.updateLevelStats(hashedUserId, level, {
        score: finalScore,
        money: finalMoney,
        passengersDelivered
      });

      // Prüfe auf neue freigeschaltete Level
      const newUnlockedLevels = await this.checkUnlockedLevels(hashedUserId, level);

      // Prüfe auf neue Erfolge
      const newAchievements = await this.checkAchievements(hashedUserId, gameState);

      return {
        gameState,
        newUnlockedLevels,
        newAchievements
      };
    } catch (error) {
      console.error('Error finishing game:', error);
      throw error;
    }
  }

  // Level freischalten
  async unlockLevel(hashedUserId, level) {
    try {
      const userId = await this.getUserIdFromHashedId(hashedUserId);
      const gameState = await TaxiGameState.findOne({
        where: { userId }
      });

      if (!gameState) {
        throw new Error('Spielstand nicht gefunden');
      }

      const unlockedLevels = [...gameState.unlockedLevels];
      if (!unlockedLevels.includes(level)) {
        unlockedLevels.push(level);
        unlockedLevels.sort((a, b) => a - b);

        await gameState.update({
          unlockedLevels
        });
      }

      return { unlockedLevels };
    } catch (error) {
      console.error('Error unlocking level:', error);
      throw error;
    }
  }

  // Spieler-Statistiken abrufen
  async getPlayerStats(hashedUserId) {
    try {
      const userId = await this.getUserIdFromHashedId(hashedUserId);
      const gameState = await this.getGameState(hashedUserId);
      const levelStats = await TaxiLevelStats.findAll({
        where: { userId },
        order: [['level', 'ASC']]
      });

      const totalLevelsPlayed = levelStats.length;
      const completedLevels = levelStats.filter(stat => stat.completed).length;
      const totalPlayTime = levelStats.reduce((sum, stat) => sum + (stat.playTime || 0), 0);

      return {
        ...gameState,
        totalLevelsPlayed,
        completedLevels,
        totalPlayTime,
        levelStats: levelStats.map(stat => ({
          level: stat.level,
          bestScore: stat.bestScore,
          bestMoney: stat.bestMoney,
          bestPassengersDelivered: stat.bestPassengersDelivered,
          timesPlayed: stat.timesPlayed,
          completed: stat.completed
        }))
      };
    } catch (error) {
      console.error('Error getting player stats:', error);
      throw error;
    }
  }

  // Level zurücksetzen
  async resetLevel(hashedUserId, level) {
    try {
      const userId = await this.getUserIdFromHashedId(hashedUserId);
      await TaxiLevelStats.destroy({
        where: { userId, level }
      });

      return { success: true };
    } catch (error) {
      console.error('Error resetting level:', error);
      throw error;
    }
  }

  // Alle Spielstände zurücksetzen
  async resetAllProgress(hashedUserId) {
    try {
      const userId = await this.getUserIdFromHashedId(hashedUserId);
      await TaxiGameState.destroy({
        where: { userId }
      });

      await TaxiLevelStats.destroy({
        where: { userId }
      });

      return { success: true };
    } catch (error) {
      console.error('Error resetting all progress:', error);
      throw error;
    }
  }

  // Hilfsmethoden
  async updateLevelStats(hashedUserId, level, stats) {
    try {
      const userId = await this.getUserIdFromHashedId(hashedUserId);
      const { score, money, passengersDelivered } = stats;

      const [levelStat, created] = await TaxiLevelStats.findOrCreate({
        where: { userId, level },
        defaults: {
          userId,
          level,
          bestScore: score,
          bestMoney: money,
          bestPassengersDelivered: passengersDelivered,
          timesPlayed: 1,
          completed: true
        }
      });

      if (!created) {
        const updates = {
          timesPlayed: levelStat.timesPlayed + 1,
          completed: true
        };

        if (score > levelStat.bestScore) updates.bestScore = score;
        if (money > levelStat.bestMoney) updates.bestMoney = money;
        if (passengersDelivered > levelStat.bestPassengersDelivered) {
          updates.bestPassengersDelivered = passengersDelivered;
        }

        await levelStat.update(updates);
      }
    } catch (error) {
      console.error('Error updating level stats:', error);
      throw error;
    }
  }

  async checkUnlockedLevels(hashedUserId, currentLevel) {
    try {
      const userId = await this.getUserIdFromHashedId(hashedUserId);
      const gameState = await TaxiGameState.findOne({
        where: { userId }
      });

      if (!gameState) return [];

      const newUnlockedLevels = [];
      const nextLevel = currentLevel + 1;

      if (!gameState.unlockedLevels.includes(nextLevel)) {
        newUnlockedLevels.push(nextLevel);
        await this.unlockLevel(hashedUserId, nextLevel);
      }

      return newUnlockedLevels;
    } catch (error) {
      console.error('Error checking unlocked levels:', error);
      return [];
    }
  }

  async checkAchievements(hashedUserId, gameState) {
    try {
      const userId = await this.getUserIdFromHashedId(hashedUserId);
      const achievements = [];
      const currentAchievements = gameState.achievements || [];

      // Beispiel-Erfolge
      if (gameState.totalScore >= 1000 && !currentAchievements.includes('score_1000')) {
        achievements.push('score_1000');
      }

      if (gameState.totalPassengersDelivered >= 50 && !currentAchievements.includes('passengers_50')) {
        achievements.push('passengers_50');
      }

      if (gameState.currentLevel >= 10 && !currentAchievements.includes('level_10')) {
        achievements.push('level_10');
      }

      if (achievements.length > 0) {
        const newAchievements = [...currentAchievements, ...achievements];
        await TaxiGameState.update(
          { achievements: newAchievements },
          { where: { userId } }
        );
      }

      return achievements;
    } catch (error) {
      console.error('Error checking achievements:', error);
      return [];
    }
  }
}

export default TaxiService;
