/**
 * Automated Permission Controller
 * Handles TMS permission automation with username suffix logic
 * 
 * Username Suffix Rules:
 * - (DM) or (DM/QC) → RW (Read/Write)
 * - (L) → R (Read Only)
 * - Other → Skip
 */

import { mongodbService } from '../services/mongodb.service';
import { tmsApiService, langToLocale } from '../services/tms-api.service';
import { supabaseService } from '../services/supabase.service';
import { logger } from '../utils/logger';
import type {
  SubmissionInput,
  ParsedGeInput,
  SubmissionResult,
  PermissionType,
} from '../types';



/**
 * Parse ge_input string into structured data
 * Format: "1000 de\n1001 us final"
 */
export function parseGeInput(geInput: string): ParsedGeInput[] {
  const lines = geInput.trim().split('\n').filter(Boolean);
  const parsed: ParsedGeInput[] = [];

  for (const line of lines) {
    const parts = line.trim().split(/\s+/);
    if (parts.length < 2) continue;

    const ge_id = parts[0];
    const langPart = parts[1];
    const final = parts.some(p => p.toLowerCase() === 'final');

    // Extract base language (remove _FINAL suffix if present)
    const lang = langPart.replace(/_FINAL$/i, '').toLowerCase();

    parsed.push({ ge_id, lang, final });
  }

  return parsed;
}

/**
 * Extract permission type from username suffix
 * Returns null if username should be skipped
 */
export function extractPermissionType(username: string): PermissionType | null {
  const match = username.match(/\((.*?)\)$/);
  if (!match) return null;

  const suffix = match[1].toUpperCase();

  // RW permissions
  if (suffix === 'DM' || suffix === 'DM/QC') {
    return 'RW';
  }

  // R permissions
  if (suffix === 'L') {
    return 'R';
  }

  // Unknown suffix - skip
  return null;
}

/**
 * Process single username for single GE/lang combination
 */
export async function processPermission(
  username: string,
  geId: string,
  lang: string,
  final: boolean
): Promise<SubmissionResult> {
  try {
    logger.debug('Processing permission', { username, geId, lang, final });

    // Step 1: Get TMS ID from MongoDB and build URL with locale
    const tmsId = await mongodbService.getTmsId(geId, lang);
    const locale = langToLocale(lang);
    const tmsUrl = `https://tms.kiledel.com/project/${tmsId}?l=${locale}`;
    const projectId = parseInt(tmsId, 10);

    logger.debug('TMS ID found', { geId, lang, tmsId, locale });

    // Step 2: Resolve username to email
    let email: string;
    try {
      email = await tmsApiService.resolveUsernameToEmail(username);
      logger.debug('Username resolved to email', { username, email });
    } catch (error: any) {
      return {
        ge_id: geId,
        lang,
        tms_id: tmsId,
        tms_url: tmsUrl,
        username,
        status: 'error',
        message: `Không tìm thấy user: ${username}`,
        processed_at: new Date().toISOString(),
      };
    }

    // Step 3: Get project details for the specific locale
    const projectDetails = await tmsApiService.getProjectDetails(projectId, lang);

    // Step 4: Extract permission type from username
    const permissionType = extractPermissionType(username);

    if (!permissionType) {
      return {
        ge_id: geId,
        lang,
        tms_id: tmsId,
        tms_url: tmsUrl,
        username,
        status: 'error',
        message: `Username ${username} không có suffix hợp lệ - Bỏ qua`,
        processed_at: new Date().toISOString(),
      };
    }

    logger.debug('Permission type extracted', { username, permissionType });

    // Step 5: Check if user exists in project members (by email)
    const existsInProject = projectDetails.members[email];

    logger.debug('User membership status', {
      username,
      email,
      existsInProject: !!existsInProject,
      currentProjectRole: existsInProject || 'none',
    });

    // Step 6: Add to project member if not exists (common for both R and RW)
    let message = '';

    if (!existsInProject) {
      logger.debug('Adding user to project members', { username, email });
      await tmsApiService.addProjectMember(projectId, email, lang);
      message += `Đã thêm vào Project Members. `;
    }

    // Step 7: Process based on permission type
    // Case 1: User needs R permission (role L)
    if (permissionType === 'R') {
      // R is granted automatically when added to project members
      if (existsInProject) {
        message = `Đã có quyền R`;
      } else {
        message += `Cấp quyền R thành công.`;
      }

      return {
        ge_id: geId,
        lang,
        tms_id: tmsId,
        tms_url: tmsUrl,
        username,
        status: 'success',
        message,
        processed_at: new Date().toISOString(),
      };
    }

    // Case 2: User needs RW permission (role DM or DM/QC)
    // Log all subsets for debugging
    logger.debug('Available subsets', {
      subsets: projectDetails.subsets.map(s => ({ id: s.id, title: s.title, lang: s.lang })),
    });

    // Find QC subset (for DM/DM/QC role, grant RW to QC subset)
    const qcSubset = projectDetails.subsets.find(
      s => s.title.toUpperCase() === 'QC' || s.title.toUpperCase().includes('QC')
    );

    if (!qcSubset) {
      return {
        ge_id: geId,
        lang,
        tms_id: tmsId,
        tms_url: tmsUrl,
        username,
        status: 'error',
        message: message + `Subset QC không tồn tại trong project`,
        processed_at: new Date().toISOString(),
      };
    }

    logger.debug('QC subset found', {
      subsetId: qcSubset.id,
      subsetTitle: qcSubset.title,
    });

    // Check if user already has RW permission in QC subset
    const currentQcRole = qcSubset.members[email];

    if (currentQcRole === 'RW') {
      logger.debug('User already has RW in QC subset, skipping', {
        username,
        email,
        subsetTitle: qcSubset.title,
      });
      message += `Đã có quyền RW ở cột ${qcSubset.title}.`;
    } else {
      // Grant RW to QC subset
      logger.debug('Granting RW to QC subset', {
        username,
        email,
        subsetId: qcSubset.id,
        subsetTitle: qcSubset.title,
      });
      await tmsApiService.grantSubsetPermission(
        projectId,
        qcSubset.id,
        email,
        'RW',
        lang
      );
      message += `Đã cấp quyền RW cho cột ${qcSubset.title}.`;
    }

    // Grant RW to FINAL subset if requested
    if (final) {
      // Find FINAL subset - just look for subset with title containing "FINAL"
      const finalSubset = projectDetails.subsets.find(
        s => s.title.toUpperCase() === 'FINAL' || s.title.toUpperCase().includes('FINAL')
      );

      if (finalSubset) {
        // Check if user already has RW in FINAL subset
        const currentFinalRole = finalSubset.members[email];

        if (currentFinalRole === 'RW') {
          logger.debug('User already has RW in FINAL subset, skipping', {
            username,
            email,
            subsetTitle: finalSubset.title,
          });
          message += ` Đã có quyền RW ở cột  ${finalSubset.title}.`;
        } else {
          logger.debug('Granting RW to FINAL subset', {
            username,
            email,
            subsetId: finalSubset.id,
            subsetTitle: finalSubset.title,
          });
          await tmsApiService.grantSubsetPermission(
            projectId,
            finalSubset.id,
            email,
            'RW',
            lang
          );
          message += ` Đã cấp quyền RW cho cột ${finalSubset.title}.`;
        }
      } else {
        message += ` Không tìm thấy FINAL subset.`;
      }
    }

    return {
      ge_id: geId,
      lang,
      tms_id: tmsId,
      tms_url: tmsUrl,
      username,
      status: 'success',
      message,
      processed_at: new Date().toISOString(),
    };
  } catch (error: any) {
    logger.error('Error processing permission', {
      username,
      geId,
      lang,
      error: error.message,
    });

    return {
      ge_id: geId,
      lang,
      tms_id: 'unknown',
      tms_url: '#',
      username,
      status: 'error',
      message: `Lỗi: ${error.message}`,
      processed_at: new Date().toISOString(),
    };
  }
}

/**
 * Process entire submission with multiple users and GE/langs
 */
export async function processSubmission(submissionId: string): Promise<void> {
  try {
    logger.debug('Processing submission', { submissionId });

    // Get submission from database
    const submission = await supabaseService.getSubmission(submissionId);

    if (!submission || !submission.input) {
      throw new Error('Submission not found or invalid');
    }

    // Mark as processing
    await supabaseService.updateSubmissionStatus(submissionId, 'processing');

    const input = submission.input as SubmissionInput;
    const { username_list, ge_input } = input;

    // Parse GE input
    const parsedGes = parseGeInput(ge_input);

    if (parsedGes.length === 0) {
      throw new Error('No valid GE entries in input');
    }

    logger.debug('Parsed GE input', {
      submissionId,
      geCount: parsedGes.length,
      userCount: username_list.length,
    });

    const results: SubmissionResult[] = [];

    // Process each GE/lang combination
    for (const { ge_id, lang, final } of parsedGes) {
      try {
        // Step 1: Get TMS ID and project details
        const tmsId = await mongodbService.getTmsId(ge_id, lang);
        const projectId = parseInt(tmsId, 10);
        const projectDetails = await tmsApiService.getProjectDetails(projectId, lang);



        // Step 3: Process each username
        for (const username of username_list) {
          const result = await processPermission(username, ge_id, lang, final);
          results.push(result);

          // Small delay to avoid rate limiting
          await new Promise(resolve => setTimeout(resolve, 500));
        }

        // Save results after each GE ID is fully processed (for real-time UI updates)
        await supabaseService.updateSubmissionStatus(submissionId, 'processing', results);

      } catch (error: any) {
        logger.error('Error processing GE', {
          ge_id,
          lang,
          error: error.message,
        });

        // Add error results for all users for this GE
        for (const username of username_list) {
          results.push({
            ge_id,
            lang,
            tms_id: 'unknown',
            tms_url: '#',
            username,
            status: 'error',
            message: `Lỗi xử lý GE ${ge_id} ${lang}: ${error.message}`,
            processed_at: new Date().toISOString(),
          });
        }

        // Save error results immediately for real-time UI updates
        await supabaseService.updateSubmissionStatus(submissionId, 'processing', results);
      }
    }

    // Determine final status
    const hasErrors = results.some(r => r.status === 'error');
    const finalStatus = hasErrors ? 'failed' : 'completed';

    // Update submission with results
    await supabaseService.updateSubmissionStatus(
      submissionId,
      finalStatus,
      results
    );

    logger.debug('Submission processing complete', {
      submissionId,
      status: finalStatus,
      totalResults: results.length,
      successCount: results.filter(r => r.status === 'success').length,
      errorCount: results.filter(r => r.status === 'error').length,
    });
  } catch (error: any) {
    logger.error('Fatal error processing submission', {
      submissionId,
      error: error.message,
    });

    // Mark as failed
    await supabaseService.updateSubmissionStatus(
      submissionId,
      'failed',
      [],
      error.message
    );
  }
}
