import { Request, Response } from 'express';
import { supabaseService } from '../services/supabase.service';
import { tmsApiService, langToLocale } from '../services/tms-api.service';
import { mongodbService } from '../services/mongodb.service';
import { logger } from '../utils/logger';
import type { ParsedCheckInput, CheckResult } from '../types';

/**
 * Normalize chapter format for processing
 * Converts raw chapter format (with 'x', '-') to standard format (numbers and '.')
 * 
 * Examples:
 * - "17-3x" -> "17.03"
 * - "3-14x" -> "3.14"
 * - "2.5" -> "2.5"
 * - "4.03" -> "4.03"
 */
function normalizeChapter(chapRaw: string): string {
    if (!chapRaw) {
        return chapRaw;
    }

    let chapNormalized = chapRaw;

    // Handle special case with format "-Nx" (e.g., "17-3x" -> "17.03")
    if (chapRaw.includes('-') && chapRaw.endsWith('x')) {
        // Split by "-" and remove "x"
        const parts = chapRaw.replace('x', '').split('-');
        if (parts.length === 2) {
            const mainPart = parts[0];
            const subPart = parts[1];

            // If sub part has only 1 digit, add leading zero
            if (subPart.length === 1) {
                chapNormalized = `${mainPart}.0${subPart}`;
            } else {
                chapNormalized = `${mainPart}.${subPart}`;
            }
        } else {
            // Fallback for non-standard format
            chapNormalized = chapRaw.replace('-', '.').replace('x', '');
        }
    } else {
        // Fallback: simple replacement for cases without both '-' and 'x' (e.g., "2.5" -> "2.5", "17" -> "17")
        chapNormalized = chapRaw.replace('-', '.').replace('x', '');
    }

    // Remove trailing dots if any
    chapNormalized = chapNormalized.replace(/\.$/, '');

    // Remove trailing zeros after decimal point (e.g., "92.30" -> "92.3", "17.00" -> "17")
    if (chapNormalized.includes('.')) {
        chapNormalized = chapNormalized.replace(/\.?0+$/, '');
        // If we removed all digits after decimal, remove the decimal point too
        chapNormalized = chapNormalized.replace(/\.$/, '');
    }

    return chapNormalized;
}

/**
 * Parse check input string into structured data
 * Format: First word = GE_ID, Second word = LANG, Last word = CHAP (or second-to-last if last is [...])
 * Other words in between are ignored
 * Examples:
 *   "4164 FR 3" -> { ge_id: "4164", lang: "FR", chapter: "3" }
 *   "4164 FR Extra Info 3" -> { ge_id: "4164", lang: "FR", chapter: "3" }
 *   "2637 DE 만져도 돼? 26-7x [외전]" -> { ge_id: "2637", lang: "DE", chapter: "26.07" }
 */
function parseCheckInput(input: string): ParsedCheckInput[] {
    const lines = input.split('\n').filter(line => line.trim());
    const parsed: ParsedCheckInput[] = [];

    for (const line of lines) {
        const parts = line.trim().split(/\s+/); // Split by whitespace (tab or space)
        if (parts.length >= 3) {
            // Find chapter: last word, but skip if it's in [...] format
            let chapterIndex = parts.length - 1;
            if (/^\[.*\]$/.test(parts[chapterIndex]) && parts.length >= 4) {
                chapterIndex = parts.length - 2;
            }
            
            parsed.push({
                ge_id: parts[0],                           // First word = GE ID
                lang: parts[1].toUpperCase(),              // Second word = LANG
                chapter: normalizeChapter(parts[chapterIndex]), // Last word (or second-to-last if last is [...])
            });
        }
    }
    return parsed;
}

/**
 * Process check for a single item
 */
async function processSingleCheck(item: ParsedCheckInput): Promise<CheckResult> {
    const { ge_id, lang, chapter } = item;

    try {
        // 1. Get TMS ID from MongoDB
        let tmsId: string;
        try {
            tmsId = await mongodbService.getTmsId(ge_id, lang);
        } catch (error) {
            return {
                ge_id,
                lang,
                chapter,
                status: 'ERROR',
                message: 'TMS ID not found',
            };
        }

        const projectId = parseInt(tmsId, 10);
        // Convert lang to locale using centralized mapping
        const locale = langToLocale(lang);
        const tmsUrl = `https://tms.kiledel.com/project/${projectId}?l=${locale}`;

        // 2. Get Project Details (with Auto Access)
        const projectDetails = await tmsApiService.getProjectDetailsWithAutoAccess(projectId, lang);

        // 3. Find QC Workspace
        const subsets = projectDetails.subsets;
        const qcSubset = subsets.find(s => s.title.toUpperCase() === 'QC');

        if (!qcSubset) {
            const available = subsets.map(s => s.title).join(', ');
            return {
                ge_id,
                lang,
                chapter,
                status: 'ERROR',
                message: `Subset "QC" not found. Available: ${available}`,
                tms_url: tmsUrl
            };
        }

        // 4. Check Episodes
        const episodes = qcSubset.episodes || {};

        if (episodes[chapter]) {
            return {
                ge_id,
                lang,
                chapter,
                status: 'FOUND',
                message: 'ĐÃ CÓ',
                tms_url: tmsUrl
            };
        } else {
            return {
                ge_id,
                lang,
                chapter,
                status: 'NOT_FOUND',
                message: 'CHƯA CÓ',
                tms_url: tmsUrl
            };
        }

    } catch (error: any) {
        return {
            ge_id,
            lang,
            chapter,
            status: 'ERROR',
            message: error.message,
        };
    }
}

/**
 * Background processing function with parallel execution
 * Processes items in batches of BATCH_SIZE for better performance
 */
const BATCH_SIZE = 5; // Number of items to process in parallel

async function processCheck(recordId: string, items: ParsedCheckInput[]) {
    await supabaseService.updateCheckStatus(recordId, 'processing');
    const results: CheckResult[] = [];

    // Process items in batches of BATCH_SIZE
    for (let i = 0; i < items.length; i += BATCH_SIZE) {
        const batch = items.slice(i, i + BATCH_SIZE);
        
        // Process batch in parallel
        const batchResults = await Promise.all(
            batch.map(item => processSingleCheck(item))
        );
        
        results.push(...batchResults);

        // Update progress after each batch
        await supabaseService.updateCheckStatus(recordId, 'processing', results);

        // Small delay between batches to avoid rate limiting
        if (i + BATCH_SIZE < items.length) {
            await new Promise(resolve => setTimeout(resolve, 300));
        }
    }

    await supabaseService.updateCheckStatus(recordId, 'completed', results);
}

/**
 * API Handler: Submit Check Request
 */
export async function submitCheck(req: Request, res: Response) {
    try {
        const { check_input } = req.body;

        if (!check_input) {
            return res.status(400).json({ success: false, error: 'Missing check_input' });
        }

        const parsedInput = parseCheckInput(check_input);
        if (parsedInput.length === 0) {
            return res.status(400).json({ success: false, error: 'Invalid input format' });
        }

        // Create record in Supabase
        const record = await supabaseService.createCheck(check_input);

        // Start processing in background
        processCheck(record.id, parsedInput).catch(err => {
            logger.error('Background check processing failed', { id: record.id, error: err.message });
            supabaseService.updateCheckStatus(record.id, 'failed', [], err.message);
        });

        return res.json({ success: true, id: record.id });
    } catch (error: any) {
        logger.error('Submit check error', { error: error.message });
        return res.status(500).json({ success: false, error: error.message });
    }
}

/**
 * API Handler: Get Check History
 */
export async function getCheckHistory(req: Request, res: Response) {
    try {
        const history = await supabaseService.getCheckHistory(30);
        return res.json({ success: true, data: history });
    } catch (error: any) {
        return res.status(500).json({ success: false, error: error.message });
    }
}

/**
 * API Handler: Delete Check Record
 */
export async function deleteCheck(req: Request, res: Response) {
    try {
        const { id } = req.params;
        
        if (!id) {
            return res.status(400).json({ success: false, error: 'Missing record ID' });
        }

        await supabaseService.deleteCheck(id);
        return res.json({ success: true });
    } catch (error: any) {
        logger.error('Delete check error', { error: error.message });
        return res.status(500).json({ success: false, error: error.message });
    }
}
