// DCS Credit Application Content Script
// This script runs on all web pages to detect and extract data from DCS credit applications

class DCSDataExtractor {
  constructor() {
    this.extractedData = {};
    this.isDCSPage = false;
    this.reactAppLoaded = false;
    
    // Check if URL is valid for processing
    if (!this.isValidCreditAppURL()) {
      console.log('Extension disabled: Not a valid credit application print URL');
      return; // Don't initialize if not a valid URL
    }
    
    this.init();
  }

  isValidCreditAppURL() {
    const url = window.location.href;
    
    // Only allow URLs that match the print-credit-app-lead pattern
    // Format: https://adminv2.dealercarsearch.com/leads/print-credit-app-lead/[ID]
    const validPattern = /^https:\/\/adminv2\.dealercarsearch\.com\/leads\/print-credit-app-lead\/\d+$/;
    
    // Check if URL matches the valid pattern
    const isValid = validPattern.test(url);
    
    if (!isValid) {
      console.log(`URL validation failed: ${url}`);
      console.log('Valid format: https://adminv2.dealercarsearch.com/leads/print-credit-app-lead/[ID]');
    }
    
    return isValid;
  }

  init() {
    // Initial check
    this.checkPage();
    
    // For React apps, content loads dynamically - keep checking
    this.waitForReactApp();
    
    // Listen for messages from popup and background script
    chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
      try {
        // Check if this message was forwarded from background script
        const isForwarded = request.forwardedFromBackground === true;
        if (isForwarded) {
          console.log('Received forwarded message from background script:', request.action);
        }
        
        switch (request.action) {
          case 'checkPageStatus':
            // Check URL validity first
            if (!this.isValidCreditAppURL()) {
              sendResponse({ 
                isDCSPage: false,
                url: window.location.href,
                reactLoaded: false,
                invalidURL: true,
                message: 'This URL is not a valid credit application print page',
                forwardedResponse: isForwarded
              });
            } else {
              sendResponse({ 
                isDCSPage: this.isDCSPage,
                url: window.location.href,
                reactLoaded: this.reactAppLoaded,
                forwardedResponse: isForwarded
              });
            }
            break;
            
          case 'extractData':
            // Handle data extraction asynchronously to prevent message port timeout
            this.handleDataExtraction(sendResponse, isForwarded);
            return true; // Keep message channel open for async response
            
          default:
            sendResponse({ 
              success: false, 
              error: 'Unknown action',
              forwardedResponse: isForwarded
            });
        }
      } catch (error) {
        console.error('Error in message listener:', error);
        sendResponse({ 
          success: false, 
          error: error.message,
          forwardedResponse: request.forwardedFromBackground === true
        });
      }
    });
  }

  async handleDataExtraction(sendResponse, isForwarded = false) {
    try {
      console.log('Starting async data extraction...');
      
      // Add timeout protection
      const extractionTimeout = new Promise((resolve, reject) => {
        setTimeout(() => {
          reject(new Error('Data extraction timeout - operation took too long'));
        }, 30000); // 30 second timeout
      });
      
      // Perform extraction with timeout protection
      const extractionPromise = new Promise((resolve) => {
        try {
          console.log('Extracting data from page...');
          const data = this.extractAllData();
          
          console.log('Capturing page HTML...');
          const pageHtml = this.capturePageHTML();
          
          // Check if HTML content is too large (Chrome message limit is ~64MB)
          const htmlSize = JSON.stringify(pageHtml).length;
          console.log(`HTML content size: ${(htmlSize / 1024 / 1024).toFixed(2)} MB`);
          
          let processedPageHtml = pageHtml;
          if (htmlSize > 50 * 1024 * 1024) { // 50MB threshold
            console.warn('HTML content too large, compressing...');
            processedPageHtml = this.compressPageHTML(pageHtml);
          }
          
          resolve({
            success: true,
            data: data,
            pageHtml: processedPageHtml,
            fieldCount: Object.keys(data).length,
            htmlSize: htmlSize,
            forwardedResponse: isForwarded
          });
        } catch (error) {
          console.error('Error during data extraction:', error);
          resolve({
            success: false,
            error: error.message,
            data: {},
            fieldCount: 0,
            forwardedResponse: isForwarded
          });
        }
      });
      
      // Race between extraction and timeout
      const result = await Promise.race([extractionPromise, extractionTimeout]);
      
      console.log('Data extraction completed, sending response...');
      sendResponse(result);
      
    } catch (error) {
      console.error('Error in handleDataExtraction:', error);
      sendResponse({
        success: false,
        error: error.message,
        data: {},
        fieldCount: 0,
        forwardedResponse: isForwarded
      });
    }
  }

  compressPageHTML(pageHtml) {
    try {
      // Create a compressed version of the page HTML
      const compressed = {
        ...pageHtml,
        html: this.removeNonEssentialHTML(pageHtml.html || ''),
        compressed: true
      };
      
      console.log(`HTML compressed from ${JSON.stringify(pageHtml).length} to ${JSON.stringify(compressed).length} bytes`);
      return compressed;
    } catch (error) {
      console.error('Error compressing HTML:', error);
      return {
        html: '',
        url: pageHtml.url || window.location.href,
        title: pageHtml.title || document.title,
        timestamp: pageHtml.timestamp || new Date().toISOString(),
        error: 'HTML compression failed',
        compressed: true
      };
    }
  }

  removeNonEssentialHTML(html) {
    try {
      // Remove script tags, large images, and other non-essential elements
      let cleaned = html
        .replace(/<script[^>]*>.*?<\/script>/gis, '')
        .replace(/<style[^>]*>.*?<\/style>/gis, '')
        .replace(/<!--.*?-->/gis, '')
        .replace(/data:image\/[^;]+;base64,[^"']*/gi, 'data:image/placeholder')
        .replace(/\s+/g, ' ') // Compress whitespace
        .trim();
      
      // If still too large, keep only the body content
      if (cleaned.length > 10 * 1024 * 1024) { // 10MB
        const bodyMatch = cleaned.match(/<body[^>]*>(.*?)<\/body>/is);
        if (bodyMatch) {
          cleaned = `<html><head><title>${document.title}</title></head><body>${bodyMatch[1]}</body></html>`;
        }
      }
      
      return cleaned;
    } catch (error) {
      console.error('Error cleaning HTML:', error);
      return `<html><head><title>${document.title}</title></head><body>HTML cleaning failed</body></html>`;
    }
  }

  waitForReactApp() {
    // React apps take time to load - check every 500ms for up to 10 seconds
    let attempts = 0;
    const maxAttempts = 20;
    
    console.log('Starting React app detection...');
    
    const checkInterval = setInterval(() => {
      attempts++;
      
      // Check if React content has loaded
      const bodyText = (document.body.textContent || '').trim();
      const textLength = bodyText.length;
      const hasReactRoot = document.getElementById('root') && 
                          document.getElementById('root').children.length > 0;
      
      console.log(`React check ${attempts}: textLength=${textLength}, hasReactRoot=${hasReactRoot}`);
      
      // Look for credit application specific content, not just any content
      const hasCredAppContent = bodyText.toLowerCase().includes('applicant') || 
                               bodyText.toLowerCase().includes('credit') ||
                               bodyText.toLowerCase().includes('name') ||
                               bodyText.toLowerCase().includes('address') ||
                               bodyText.toLowerCase().includes('phone');
      
      if (textLength > 500 && hasCredAppContent) {
        console.log('Credit application content detected!');
        console.log('Full content sample:', bodyText.substring(0, 800));
        this.reactAppLoaded = true;
        this.checkPage();
        clearInterval(checkInterval);
      } else if (textLength > 200 && attempts > 3) {
        // Fallback: if we have some content after a few attempts, proceed
        console.log('Proceeding with available content...');
        console.log('Content sample:', bodyText.substring(0, 400));
        this.reactAppLoaded = true;
        this.checkPage();
        clearInterval(checkInterval);
      } else if (attempts >= maxAttempts) {
        console.log('React app load timeout - continuing anyway');
        clearInterval(checkInterval);
      }
    }, 500);
  }

  checkPage() {
    // Check if this is a DCS credit application page
    this.isDCSPage = this.detectDCSPage();
    
    if (this.isDCSPage) {
      console.log('DCS Credit Application page detected');
      this.addExtractionIndicators();
    }
  }

  detectDCSPage() {
    // Look for DCS-specific indicators in the page
    const indicators = [
      // Common DCS form identifiers
      'credit application',
      'dcs',
      'dealer credit services',
      'finance application',
      'auto loan',
      'car loan',
      'vehicle financing',
      // Form field patterns that suggest a credit application
      'applicant',
      'co-applicant', 
      'ssn',
      'social security',
      'employment',
      'employer',
      'vehicle information',
      'annual income',
      'monthly income',
      'driver license',
      'date of birth'
    ];
    
    const pageText = (document.body.textContent || document.body.innerText || '').toLowerCase();
    const pageTitle = (document.title || '').toLowerCase();
    const pageURL = (window.location.href || '').toLowerCase();
    
    // Check if page contains credit application indicators
    const hasIndicators = indicators.some(indicator => 
      pageText.includes(indicator.toLowerCase()) || 
      pageTitle.includes(indicator.toLowerCase()) ||
      pageURL.includes(indicator.toLowerCase())
    );
    
    // Check for form elements that are common in credit applications
    const hasFormElements = this.hasRelevantFormElements();
    
    // More relaxed detection - just need indicators OR form elements
    const isDetected = hasIndicators || hasFormElements;
    
    // Debug logging
    console.log('DCS Page Detection Debug:');
    console.log('- Page URL:', window.location.href);
    console.log('- Page Title:', document.title);
    console.log('- Has Indicators:', hasIndicators);
    console.log('- Has Form Elements:', hasFormElements);
    console.log('- Final Detection:', isDetected);
    
    return isDetected;
  }

  hasRelevantFormElements() {
    // Look for input fields that are common in credit applications
    const commonFields = [
      'name', 'first', 'last', 'address', 'phone', 'ssn', 'email',
      'employer', 'income', 'vehicle', 'year', 'make', 'model'
    ];
    
    const inputs = Array.from(document.querySelectorAll('input, select, textarea'));
    const formFieldNames = inputs.map(input => 
      (input.name || input.id || input.placeholder || '').toLowerCase()
    ).join(' ');
    
    return commonFields.some(field => formFieldNames.includes(field));
  }

  addExtractionIndicators() {
    // Add visual indicators to show which fields will be extracted
    const style = document.createElement('style');
    style.textContent = `
      .dcs-extract-highlight {
        outline: 2px solid #4CAF50 !important;
        outline-offset: 2px !important;
        background-color: rgba(76, 175, 80, 0.1) !important;
      }
      .dcs-extract-label {
        position: absolute;
        background: #4CAF50;
        color: white;
        padding: 2px 6px;
        font-size: 11px;
        border-radius: 3px;
        z-index: 10000;
        pointer-events: none;
      }
    `;
    document.head.appendChild(style);
  }

  extractAllData() {
    console.log('Starting data extraction from DCS page...');
    
    const data = {};
    
    // Debug: Show all form elements on the page
    this.debugFormElements();
    
    // Extract applicant information
    Object.assign(data, this.extractApplicantInfo());
    
    // Extract co-applicant information  
    Object.assign(data, this.extractCoApplicantInfo());
    
    // Extract employment information
    Object.assign(data, this.extractEmploymentInfo());
    
    // Extract vehicle information
    Object.assign(data, this.extractVehicleInfo());
    
    console.log('Final extracted data:', data);
    console.log('Total fields found:', Object.keys(data).length);
    return data;
  }

  debugFormElements() {
    console.log('=== FORM ELEMENTS DEBUG ===');
    const allInputs = Array.from(document.querySelectorAll('input, select, textarea'));
    
    console.log(`Found ${allInputs.length} form elements:`);
    
    allInputs.forEach((input, index) => {
      const identifier = {
        index: index,
        type: input.type || input.tagName,
        name: input.name || 'no-name',
        id: input.id || 'no-id',
        placeholder: input.placeholder || 'no-placeholder',
        value: input.value || 'empty',
        label: this.findLabelText(input) || 'no-label'
      };
      console.log(`Element ${index}:`, identifier);
    });
    
    // Also check for other data sources
    console.log('=== CHECKING FOR DATA IN PAGE TEXT ===');
    const pageText = document.body.textContent || document.body.innerText || '';
    console.log('Page contains:', pageText.length, 'characters');
    
    // Show page text in smaller chunks to avoid console overflow
    if (pageText.length > 0) {
      console.log('First 200 characters:', pageText.substring(0, 200));
      console.log('Characters 200-400:', pageText.substring(200, 400));
      console.log('Characters 400-600:', pageText.substring(400, 600));
    } else {
      console.log('No text content found!');
    }
    
    // Look for common patterns in the page
    const patterns = [
      /Name:\s*([^\n\r]+)/gi,
      /First Name:\s*([^\n\r]+)/gi,
      /Last Name:\s*([^\n\r]+)/gi,
      /Address:\s*([^\n\r]+)/gi,
      /Phone:\s*([^\n\r]+)/gi,
      /Email:\s*([^\n\r]+)/gi,
      /SSN:\s*([^\n\r]+)/gi,
      /Employer:\s*([^\n\r]+)/gi,
      /Income:\s*([^\n\r]+)/gi
    ];
    
    console.log('=== PATTERN MATCHES ===');
    patterns.forEach((pattern, i) => {
      try {
        const matches = pageText.match(pattern);
        if (matches) {
          console.log(`Pattern ${i} matches:`, matches.slice(0, 3)); // Limit output
        }
      } catch (e) {
        console.log(`Pattern ${i} error:`, e.message);
      }
    });
    
    console.log('=== END DEBUG ===');
  }

  extractApplicantInfo() {
    const data = {};
    const pageText = document.body.textContent || document.body.innerText || '';
    
    // Text-based patterns for DCS credit application format - ultra precise
    const patterns = {
      'first_name': /Full Name:\s*([A-Za-z]+)(?=\s)/i,
      'last_name': /Full Name:\s*[A-Za-z]+\s+([A-Za-z\s-]+?)(?=\s*Address:|$)/i,
      'address': /Address:\s*([^\n\r]+?)(?=\s*Address 2:|City\/State\/Zip:|Email:)/i,
      'address2': /Address 2:\s*([^\n\r]+?)(?=\s*City\/State\/Zip:|Email:|$)/i,
      'city': /City\/State\/Zip:\s*([A-Za-z\s]+)(?=\s+[A-Z]{2})/i,
      'state': /City\/State\/Zip:\s*[^,\n\r]+?\s+([A-Z]{2})(?=\s*,|\s*\d)/i,
      'zip': /City\/State\/Zip:\s*[^,\n\r]+?\s+[A-Z]{2}[,\s]*(\d{5}(?:-\d{4})?)(?=\s|Email:)/i,
      'email': /Email:\s*([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})(?=Time|\s|Home|$)/i,
      'phone': /(?:Mobile Phone|Cell Phone):\s*((?:\(?\d{3}\)?[-.\s]*\d{3}[-.\s]*\d{4}|\d{10}))(?=\s|Social|Date|$)/i,
      'mobile_phone': /(?:Mobile Phone|Cell Phone):\s*((?:\(?\d{3}\)?[-.\s]*\d{3}[-.\s]*\d{4}|\d{10}))(?=\s|Social|Date|$)/i,
      'home_phone': /Home Phone:\s*(\d{10})(?=\s|Mobile)/i,
      'ssn': /Social Security:\s*(\d{3}-?\d{2}-?\d{4}|\d{9})(?=\s|Date)/i,
      'date_of_birth': /Date of Birth:\s*(\d{1,2}\/\d{1,2}\/\d{4})(?=\s|Residence)/i,
      'drivers_license': /Drivers License #:\s*([A-Za-z0-9]+)(?=\s*DL State|\s*$)/i,
      'dl_state': /DL State\/Exp Date:\s*([A-Z]{2})(?=\s)/i,
      'dl_exp_date': /DL State\/Exp Date:\s*[A-Z]{2}\s+(\d{1,2}\/\d{1,2}\/\d{4})(?=\s|Home)/i,
      'time_at_residence': /Time at Residence:\s*(\d+\s*years?,?\s*\d+\s*months?)(?=\s|Rent)/i,
      'rent_mortgage': /Rent\/Mortgage:\s*\$?([0-9,.]+)(?=\s|Drivers)/i,
      'residence_type': /Residence Type:\s*(Own|Rent|Living with Family)(?=\s|Applicant)/i
    };
    
    // Extract using regex patterns
    for (const [field, pattern] of Object.entries(patterns)) {
      const match = pageText.match(pattern);
      if (match && match[1]) {
        let value = match[1].trim();

        // Validation: filter out invalid values
        if (field === 'address2' && value.toLowerCase().includes('city/state/zip')) {
          console.log(`Skipping invalid address2: ${value}`);
          continue; // Skip this invalid address2 value
        }

        if (field === 'email' && value.toLowerCase().includes('time')) {
          // Clean email by removing anything after the domain
          value = value.replace(/time.*$/i, '').trim();
        }

        if (field === 'employer_address') {
          console.log(`Checking employer_address value: "${value}"`);
          if (value.length > 100 || value.toLowerCase().includes('vehicle information') || value.toLowerCase().includes('city/state/zip')) {
            console.log(`Skipping invalid employer_address: ${value.substring(0, 50)}...`);
            continue; // Skip this invalid employer_address value
          }
        }

        // Format phone numbers to XXX-XXX-XXXX
        if (field === 'phone' || field === 'mobile_phone' || field === 'home_phone' || field === 'work_phone') {
          const digitsOnly = value.replace(/\D/g, ''); // Remove all non-digits first
          if (digitsOnly.length === 10) {
            value = `${digitsOnly.slice(0,3)}-${digitsOnly.slice(3,6)}-${digitsOnly.slice(6)}`;
            console.log(`Formatted phone number for ${field}: ${value}`);
          } else {
            console.log(`Phone number ${field} has ${digitsOnly.length} digits, keeping original: ${value}`);
          }
        }

        // Format SSN to remove dashes (keep as 9 digits)
        if (field === 'ssn') {
          value = value.replace(/-/g, ''); // Remove dashes from SSN
          console.log(`Formatted SSN: ${value}`);
        }

        // Capitalize names, employers, cities, and addresses
        if (field === 'first_name' || field === 'last_name' || field === 'city' ||
            field === 'address' || field === 'address2') {
          value = this.capitalizeNames(value);
          console.log(`Capitalized ${field}: ${value}`);
        }

        data[field] = value;
        console.log(`Found ${field}:`, value);
      }
    }

    // Post-process to extract middle name from last_name if it contains multiple words
    if (data.last_name && data.last_name.includes(' ')) {
      const nameParts = data.last_name.split(' ');
      if (nameParts.length > 1) {
        // If we have multiple parts in last name, first part might be middle name
        const middleName = nameParts[0];
        const actualLastName = nameParts.slice(1).join(' ');

        // Only extract middle name if it looks reasonable (1-2 words, not too long)
        if (middleName.length >= 1 && middleName.length <= 20 && nameParts.length <= 4) {
          data.middle_name = this.capitalizeNames(middleName);
          data.last_name = this.capitalizeNames(actualLastName);
          console.log(`Extracted middle name: ${data.middle_name}, corrected last name: ${data.last_name}`);
        }
      }
    }
    
    return data;
  }

  extractCoApplicantInfo() {
    const data = {};
    
    // Get page text for regex-based extraction (same as legacy system)
    const pageText = document.body.innerText || document.body.textContent || '';
    
    // Look for co-applicant section like the legacy system
    const coAppMatch = pageText.match(/Co-Applicant Information:(.*?)(?=Co-Applicant Employment|Vehicle Information|$)/s);
    if (!coAppMatch) {
      console.log('No Co-Applicant Information section found');
      return data;
    }
    
    const coAppText = coAppMatch[1];
    console.log('Found Co-Applicant section:', coAppText.substring(0, 200) + '...');
    
    // DCS-specific patterns (matching legacy system field names)
    const patterns = {
      'co_applicant_first_name': /Full Name:\s*([A-Za-z]+)(?=\s)/i,
      'co_applicant_last_name': /Full Name:\s*[A-Za-z]+\s+([A-Za-z\s-]+?)(?=\s*Address:|$)/i,
      'co_applicant_address': /Address:\s*([^\n\r]+?)(?=\s*Address 2:|City\/State\/Zip:|DL State)/i,
      'co_applicant_address2': /Address 2:\s*([^\n\r]+?)(?=\s*City\/State\/Zip:|Home Phone|$)/i,
      'co_applicant_city': /City\/State\/Zip:\s*([A-Za-z\s]+)(?=\s+[A-Z]{2})/i,
      'co_applicant_state': /City\/State\/Zip:\s*[^,\n\r]+?\s+([A-Z]{2})(?=\s*,|\s*\d)/i,
      'co_applicant_zip': /City\/State\/Zip:\s*[^,\n\r]+?\s+[A-Z]{2}[,\s]*(\d{5}(?:-\d{4})?)(?=\s|Home|$)/i,
      'co_applicant_email': /Email:\s*([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})(?=Time|\s|$)/i,
      'co_applicant_mobile_phone': /(?:Mobile Phone|Cell Phone):\s*((?:\(?\d{3}\)?[-.\s]*\d{3}[-.\s]*\d{4}|\d{10}))(?=\s|Social|Date|$)/i,
      'co_applicant_home_phone': /Home Phone:\s*((?:\(?\d{3}\)?[-.\s]*\d{3}[-.\s]*\d{4}|\d{10}))(?=\s|Mobile|$)/i,
      'co_applicant_ssn': /Social Security:\s*(\d{9}|\d{3}-\d{2}-\d{4})(?=\s|Date)/i,
      'co_applicant_dob': /Date of Birth:\s*(\d{1,2}\/\d{1,2}\/\d{4})(?=\s|Residence)/i,
      'co_applicant_residence_type': /Residence Type:\s*(Own|Rent|Living with Family)(?=\s|$)/i,
      'co_applicant_rent_mortgage': /Rent\/Mortgage:\s*\$?([0-9,.]+)(?=\s|Drivers)/i,
      'co_applicant_time_at_residence': /Time at Residence:\s*(\d+\s*years?,?\s*\d+\s*months?)(?=\s|$)/i
    };
    
    // Extract using regex patterns
    for (const [field, pattern] of Object.entries(patterns)) {
      const match = coAppText.match(pattern);
      if (match && match[1]) {
        let value = match[1].trim();
        
        // Apply same formatting as applicant data
        if (field === 'co_applicant_mobile_phone' || field === 'co_applicant_home_phone') {
          const digitsOnly = value.replace(/\D/g, '');
          if (digitsOnly.length === 10) {
            value = `${digitsOnly.slice(0,3)}-${digitsOnly.slice(3,6)}-${digitsOnly.slice(6)}`;
          }
        }
        
        // Handle SSN formatting (remove dashes to match legacy)
        if (field === 'co_applicant_ssn') {
          value = value.replace(/\D/g, '');
        }
        
        // Capitalize names, cities, addresses
        if (field === 'co_applicant_first_name' || field === 'co_applicant_last_name' || field === 'co_applicant_city' || 
            field === 'co_applicant_address' || field === 'co_applicant_address2') {
          value = this.capitalizeNames(value);
        }
        
        data[field] = value;
        console.log(`Found co-applicant ${field}:`, value);
      }
    }

    // Post-process to extract co-applicant middle name from last_name if it contains multiple words
    if (data.co_applicant_last_name && data.co_applicant_last_name.includes(' ')) {
      const nameParts = data.co_applicant_last_name.split(' ');
      if (nameParts.length > 1) {
        // If we have multiple parts in last name, first part might be middle name
        const middleName = nameParts[0];
        const actualLastName = nameParts.slice(1).join(' ');

        // Only extract middle name if it looks reasonable (1-2 words, not too long)
        if (middleName.length >= 1 && middleName.length <= 20 && nameParts.length <= 4) {
          data.co_applicant_middle_name = this.capitalizeNames(middleName);
          data.co_applicant_last_name = this.capitalizeNames(actualLastName);
          console.log(`Extracted co-applicant middle name: ${data.co_applicant_middle_name}, corrected last name: ${data.co_applicant_last_name}`);
        }
      }
    }

    // Look for co-applicant employment section
    const coEmpMatch = pageText.match(/Co-Applicant Employment Information:(.*?)(?=Vehicle Information|$)/s);
    if (coEmpMatch) {
      const coEmpText = coEmpMatch[1];
      console.log('Found Co-Applicant Employment section');
      
      const empPatterns = {
        'co_applicant_employer': /Employer:\s*([A-Za-z0-9\s&./,'''()"-]+?)(?=\s*Monthly Income:|Address:|City\/State\/Zip:)/i,
        'co_applicant_monthly_income': /Monthly Income:\s*\$?([0-9,.]+)(?=\s|Occupation:)/i,

        // Co-applicant YTD Income fields
        'co_applicant_ytd_income': /YTD Income:\s*\$([0-9,.]+)/i,
        'co_applicant_ytd_pay_periods': /YTD Pay Periods:\s*([0-9]+)/i,

        // Co-applicant Hourly wage fields
        'co_applicant_hourly_pay': /(?:Hourly Pay|Hourly Rate):\s*\$([0-9,.]+)/i,
        'co_applicant_hours_per_week': /Hours per Week:\s*([0-9]+(?:\.[0-9]+)?)/i,

        'co_applicant_occupation': /Occupation:\s*([^\n\r]+?)(?=\s*Address:|Work Phone:|Time on Job:)/i,
        'co_applicant_work_phone': /Work Phone:\s*((?:\(?\d{3}\)?[-.\s]*\d{3}[-.\s]*\d{4}|\d{10}))(?=\s|Time)/i,
        'co_applicant_time_on_job': /Time on Job:\s*(\d+\s*years?,?\s*\d+\s*months?)(?=\s|$)/i,
        'co_applicant_employer_address': /(?:Address:\s*([^\n\r]+?)(?=\s*City\/State\/Zip:|Work Phone:|$)|City\/State\/Zip:\s*([A-Za-z\s,0-9]+))/i
      };
      
      for (const [field, pattern] of Object.entries(empPatterns)) {
        const match = coEmpText.match(pattern);
        if (match && match[1]) {
          let value = match[1].trim();
          
          // Format phone numbers
          if (field === 'co_applicant_work_phone') {
            const digitsOnly = value.replace(/\D/g, '');
            if (digitsOnly.length === 10) {
              value = `${digitsOnly.slice(0,3)}-${digitsOnly.slice(3,6)}-${digitsOnly.slice(6)}`;
            }
          }
          
          // Capitalize names and addresses
          if (field === 'co_applicant_employer' || field === 'co_applicant_employer_address') {
            value = this.capitalizeNames(value);
          }
          
          data[field] = value;
          console.log(`Found co-applicant employment ${field}:`, value);
        }
      }
    }
    
    return data;
  }

  extractEmploymentInfo() {
    const data = {};
    const pageText = document.body.textContent || document.body.innerText || '';
    
    // Debug logging for employer extraction
    console.log('=== EMPLOYER EXTRACTION DEBUG ===');
    const employerSearch = pageText.match(/Employer:\s*[^\n\r]{0,100}/i);
    if (employerSearch) {
      console.log('Found Employer section:', employerSearch[0]);
      
      // Debug the employer city section specifically
      const citySearch = pageText.match(/City\/State\/Zip:\s*[^\n\r]{0,100}/gi);
      if (citySearch) {
        console.log('Found City/State/Zip sections:', citySearch);
        
        // More specific debugging for employer city/state/zip
        const employerCitySearch = pageText.match(/Employer[^\n\r]*?City\/State\/Zip:\s*[^\n\r]{0,100}/gi);
        if (employerCitySearch) {
          console.log('Found EMPLOYER City/State/Zip sections:', employerCitySearch);
        } else {
          console.log('No EMPLOYER-specific City/State/Zip found');
        }
      }
    } else {
      console.log('No Employer section found in page text');
    }
    
    // Employment patterns based on DCS format - more flexible for employer extraction
    const patterns = {
      'applicant_employer': [
        // Primary pattern: Stop before "Monthly Income" (with or without spaces) - includes special characters and smart quotes
        /Employer:\s*([A-Za-z0-9\s&./,'''()"-]+?)(?=\s*Monthly\s*Income:)/i,
        // Pattern: Stop before any field that starts with capital letter + colon - includes special characters and smart quotes
        /Employer:\s*([A-Za-z0-9\s&./,'''()"-]+?)(?=\s*[A-Z][a-z]+\s*:)/i,
        // Pattern: Extract until we hit common next field words - includes special characters and smart quotes
        /Employer:\s*([A-Za-z0-9\s&./,'''()"-]+?)(?=\s*(?:Monthly|Occupation|Address|Work|Time|Vehicle|Income))/i,
        // Fallback: Stop at line break, double space, or end - includes special characters and smart quotes
        /Employer:\s*([A-Za-z0-9\s&./,'''()"-]+?)(?=[\n\r]|\s{2,}|$)/i
      ],
      'applicant_monthly_income': /Monthly Income:\s*\$([0-9,.]+)(?=\s*Occupation:)/i,

      // YTD Income fields
      'applicant_ytd_income': /YTD Income:\s*\$([0-9,.]+)/i,
      'applicant_ytd_pay_periods': /YTD Pay Periods:\s*([0-9]+)/i,

      // Hourly wage fields
      'applicant_hourly_pay': /(?:Hourly Pay|Hourly Rate):\s*\$([0-9,.]+)/i,
      'applicant_hours_per_week': /Hours per Week:\s*([0-9]+(?:\.[0-9]+)?)/i,

      'applicant_occupation': /Occupation:\s*([A-Za-z\s/-]+?)(?=\s*Address:|Work Phone:|Time on Job:)/i,
      'applicant_work_phone': /Work Phone:\s*((?:\(?\d{3}\)?[-.\s]*\d{3}[-.\s]*\d{4}|\d{10}))(?=\s*Time on Job:)/i,
      'applicant_time_on_job': /Time on Job:\s*(\d+\s*years?,?\s*\d+\s*months?)(?=\s*Vehicle)/i,
      'applicant_employer_address': [
        // Primary pattern: Employer Address with street info
        /Employer.*?Address:\s*([^\n\r]+?)(?=\s*City\/State\/Zip:|Work Phone:|$)/i,
        // Fallback pattern: Look for address after employer name
        /Employer:\s*[^\n\r]*?Address:\s*([^\n\r]+?)(?=\s*City\/State\/Zip:|Work Phone:|$)/i,
        // More flexible pattern for employer address - includes smart quotes
        /(?:Employer[^\n\r]*?)Address:\s*([A-Za-z0-9\s#.'''-]+?)(?=\s*(?:City\/State\/Zip:|Work Phone:|Time on Job:|$))/i
      ],
      'applicant_employer_city': 'special', // Handle this separately
      'applicant_employer_state': /(?:Employer[^\n\r]*City\/State\/Zip:\s*[^,\n\r]+?\s+)([A-Z]{2})(?=\s*\d)/i,
      'applicant_employer_zip': /(?:Employer[^\n\r]*City\/State\/Zip:\s*[^,\n\r]+?\s+[A-Z]{2}\s*)(\d{5}(?:-\d{4})?)(?=\s*Work)/i
    };
    
    // Extract using regex patterns
    for (const [field, pattern] of Object.entries(patterns)) {
      if (Array.isArray(pattern)) {
        // Handle multiple patterns for employer and employer_address
        for (let i = 0; i < pattern.length; i++) {
          const match = pageText.match(pattern[i]);
          if (match && match[1] && match[1].trim()) {
            let fieldValue = match[1].trim();
            console.log(`${field} pattern ${i+1} matched: "${match[0]}" -> extracted: "${fieldValue}"`);
            
            if (field === 'applicant_employer') {
              // Clean up employer name - remove unwanted text and trailing punctuation
              fieldValue = fieldValue.replace(/[.,;:]+$/, '').trim();
              
              // Remove common contaminating words from the end
              fieldValue = fieldValue.replace(/\s*(monthly|income|occupation|address|work|time|vehicle)$/i, '').trim();
              
              // Validate employer name (should be reasonable length and not contain field names)
              if (fieldValue.length >= 2 && fieldValue.length <= 50 && 
                  !fieldValue.toLowerCase().includes('monthly') &&
                  !fieldValue.toLowerCase().includes('income') &&
                  !fieldValue.toLowerCase().includes('occupation')) {
                // Capitalize employer name
                fieldValue = this.capitalizeNames(fieldValue);
                data[field] = fieldValue;
                console.log(`Found employment ${field} (pattern ${i+1}):`, fieldValue);
                break; // Stop trying patterns once we find a valid match
              } else {
                console.log(`Rejected employer name (pattern ${i+1}): "${fieldValue}" (length: ${fieldValue.length})`);
              }
            } else if (field === 'applicant_employer_address') {
              // Validate employer address
              if (fieldValue.length >= 3 && fieldValue.length <= 100 &&
                  !fieldValue.toLowerCase().includes('city/state/zip') &&
                  !fieldValue.toLowerCase().includes('work phone')) {
                // Capitalize address
                fieldValue = this.capitalizeNames(fieldValue);
                data[field] = fieldValue;
                console.log(`Found employment ${field} (pattern ${i+1}):`, fieldValue);
                break;
              }
            } else if (field === 'applicant_employer_city') {
              // Clean quotes and validate employer_city
              fieldValue = fieldValue.replace(/['"]/g, '').trim();
              if (fieldValue.length >= 2 && fieldValue.length <= 50) {
                // Capitalize city
                fieldValue = this.capitalizeNames(fieldValue);
                data[field] = fieldValue;
                console.log(`Found employment ${field} (pattern ${i+1}):`, fieldValue);
                break;
              }
            }
          }
        }
      } else {
        // Handle single patterns
        const match = pageText.match(pattern);
        if (match && match[1]) {
          let cleanValue = match[1].trim().replace(/['"]/g, '');
          data[field] = cleanValue;
          console.log(`Found employment ${field}:`, cleanValue);
        }
      }
    }
    
    // Special handling for employer_city - try multiple strategies
    if (!data.applicant_employer_city) {
      console.log('=== SPECIAL EMPLOYER CITY EXTRACTION ===');
      
      // First, let's see what the actual text looks like around city entries
      const cityDebugMatch = pageText.match(/City\/State\/Zip:\s*[^\n\r]{0,50}/gi);
      console.log('Raw City/State/Zip text found:', cityDebugMatch);
      
      // Strategy 1: Look for all City/State/Zip entries and try to pick the employer one
      const allCityEntries = pageText.match(/City\/State\/Zip:\s*[A-Za-z\s,]+\s+[A-Z]{2}[\s,]*\d{5}(?:-\d{4})?/gi);
      if (allCityEntries) {
        console.log('Found all City/State/Zip entries:', allCityEntries);
        
        // If there are multiple entries, try to find the one after employer information
        for (let i = 0; i < allCityEntries.length; i++) {
          const entry = allCityEntries[i];
          const cityMatch = entry.match(/City\/State\/Zip:\s*([A-Za-z\s,]+\s+[A-Z]{2}[\s,]*\d{5}(?:-\d{4})?)/i);
          if (cityMatch && cityMatch[1]) {
            // Check if this entry appears after employer information in the text
            const entryIndex = pageText.indexOf(entry);
            const employerIndex = pageText.toLowerCase().indexOf('employer:');
            const monthlyIncomeIndex = pageText.toLowerCase().indexOf('monthly income:');
            
            // If this city entry appears after employer info, it's likely the employer city
            if (entryIndex > employerIndex && entryIndex > monthlyIncomeIndex) {
              let cleanCity = cityMatch[1].trim();
              // Remove quote characters that might be captured from HTML
              cleanCity = cleanCity.replace(/['"]/g, '');
              data.applicant_employer_city = cleanCity;
              console.log(`Found applicant_employer_city (strategy 1, entry ${i+1}):`, cleanCity);
              break;
            }
          }
        }
        
        // Fallback: if we still don't have employer_city and there are multiple entries, use the second one
        if (!data.applicant_employer_city && allCityEntries.length > 1) {
          const secondEntry = allCityEntries[1];
          const cityMatch = secondEntry.match(/City\/State\/Zip:\s*([A-Za-z\s,]+\s+[A-Z]{2}[\s,]*\d{5}(?:-\d{4})?)/i);
          if (cityMatch && cityMatch[1]) {
            let cleanCity = cityMatch[1].trim();
            // Remove quote characters that might be captured from HTML
            cleanCity = cleanCity.replace(/['"]/g, '');
            data.applicant_employer_city = cleanCity;
            console.log('Found applicant_employer_city (fallback - second entry):', cleanCity);
          }
        }
      } else {
        console.log('No City/State/Zip entries found with strict pattern');
        
        // Try a more flexible pattern if the strict one fails
        const flexibleCityEntries = pageText.match(/City\/State\/Zip:\s*[^\n\r]+/gi);
        if (flexibleCityEntries) {
          console.log('Found flexible City/State/Zip entries:', flexibleCityEntries);
          
          // If we have multiple, try the second one (likely employer)
          if (flexibleCityEntries.length > 1) {
            const secondEntry = flexibleCityEntries[1];
            // Extract just the city/state/zip part after the colon
            const flexibleMatch = secondEntry.match(/City\/State\/Zip:\s*(.+)/i);
            if (flexibleMatch && flexibleMatch[1]) {
              let flexibleCity = flexibleMatch[1].trim().replace(/['"]/g, '');
              data.applicant_employer_city = flexibleCity;
              console.log('Found applicant_employer_city (flexible pattern):', flexibleCity);
            }
          }
        } else {
          console.log('No City/State/Zip entries found at all');
        }
      }
    }
    
    return data;
  }

  extractVehicleInfo() {
    const data = {};
    const pageText = document.body.textContent || document.body.innerText || '';
    
    // Vehicle patterns based on DCS format - ultra precise
    const patterns = {
      'vehicle_year': /Year:\s*(\d{4})(?=\s*Make:)/i,
      'vehicle_make': /Make:\s*([A-Za-z]+(?:\s+[A-Za-z]+)*)(?=\s*Model:)/i,
      'vehicle_model': /Model:\s*([A-Za-z0-9\s\-]+?)(?=\s*VIN:)/i,
      'vehicle_vin': /VIN:\s*([A-HJ-NPR-Z0-9]{17})(?=\s*Odometer:)/i,
      'vehicle_mileage': /Odometer:\s*([0-9,]+)(?=\s*Sales Price:)/i,
      'sale_price': /Sales Price:\s*\$([0-9,.]+)(?=\s*Trade)/i,
      'down_payment': /Down Payment:\s*\$?([0-9,.]+)(?=\s*Loan)/i
    };
    
    // Extract using regex patterns
    for (const [field, pattern] of Object.entries(patterns)) {
      const match = pageText.match(pattern);
      if (match && match[1]) {
        let value = match[1].trim();
        
        // Validation: exclude "Trade" from vehicle make
        if (field === 'vehicle_make' && value.toLowerCase() === 'trade') {
          console.log(`Skipping invalid vehicle_make: ${value}`);
          continue;
        }
        
        // Capitalize vehicle make and model
        if (field === 'vehicle_make' || field === 'vehicle_model') {
          value = this.capitalizeNames(value);
          console.log(`Capitalized vehicle ${field}: ${value}`);
        }
        
        data[field] = value;
        console.log(`Found vehicle ${field}:`, value);
      }
    }
    
    return data;
  }

  findFieldValue(searchTerms) {
    // Search for form fields that match any of the search terms
    const allInputs = Array.from(document.querySelectorAll('input, select, textarea'));
    
    for (const input of allInputs) {
      const fieldIdentifier = (
        input.name + ' ' +
        input.id + ' ' + 
        input.placeholder + ' ' +
        (input.getAttribute('aria-label') || '') + ' ' +
        this.findLabelText(input)
      ).toLowerCase();
      
      // Check if any search term matches the field identifier
      for (const term of searchTerms) {
        if (fieldIdentifier.includes(term.toLowerCase())) {
          const value = input.value || input.textContent;
          if (value && value.trim()) {
            return value.trim();
          }
        }
      }
    }
    
    return null;
  }

  findLabelText(input) {
    // Find associated label text
    let labelText = '';
    
    // Method 1: Direct label association
    if (input.id) {
      const label = document.querySelector(`label[for="${input.id}"]`);
      if (label) {
        labelText += label.textContent + ' ';
      }
    }
    
    // Method 2: Parent label
    const parentLabel = input.closest('label');
    if (parentLabel) {
      labelText += parentLabel.textContent + ' ';
    }
    
    // Method 3: Previous sibling text
    let sibling = input.previousElementSibling;
    while (sibling && labelText.length < 100) {
      if (sibling.tagName === 'LABEL' || sibling.tagName === 'SPAN') {
        labelText += sibling.textContent + ' ';
        break;
      }
      sibling = sibling.previousElementSibling;
    }
    
    return labelText;
  }

  capitalizeNames(text) {
    if (!text || typeof text !== 'string') return text;
    
    // Helper function to capitalize a single word, handling hyphens
    const capitalizeWord = (word, isFirstWord = false) => {
      if (word.length === 0) return word;
      
      // Handle hyphenated words (e.g., "Westlund-Cartie")
      if (word.includes('-')) {
        return word.split('-')
          .map(part => capitalizeWord(part, isFirstWord))
          .join('-');
      }
      
      // Handle common abbreviations and special cases
      const lowerWord = word.toLowerCase();
      if (['llc', 'inc', 'corp', 'ltd', 'co'].includes(lowerWord)) {
        return word.toUpperCase();
      }
      if (!isFirstWord && ['of', 'the', 'and', 'or', 'at', 'in', 'on', 'to', 'for'].includes(lowerWord)) {
        return lowerWord; // Keep small words lowercase unless they're the first word
      }
      
      // Capitalize first letter, make rest lowercase
      return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
    };
    
    // Split by spaces and capitalize each word
    return text.split(' ')
      .map((word, index) => capitalizeWord(word, index === 0))
      .join(' ');
  }

  capturePageHTML() {
    try {
      // Capture the full page HTML for PDF generation
      console.log('Capturing DCS page HTML for PDF generation...');
      
      // Get the complete HTML content
      const htmlContent = document.documentElement.outerHTML;
      
      // Also capture any inline styles and computed styles that might be needed
      const pageData = {
        html: htmlContent,
        url: window.location.href,
        title: document.title,
        timestamp: new Date().toISOString()
      };
      
      console.log(`Captured HTML content: ${htmlContent.length} characters`);
      return pageData;
      
    } catch (error) {
      console.error('Error capturing page HTML:', error);
      return {
        html: '',
        url: window.location.href,
        title: document.title,
        timestamp: new Date().toISOString(),
        error: error.message
      };
    }
  }

}

// Initialize the extractor when the page loads
if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', () => {
    new DCSDataExtractor();
  });
} else {
  new DCSDataExtractor();
}