const { generateRandomData, parseLocator } = require('./config');
const { detectFormFields } = require('./fields');
const { detectSubmitButton } = require('./submit');
const { detectCaptcha, solveSimpleCaptcha, solveHCaptcha } = require('./captcha');
const { classifyNewsletterForm } = require('./classifier');
const { detectSubmissionResult } = require('./submission');

async function processSite(browser, site, globalCreds, browserConfig, keepOpen = false, dryRun = false) {
    let siteFailed = false;
    let failureReason = '';
    let page = null;
    
    try {
        let creds;
        if (site.credentials && site.credentials.username) {
            creds = { ...globalCreds, ...site.credentials };
        } else {
            creds = { ...globalCreds };
        }
        
        if (!creds.username || !creds.email || !creds.password) {
            const randomData = generateRandomData();
            creds = { ...randomData, ...creds };
        }

        console.log(`\n${site.url}`);
        console.log(`${'-'.repeat(70)}`);
        
        page = await browser.newPage();

        if (browserConfig.userAgent) {
            await page.setUserAgent(browserConfig.userAgent);
        }

        await page.goto(site.url, { waitUntil: 'networkidle2', timeout: 30000 });
        
        const captchaInfo = await detectCaptcha(page);
        if (captchaInfo.length > 0) {
            console.log(`\n   CAPTCHA DETECTED:`);
            for (const captcha of captchaInfo) {
                const visibility = captcha.isVisible ? '(visible)' : '(hidden)';
                console.log(`      - ${captcha.name} ${visibility}`);
            }
            
            if (captchaInfo.some(c => c.type === 'mathCaptcha')) {
                if (dryRun) {
                    console.log(`   [DRY-RUN] Would solve math CAPTCHA`);
                } else {
                    const solution = await solveSimpleCaptcha(page);
                    if (solution && solution.answer) {
                        console.log(`   Auto-solving math: ${solution.text} = ${solution.answer}`);
                        try {
                            await page.evaluate((answer) => {
                                const input = document.querySelector('input[name*="captcha"], input[class*="captcha"], #captcha');
                                if (input) {
                                    input.value = answer;
                                    input.dispatchEvent(new Event('input', { bubbles: true }));
                                }
                            }, solution.answer);
                        } catch (e) {
                            console.warn(`   Failed to fill math answer: ${e.message}`);
                        }
                    }
                }
            }
            
            if (captchaInfo.some(c => c.type === 'textCaptcha')) {
                console.log(`   Text CAPTCHA detected - looking for input field...`);
                const textCaptchaFilled = await page.evaluate(() => {
                    const input = document.querySelector('input[name*="captcha"], input[id*="captcha"], .captcha-input, #captcha, input[placeholder*="captcha" i]');
                    if (input) {
                        return {
                            found: true,
                            selector: input.id ? `#${input.id}` : (input.name ? `[name="${input.name}"]` : 'input[name*="captcha"]')
                        };
                    }
                    return { found: false };
                });
                if (textCaptchaFilled.found) {
                    console.log(`   Text CAPTCHA input found: ${textCaptchaFilled.selector}`);
                }
            }
            
            if (captchaInfo.some(c => c.type === 'imageCaptcha' || c.type === 'textCaptcha')) {
                if (dryRun) {
                    console.log(`   [DRY-RUN] Would solve image/text CAPTCHA (no API calls)`);
                } else {
                    const solution = await solveSimpleCaptcha(page);
                    if (solution && solution.answer) {
                        console.log(`   OCR solved CAPTCHA: "${solution.answer}"`);
                        try {
                            await page.evaluate((answer) => {
                                const input = document.querySelector('input[name*="captcha"], input[class*="captcha"], input[id*="captcha"], #captcha, .captcha-input');
                                if (input) {
                                    input.value = answer;
                                    input.dispatchEvent(new Event('input', { bubbles: true }));
                                    input.dispatchEvent(new Event('change', { bubbles: true }));
                                    console.log(`   Filled CAPTCHA with: ${answer}`);
                                }
                            }, solution.answer);
                        } catch (e) {
                            console.warn(`   Failed to fill CAPTCHA answer: ${e.message}`);
                        }
                    } else if (solution && solution.message) {
                        console.log(`   CAPTCHA solving failed: ${solution.message}`);
                    }
                }
            }
            
            const visibleRecaptcha = captchaInfo.filter(c => (c.type === 'recaptcha' || c.type === 'hcaptcha') && c.isVisible);
            if (visibleRecaptcha.length > 0) {
                siteFailed = true;
                failureReason = `CAPTCHA present: ${visibleRecaptcha.map(c => c.name).join(', ')}`;
                console.error(`   Cannot auto-solve ${visibleRecaptcha.map(c => c.name).join(', ')}`);
                return { siteFailed, failureReason, page };
            } else if (captchaInfo.some(c => c.type === 'recaptcha' || c.type === 'hcaptcha')) {
                console.log(`   CAPTCHA detected but not visible - attempting to proceed anyway`);
            }
        }
        
        const formClassification = await classifyNewsletterForm(page);
        console.log(`\n   Form Classification: ${formClassification.isNewsletter ? 'Newsletter' : 'Not newsletter'} (${formClassification.confidence}/100 confidence)`);
        
        if (formClassification.signals.positive.length > 0) {
            console.log('   Positive signals:');
            formClassification.signals.positive.forEach(signal => console.log(`      + ${signal}`));
        }
        
        if (formClassification.signals.negative.length > 0) {
            console.log('   Negative signals:');
            formClassification.signals.negative.forEach(signal => console.log(`      - ${signal}`));
        }
        
        if (!formClassification.isNewsletter && formClassification.confidence < 40) {
            siteFailed = true;
            failureReason = 'Not a newsletter signup form';
            console.error(`   ${failureReason}`);
        }
        
        console.log('\nDETECTED FIELDS:');
        
        let fieldsToFill = {};
        let detectedFields = {};
        const definedLocators = site.locators || {};
        
        if (site.autoDetect !== false) {
            detectedFields = await detectFormFields(page);
            for (const [fieldName, fieldInfo] of Object.entries(detectedFields)) {
                fieldsToFill[fieldName] = fieldInfo.selector;
            }
        }
        
        const hasEmailField = fieldsToFill.email || fieldsToFill.confirmEmail;
        if (!hasEmailField) {
            siteFailed = true;
            failureReason = 'No email field detected';
            console.warn(`\n   ${failureReason}`);
        }
        
        const hasSearchInput = await page.evaluate(() => {
            const inputs = document.querySelectorAll('input[type="search"], input[name*="search"], input[id*="search"]');
            return inputs.length > 0;
        }).catch(() => false);
        
        if (hasSearchInput && !hasEmailField) {
            console.warn(`   Search form detected instead of newsletter`);
            siteFailed = true;
            failureReason = failureReason || 'Search form instead of newsletter';
        }
        
        for (const [fieldName, locator] of Object.entries(definedLocators)) {
            if (fieldName !== 'submit') {
                fieldsToFill[fieldName] = parseLocator(locator);
            }
        }
        
        if (Object.keys(fieldsToFill).length > 0) {
            console.log(`\n   ${'FIELD'.padEnd(12)} | ${'SELECTOR'.padEnd(35)} | ${'CONF'.padEnd(4)} | VALUE`);
            console.log('   ' + '-'.repeat(75));
            
            for (const [fieldName, fieldInfo] of Object.entries(detectedFields)) {
                let valueToFill = creds[fieldName];
                
                if (fieldName === 'confirmEmail') {
                    valueToFill = creds['email'];
                }
                
                const selector = fieldInfo.selector.length > 34 ? fieldInfo.selector.substring(0, 31) + '...' : fieldInfo.selector;
                const value = valueToFill ? valueToFill.substring(0, 20) : 'N/A';
                
                console.log(`   ${fieldName.padEnd(12)} | ${selector.padEnd(35)} | ${fieldInfo.confidence.toString().padEnd(4)} | ${value}`);
                
                if (valueToFill) {
                    try {
                        await page.evaluate((sel, val) => {
                            const el = document.querySelector(sel);
                            if (el) {
                                el.value = val;
                                el.dispatchEvent(new Event('input', { bubbles: true }));
                                el.dispatchEvent(new Event('change', { bubbles: true }));
                            }
                        }, fieldInfo.selector, valueToFill);
                    } catch (e) {
                        console.warn(`   Failed to fill ${fieldName}: ${e.message}`);
                        siteFailed = true;
                        failureReason = `Failed to fill ${fieldName}: ${e.message}`;
                    }
                }
            }
            console.log('   ' + '-'.repeat(75));
        }

        let submitSelector = null;
        if (definedLocators.submit) {
            submitSelector = parseLocator(definedLocators.submit);
        } else if (site.autoDetect !== false) {
            submitSelector = await detectSubmitButton(page);
        }
        
        if (submitSelector) {
            try {
                const urlBeforeSubmit = page.url();
                await page.click(submitSelector);
                console.log(`   Submitted (${submitSelector})`);
                
                await new Promise(r => setTimeout(r, 1500));
                
                let submissionResult;
                try {
                    const urlAfterSubmit = page.url();
                    if (urlAfterSubmit !== urlBeforeSubmit) {
                        console.log(`   Page navigated to: ${urlAfterSubmit}`);
                    }
                    
                    submissionResult = await detectSubmissionResult(page, urlBeforeSubmit);
                } catch (resultError) {
                    console.log(`   Could not detect submission result: ${resultError.message}`);
                    submissionResult = { failure: false, success: false, signals: ['Could not determine - page may have redirected'] };
                }
                
                console.log(`\n   Submission Result Analysis:`);
                
                if (submissionResult.signals && submissionResult.signals.length > 0) {
                    for (const signal of submissionResult.signals) {
                        console.log(`      - ${signal}`);
                    }
                }
                
                // Check for hCaptcha on redirected pages (like /challenge)
                const postSubmitCaptcha = await detectCaptcha(page);
                const visibleHCaptcha = postSubmitCaptcha.filter(c => c.type === 'hcaptcha' && c.isVisible);
                const hasChallengeRedirect = page.url().includes('/challenge') || page.url().includes('captcha');
                
                if ((visibleHCaptcha.length > 0 || hasChallengeRedirect) && !dryRun) {
                    console.log(`   hCaptcha/challenge detected - attempting to solve...`);
                    const hcaptchaResult = await solveHCaptcha(page, page.url());
                    
                    if (hcaptchaResult && hcaptchaResult.answer) {
                        console.log(`   hCaptcha solved - resubmitting form...`);
                        
                        // Wait a moment for the token to be set
                        await new Promise(r => setTimeout(r, 500));
                        
                        const resubmitSelector = await detectSubmitButton(page);
                        if (resubmitSelector) {
                            await page.click(resubmitSelector);
                            await new Promise(r => setTimeout(r, 3000));
                            
                            const resubmitResult = await detectSubmissionResult(page, urlBeforeSubmit);
                            if (resubmitResult.success) {
                                console.log(`   SUCCESS after hCaptcha solve!`);
                                siteFailed = false;
                                failureReason = '';
                            } else if (resubmitResult.failure) {
                                siteFailed = true;
                                failureReason = resubmitResult.failureReason || 'Failed after hCaptcha';
                            } else {
                                // Still unknown but hCaptcha was solved - assume success
                                console.log(`   hCaptcha solved, result unknown - assuming success`);
                                siteFailed = false;
                                failureReason = '';
                            }
                        }
                    } else {
                        console.log(`   Could not solve hCaptcha`);
                        siteFailed = true;
                        failureReason = 'hCaptcha solving failed';
                    }
                } else if ((visibleHCaptcha.length > 0 || hasChallengeRedirect) && dryRun) {
                    console.log(`   [DRY-RUN] Would solve hCaptcha/challenge`);
                } else if (submissionResult.failure) {
                    if (siteFailed) {
                        console.error(`   FAILED: ${submissionResult.failureReason}`);
                    }
                } else if (submissionResult.success) {
                    console.log(`   SUCCESS: Subscription appears to have succeeded`);
                } else {
                    console.log(`   Result: Unknown (page may have redirected to confirmation)`);
                }
                
            } catch (submitError) {
                siteFailed = true;
                failureReason = failureReason || `Submit failed: ${submitError.message}`;
                console.error(`   Submit failed: ${submitError.message}`);
            }
        } else {
            siteFailed = true;
            failureReason = failureReason || 'No submit button found';
            console.warn(`   ${failureReason}`);
        }
        
    } catch (error) {
        siteFailed = true;
        failureReason = error.message;
        console.error(`   Error: ${error.message}`);
    } finally {
        if (page && !keepOpen) {
            await page.close().catch(() => {});
        }
    }
    
    return { siteFailed, failureReason, page };
}

module.exports = {
    processSite
};
