#!/usr/bin/env node

try {
  // Direct implementation of text analysis
  const fs = require('fs');
  const path = require('path');
  const { Command } = require('commander');
  const chalk = require('chalk');
  const ora = require('ora');
  const fg = require('fast-glob');

  // Ensure ora is properly imported
  const createSpinner = ora.default || ora;

  // Enhanced word counter implementation
  class WordCounter {
    constructor(text = '', wordsPerMinute = 200, handwritingWpm = 25, keyboardWpm = 60) {
      this.text = text;
      this.wordsPerMinute = wordsPerMinute;
      this.handwritingWpm = handwritingWpm;
      this.keyboardWpm = keyboardWpm;
    }

    setText(text) {
      this.text = text;
    }

    getStats() {
      const characters = this.text.length;
      const charactersNoSpaces = this.text.replace(/\s/g, '').length;
      const words = this.text.split(/\s+/).filter(word => word.length > 0).length;
      const sentences = this.text.split(/[.!?]+/).filter(sentence => sentence.trim().length > 0).length;
      const paragraphs = this.text.split(/\n\s*\n/).filter(paragraph => paragraph.trim().length > 0).length;

      // Calculate different time estimates
      const readingTime = this.formatTime(words, this.wordsPerMinute);
      const handwritingTime = this.estimateHandwritingTime(words, characters);
      const keyboardTime = this.formatTime(words, this.keyboardWpm);

      return {
        characters,
        charactersNoSpaces,
        words,
        sentences,
        paragraphs,
        readingTime,
        handwritingTime,
        keyboardTime
      };
    }

    /**
     * Estimate handwriting time using a more realistic algorithm
     *
     * @param {number} words - Number of words
     * @param {number} characters - Number of characters
     * @returns {string} Formatted time estimate
     */
    estimateHandwritingTime(words, characters) {
      // Base handwriting speed (words per minute)
      const baseWpm = this.handwritingWpm;

      // Complexity factor based on average word length
      // Longer words are generally more complex to write
      const avgWordLength = words > 0 ? characters / words : 0;
      const complexityFactor = Math.min(1.5, Math.max(1.0, avgWordLength / 5));

      // Skill factor - assuming average skill
      const skillFactor = 1.0;

      // Calculate adjusted writing speed
      const adjustedWpm = baseWpm / (complexityFactor * skillFactor);

      // Calculate time in minutes
      const timeMinutes = words / adjustedWpm;

      // Format the time
      return this.formatTimeValue(timeMinutes);
    }

    formatTime(wordCount, wpm) {
      if (wordCount === 0) return '~0 min';
      const minutes = wordCount / wpm;
      return this.formatTimeValue(minutes);
    }

    formatTimeValue(minutes) {
      if (minutes < 1) {
        return '< 1 min';
      } else if (minutes < 60) {
        return `~${Math.ceil(minutes)} min`;
      } else {
        const hours = Math.floor(minutes / 60);
        const remainingMinutes = Math.ceil(minutes % 60);
        return `~${hours}h ${remainingMinutes}m`;
      }
    }

    getReadingTime() {
      return this.getStats().readingTime;
    }

    getHandwritingTime() {
      return this.getStats().handwritingTime;
    }

    getKeyboardTime() {
      return this.getStats().keyboardTime;
    }

    getReadabilityScore() {
      // Simple readability score based on average sentence length and word length
      const words = this.text.split(/\s+/).filter(word => word.length > 0);
      const sentences = this.text.split(/[.!?]+/).filter(sentence => sentence.trim().length > 0);

      if (words.length === 0 || sentences.length === 0) {
        return 0;
      }

      const avgSentenceLength = words.length / sentences.length;
      const avgWordLength = words.join('').length / words.length;

      // Higher score for shorter sentences and words (easier to read)
      const sentenceScore = Math.max(0, 100 - (avgSentenceLength - 10) * 5);
      const wordScore = Math.max(0, 100 - (avgWordLength - 4) * 10);

      return Math.round((sentenceScore + wordScore) / 2);
    }
  }

  // Create the analyze command
  const command = new Command('devtools-analyze');

  command
    .description('Analyze text content in files')
    .argument('<patterns...>', 'File patterns to analyze (e.g., "src/**/*.md")')
    .option('--summary', 'Show summary only', false)
    .option('--ignore <pattern>', 'Files to ignore (comma-separated)', value => value.split(',').map(item => item.trim()))
    .option('--output <path>', 'Write report to file')
    .action(async (patterns, options) => {
      try {
        // Start spinner
        const spinner = createSpinner({
          text: 'Analyzing files...',
          color: 'cyan',
          spinner: 'dots'
        }).start();

        // Process each file
        let results = [];

        // Default ignore patterns
        const defaultIgnore = [
          '**/node_modules/**',
          '**/dist/**',
          '**/build/**',
          '**/.git/**',
          '**/package-lock.json',
          '**/yarn.lock',
          '**/*.min.js',
          '**/*.min.css',
          '**/*.bundle.js'
        ];

        // Combine with user-provided ignore patterns
        const ignorePatterns = options.ignore
          ? [...defaultIgnore, ...options.ignore]
          : defaultIgnore;

        // Normalize patterns for Windows paths
        const normalizedPatterns = patterns.map(pattern => {
          // Convert Windows backslashes to forward slashes for glob
          return pattern.replace(/\\/g, '/');
        });

        // Find all files matching the patterns
        const files = await fg(normalizedPatterns, {
          ignore: ignorePatterns,
          onlyFiles: true,
          absolute: true, // Use absolute paths to handle Windows paths better
          followSymbolicLinks: false // Don't follow symlinks to avoid circular references
        });

        // Create a word counter
        const wordCounter = new WordCounter();

        // Process each file
        for (const file of files) {
          try {
            // Read the file
            const content = fs.readFileSync(file, 'utf8');

            // Skip binary files
            if (isBinaryContent(content)) {
              continue;
            }

            // Set the text and get stats
            wordCounter.setText(content);
            const stats = wordCounter.getStats();
            const readabilityScore = wordCounter.getReadabilityScore();

            results.push({
              path: file,
              success: true,
              stats: {
                ...stats,
                readabilityScore
              }
            });
          } catch (error) {
            results.push({
              path: file,
              success: false,
              error: error.message
            });
          }
        }

        // Stop spinner
        spinner.succeed(`Analyzed ${results.length} files`);

        // Calculate summary
        const successResults = results.filter(r => r.success);
        const totalWords = successResults.reduce((sum, r) => sum + r.stats.words, 0);
        const totalCharacters = successResults.reduce((sum, r) => sum + r.stats.characters, 0);
        const totalReadabilityScore = successResults.length > 0
          ? successResults.reduce((sum, r) => sum + r.stats.readabilityScore, 0) / successResults.length
          : 0;

        // Log results
        console.log('\n' + chalk.bold('Detailed Results:'));

        if (!options.summary && successResults.length > 0) {
          successResults.forEach(result => {
            console.log(`\n${chalk.cyan(result.path)}:`);
            console.log(`  Words: ${result.stats.words}`);
            console.log(`  Characters: ${result.stats.characters}`);
            console.log(`  Sentences: ${result.stats.sentences}`);
            console.log(`  Paragraphs: ${result.stats.paragraphs}`);
            console.log(`  Reading Time: ${result.stats.readingTime}`);
            console.log(`  Handwriting Time: ${result.stats.handwritingTime || '~0 min'}`);
            console.log(`  Keyboard Time: ${result.stats.keyboardTime || '~0 min'}`);
            console.log(`  Readability: ${result.stats.readabilityScore}/100`);
          });
        }

        // Calculate average times
        const calculateAverageTime = (results, timeProperty) => {
          const validResults = results.filter(r => r.success && r.stats && r.stats[timeProperty]);

          if (validResults.length === 0) {
            return '~0 min';
          }

          // For handwriting time, we need to calculate the total words and characters
          if (timeProperty === 'handwritingTime') {
            const totalWords = validResults.reduce((sum, r) => sum + r.stats.words, 0);
            const totalChars = validResults.reduce((sum, r) => sum + r.stats.characters, 0);

            // Create a temporary WordCounter to calculate the handwriting time
            const tempCounter = new WordCounter();
            return tempCounter.estimateHandwritingTime(totalWords, totalChars);
          }

          // For other time properties, use the standard approach
          // Extract numeric values from time strings
          const timeValues = validResults.map(r => {
            const timeStr = r.stats[timeProperty];
            if (timeStr.includes('h')) {
              // Handle "~Xh Ym" format
              const hours = parseInt(timeStr.split('h')[0].replace(/[^0-9]/g, ''), 10) || 0;
              const minutes = parseInt(timeStr.split('h')[1].replace(/[^0-9]/g, ''), 10) || 0;
              return hours * 60 + minutes;
            } else {
              // Handle "~X min" format
              return parseInt(timeStr.replace(/[^0-9]/g, ''), 10) || 0;
            }
          });

          // Calculate average
          const totalMinutes = timeValues.reduce((sum, val) => sum + val, 0);
          const avgMinutes = totalMinutes / timeValues.length;

          // Format the result
          if (avgMinutes < 1) {
            return '< 1 min';
          } else if (avgMinutes < 60) {
            return `~${Math.ceil(avgMinutes)} min`;
          } else {
            const hours = Math.floor(avgMinutes / 60);
            const remainingMinutes = Math.ceil(avgMinutes % 60);
            return `~${hours}h ${remainingMinutes}m`;
          }
        };

        const avgReadingTime = calculateAverageTime(successResults, 'readingTime');
        const avgHandwritingTime = calculateAverageTime(successResults, 'handwritingTime');
        const avgKeyboardTime = calculateAverageTime(successResults, 'keyboardTime');

        console.log('\n' + chalk.bold('Summary:'));
        console.log(`  Total Files: ${successResults.length}`);
        console.log(`  Total Words: ${totalWords}`);
        console.log(`  Total Characters: ${totalCharacters}`);
        console.log(`  Average Readability: ${totalReadabilityScore.toFixed(2)}/100`);
        console.log(`  Estimated Reading Time: ${avgReadingTime}`);
        console.log(`  Estimated Handwriting Time: ${avgHandwritingTime}`);
        console.log(`  Estimated Keyboard Time: ${avgKeyboardTime}`);

        // Write report to file if requested
        if (options.output) {
          const report = {
            summary: {
              totalFiles: successResults.length,
              totalWords,
              totalCharacters,
              averageReadability: totalReadabilityScore,
              estimatedReadingTime: avgReadingTime,
              estimatedHandwritingTime: avgHandwritingTime,
              estimatedKeyboardTime: avgKeyboardTime
            },
            files: successResults.map(r => ({
              path: r.path,
              stats: r.stats
            }))
          };

          fs.writeFileSync(options.output, JSON.stringify(report, null, 2), 'utf8');
          console.log(`\nReport written to ${options.output}`);
        }

      } catch (error) {
        console.error(chalk.red('✗ ') + error.message);
        process.exit(1);
      }
    });

  // Helper function to check if content is binary
  function isBinaryContent(content) {
    // Simple binary check: if the content contains a high percentage of null bytes or
    // other control characters, it's likely binary
    const controlCharCount = content.split('').filter(char => {
      const code = char.charCodeAt(0);
      return code < 9 || (code > 13 && code < 32 && code !== 27);
    }).length;

    // If more than 5% is control chars, consider binary
    return controlCharCount > content.length * 0.05;
  }

  // Execute the command
  command.parse(process.argv);
} catch (error) {
  console.error('Error loading command:', error.message);
  process.exit(1);
}
