import { generate } from 'critical';
import fs from 'fs';
import path from 'path';

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
const page = await browser.newPage();

// Login
await page.goto('http://localhost:5275/Home/Login');
await page.type('#username', 'admin');
await page.type('#password', 'Test1234.');
await page.click('button[type=submit]');
await page.waitForNavigation();

// Extract cookies
const cookies = await page.cookies();
await browser.close();

async function generateCriticalCSSForViews() {
  const viewsDir = 'Views';
  
  // Helper function to get all .cshtml files recursively
  function getAllCshtmlFiles(dir) {
    let results = [];
    const list = fs.readdirSync(dir);
    
    list.forEach(file => {
      const filePath = path.join(dir, file);
      const stat = fs.statSync(filePath);
      
      if (stat && stat.isDirectory()) {
        // Recursively get files from subdirectories
        results = results.concat(getAllCshtmlFiles(filePath));
      } else if (file.endsWith('.cshtml')) {
        results.push(filePath);
      }
    });
    
    return results;
  }
  
  // Helper function to convert file path to URL path
  function filePathToUrlPath(filePath) {
    // Remove 'Views/' prefix
    let relativePath = filePath.replace(/^Views[\/\\]/, '');
    
    // Remove .cshtml extension
    relativePath = relativePath.replace(/\.cshtml$/, '');
    
    // Convert to URL format (replace \ with / and capitalize first letter)
    const urlPath = relativePath
      .split(/[\/\\]/)
      .map((segment, index) => 
        index === 0 ? segment : segment.charAt(0).toUpperCase() + segment.slice(1)
      )
      .join('/');
    
    // Handle the case where we have a single file (like Index.cshtml)
    if (relativePath.includes('/')) {
      // Convert to URL path format: Views/Home/Index.cshtml -> /Home/Index
      return '/' + relativePath.replace(/\\/g, '/').replace(/\.cshtml$/, '');
    } else {
      // For files directly in Views folder (like Views/Index.cshtml)
      return '/' + relativePath.replace(/\.cshtml$/, '');
    }
  }
  
  // Get all .cshtml files
  const cshtmlFiles = getAllCshtmlFiles(viewsDir);
  
  // Create CriticalCSS directory if it doesn't exist
  const criticalCssDir = 'CriticalCSS';
  if (!fs.existsSync(criticalCssDir)) {
    fs.mkdirSync(criticalCssDir, { recursive: true });
  }
  
  // Process each file
  for (const file of cshtmlFiles) {
    try {
      const urlPath = filePathToUrlPath(file);
      
      // Generate critical CSS
      await generate({
        src: `http://localhost:5275${urlPath}`,
        inline: false,
        width: 1920,
        height: 1080,
        penthouse: {
          customHeaders: {
            cookie: cookies.map(c => `${c.name}=${c.value}`).join('; ')
          },
          forceInclude: [
            '[data-bs-theme=dark]',
            '.navbar',
            '.nav-link',
            '.dropdown-menu',
            '.me-2',
            '.align-items-center',
            '.d-flex',
            '.position-fixed', // print batch
            '.bottom-0',
            '.start-0',
            '.m-4',
            '.row', // elements
            '.row>*',
            '.g-3',
            '.col-md-3',
            '.text-center',
            '.mb-3',
            '.mb-4',
            '.mt-3',
            '.py-4',
            '.text-center',
            'h2',
            '.form-control',
            '.form-control-sm',
            '.modal',
            '.btn',
            '.btn-sm',
            '.btn-secondary',
            '.btn-warning',
            '.btn-danger',
            '.rounded-circle', // user icon
            'table', // table elements (users)
            '.table>thead',
            '.user-row > td',
            'thead',
            'tbody',
            'th',
            'tr',
            'td',
            '.table>:not(caption)>*>*',
            '.table-striped>tbody>tr:nth-of-type(odd)>*',
            '.gap-2',
            '.table',
            '.table-responsive',
            '.align-middle'
          ]
        },
        target: {
          css: path.join(criticalCssDir, urlPath.replace(/\//g, '.').replace(/^\./, '') + '.css')
        }
      });
      
      console.log(`Critical CSS generated for: ${urlPath}`);
    } catch (err) {
      console.error(`Error processing ${file}:`, err);
    }
  }
  
  console.log('All critical CSS files generated!');
}

// Run the function
generateCriticalCSSForViews().catch(console.error);


// How to run this:
// install dependencies:
//  npm i -D critical
//  npm install puppeteer
// run:
//  node critical.js