<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use MatthiasMullie\Minify;

class BuildAppJs extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'build:appjs {--no-minify : Skip minification and just concatenate files}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Combine and minify all JS files from resources/assets/js into public/app.js';

    /**
     * Execute the console command.
     */
    public function handle()
    {
        $sourceDir = base_path('resources/assets/js');
        $outputFile = public_path('js/app.js');
        $noMinify = $this->option('no-minify');

        $this->info('Building app.js from resources/assets/js...');

        // Delete old app.js
        if (file_exists($outputFile)) {
            unlink($outputFile);
            $this->info("Deleted old app.js");
        }

        // Get all .js files recursively
        $files = $this->getAllJsFiles($sourceDir);
        
        // Sort files in proper order for AngularJS
        $orderedFiles = $this->orderFilesForAngular($files);

        $this->info("Found " . count($orderedFiles) . " JavaScript files");

        if ($noMinify) {
            // Just concatenate without minification
            $this->concatenateFiles($orderedFiles, $outputFile);
        } else {
            // Minify and concatenate
            $this->minifyFiles($orderedFiles, $outputFile);
        }

        $fileSize = round(filesize($outputFile) / 1024, 2);
        $this->info("✅ New app.js built successfully ({$fileSize} KB)");

        
        // List the file order for verification
        if ($this->getOutput()->isVerbose()) {
            $this->info("\nFile order:");
            foreach ($orderedFiles as $index => $file) {
                $relativePath = str_replace($sourceDir . '/', '', $file);
                $this->line(($index + 1) . ". " . $relativePath);
            }
        }
    }

    /**
     * Get all JavaScript files recursively
     */
    private function getAllJsFiles($sourceDir)
    {
        $files = [];
        $iterator = new \RecursiveIteratorIterator(
            new \RecursiveDirectoryIterator($sourceDir, \RecursiveDirectoryIterator::SKIP_DOTS)
        );

        foreach ($iterator as $file) {
            if ($file->isFile() && $file->getExtension() === 'js') {
                $files[] = $file->getPathname();
            }
        }

        return $files;
    }

    /**
     * Order files for proper AngularJS module loading
     */
    private function orderFilesForAngular($files)
    {
        $ordered = [];
        $moduleFiles = [];
        $archDBFactoryFiles = [];
        $otherFiles = [];

        // First, separate main app file, module files, and others
        foreach ($files as $file) {
            $filename = basename($file);
            $relativePath = str_replace(base_path('resources/assets/js') . '/', '', $file);

            // Main app file should load first
            if ($filename === 'archDB.js') {
                array_unshift($ordered, $file);
            }
            // Module definition files that DON'T contain archDB.factory calls
            elseif ($filename === 'module.js' && !$this->fileContainsArchDBFactory($file)) {
                $moduleFiles[] = $file;
            }
            // Module files that contain archDB.factory calls (need to load after archDB core)
            elseif ($filename === 'module.js' && $this->fileContainsArchDBFactory($file)) {
                $archDBFactoryFiles[] = $file;
            }
            // Everything else
            else {
                $otherFiles[] = $file;
            }
        }

        // Sort module files alphabetically
        sort($moduleFiles);
        sort($archDBFactoryFiles);
        
        // Sort other files alphabetically
        sort($otherFiles);

        // Combine in order: main app -> clean modules -> archDB factory modules -> everything else
        return array_merge($ordered, $moduleFiles, $archDBFactoryFiles, $otherFiles);
    }

    /**
     * Check if a file contains archDB.factory calls
     */
    private function fileContainsArchDBFactory($file)
    {
        $content = file_get_contents($file);
        return strpos($content, 'archDB.factory') !== false;
    }

    /**
     * Concatenate files without minification
     */
    private function concatenateFiles($files, $outputFile)
    {
        $content = '';
        
        foreach ($files as $file) {
            $fileContent = file_get_contents($file);
            $relativePath = str_replace(base_path('resources/assets/js') . '/', '', $file);
            
            $content .= "/* === {$relativePath} === */\n";
            $content .= $fileContent;
            $content .= "\n\n";
        }

        file_put_contents($outputFile, $content);
    }

    /**
     * Minify and concatenate files
     */
    private function minifyFiles($files, $outputFile)
    {
        $minifier = new Minify\JS();
        
        foreach ($files as $file) {
            $minifier->add($file);
        }

        $minifier->minify($outputFile);
    }
}
