import myTischtennisService from './myTischtennisService.js';
import myTischtennisFetchLogService from './myTischtennisFetchLogService.js';
import memberService from './memberService.js';
import MyTischtennis from '../models/MyTischtennis.js';
import Club from '../models/Club.js';
import UserClub from '../models/UserClub.js';
import { Op } from 'sequelize';
import { devLog } from '../utils/logger.js';

class AutoUpdateRatingsService {
  /**
   * Execute automatic rating updates for all clubs with autoFetchRankings enabled.
   * For each club, finds a user with MyTischtennis account and updates that club's members.
   */
  async executeAutomaticUpdates() {
    devLog('Starting automatic rating updates...');
    
    try {
      const clubs = await Club.findAll({
        where: { autoFetchRankings: true }
      });

      devLog(`Found ${clubs.length} clubs with autoFetchRankings enabled`);

      if (clubs.length === 0) {
        devLog('No clubs found with autoFetchRankings enabled');
        return { success: true, totalUpdated: 0, summaries: [] };
      }

      const summaries = [];
      for (const club of clubs) {
        const summary = await this.processClub(club);
        summaries.push({ clubId: club.id, clubName: club.name, ...summary });
      }

      devLog('Automatic rating updates completed');
      const totalUpdated = summaries.reduce((acc, s) => acc + (s.updatedCount || 0), 0);
      return { success: true, totalUpdated, summaries };
    } catch (error) {
      console.error('Error in automatic rating updates:', error);
      throw error;
    }
  }

  /**
   * Process a single club for rating updates.
   * Finds a user with MyTischtennis account (autoUpdateRatings, savePassword) and club access.
   */
  async processClub(club) {
    const startTime = Date.now();
    let success = false;
    let message = '';
    let errorDetails = null;
    let updatedCount = 0;
    let userId = null;

    try {
      const userClubs = await UserClub.findAll({
        where: { clubId: club.id, approved: true },
        attributes: ['userId']
      });

      const userIds = userClubs.map((uc) => uc.userId);
      if (userIds.length === 0) {
        throw new Error(`Keine freigeschalteten Benutzer für Verein "${club.name}" gefunden`);
      }

      const account = await MyTischtennis.findOne({
        where: {
          userId: { [Op.in]: userIds },
          autoUpdateRatings: true,
          savePassword: true
        }
      });

      if (!account) {
        throw new Error(`Kein myTischtennis-Account mit Auto-Update für Verein "${club.name}" gefunden`);
      }

      userId = account.userId;
      devLog(`Processing club ${club.name} (Club ID: ${club.id}) via User ${userId}`);

      if (!account.accessToken || !account.expiresAt || account.expiresAt < Date.now() / 1000) {
        devLog(`Session expired, attempting re-login via verifyLogin (incl. Playwright fallback)`);
        await myTischtennisService.verifyLogin(account.userId);
        const refreshed = await MyTischtennis.findOne({ where: { userId: account.userId } });
        if (!refreshed?.cookie) {
          throw new Error('Re-login via verifyLogin did not produce a valid session');
        }
        account.accessToken = refreshed.accessToken;
        account.refreshToken = refreshed.refreshToken;
        account.expiresAt = refreshed.expiresAt;
        account.cookie = refreshed.cookie;
        devLog(`Successfully re-logged in`);
      }

      const result = await memberService.updateRatingsFromMyTischtennisByUserId(account.userId, club.id);
      updatedCount = result?.response?.updated ?? 0;
      success = true;
      message = `Successfully updated ${updatedCount} ratings`;
      devLog(`Updated ${updatedCount} ratings for club ${club.name}`);

    } catch (error) {
      success = false;
      message = 'Update failed';
      errorDetails = error.message;
      console.error(`Error updating ratings for club ${club.name}:`, error);
    }

    const executionTime = Date.now() - startTime;

    if (userId) {
      await myTischtennisFetchLogService.logFetch(
        userId,
        'ratings',
        success,
        message,
        { errorDetails, recordsProcessed: updatedCount, executionTime, isAutomatic: true, clubId: club.id }
      );
      await myTischtennisService.logUpdateAttempt(userId, success, message, errorDetails, updatedCount, executionTime);
    }

    return { success, message, updatedCount, errorDetails, executionTime };
  }

  /**
   * Get all accounts with auto-updates enabled (for manual execution)
   */
  async getAutoUpdateAccounts() {
    return await MyTischtennis.findAll({
      where: {
        autoUpdateRatings: true
      },
      attributes: ['userId', 'email', 'autoUpdateRatings', 'lastUpdateRatings']
    });
  }
}

export default new AutoUpdateRatingsService();
