<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Schema;
use ReflectionClass;

class FixModelCasting extends Command
{
    /**
     * The name and signature of the console command.
     */
    protected $signature = 'models:fix-casting {--dry-run : Show what would be changed without making changes} {--auto-fix : Automatically fix models that don\'t extend BaseModel}';

    /**
     * The console command description.
     */
    protected $description = 'Check and fix models to ensure they extend BaseModel for automatic date casting';

    /**
     * Execute the console command.
     */
    public function handle()
    {
        $isDryRun = $this->option('dry-run');
        $autoFix = $this->option('auto-fix');
        
        $this->info('Scanning models for BaseModel inheritance...');
        
        $modelPath = app_path('Models');
        $models = $this->getModelFiles($modelPath);
        
        $issues = [];
        $fixed = [];
        
        foreach ($models as $modelFile) {
            $result = $this->analyzeModel($modelFile, $autoFix && !$isDryRun);
            
            if ($result['hasIssue']) {
                $issues[] = $result;
                
                if ($result['fixed']) {
                    $fixed[] = $result;
                }
            }
        }
        
        // Display results
        if (empty($issues)) {
            $this->info('✅ All models properly extend BaseModel!');
        } else {
            $this->warn("Found " . count($issues) . " model(s) with issues:");
            
            foreach ($issues as $issue) {
                $status = $issue['fixed'] ? '✅ FIXED' : '❌ NEEDS ATTENTION';
                $this->line("  {$status}: {$issue['class']} ({$issue['file']})");
                $this->line("    Current parent: {$issue['currentParent']}");
                
                if (!empty($issue['dateColumns'])) {
                    $this->line("    Date columns found: " . implode(', ', $issue['dateColumns']));
                }
            }
        }
        
        if (!empty($fixed)) {
            $this->info("\n🎉 Fixed " . count($fixed) . " model(s) to extend BaseModel");
        }
        
        if ($isDryRun) {
            $this->info("\n📋 This was a dry run. Use --auto-fix to make actual changes.");
        }
        
        // Clear cache after changes
        if (!$isDryRun && !empty($fixed)) {
            $this->info("Clearing date columns cache...");
            \App\Models\BaseModel::clearDateColumnsCache();
        }
        
        return 0;
    }
    
    /**
     * Get all model files
     */
    private function getModelFiles($directory)
    {
        $files = [];
        
        if (!File::exists($directory)) {
            return $files;
        }
        
        $iterator = new \RecursiveIteratorIterator(
            new \RecursiveDirectoryIterator($directory)
        );
        
        foreach ($iterator as $file) {
            if ($file->isFile() && $file->getExtension() === 'php') {
                $files[] = $file->getPathname();
            }
        }
        
        return $files;
    }
    
    /**
     * Analyze a model file
     */
    private function analyzeModel($filePath, $autoFix = false)
    {
        $content = File::get($filePath);
        $className = $this->extractClassName($content, $filePath);
        
        $result = [
            'file' => str_replace(base_path(), '', $filePath),
            'class' => $className,
            'hasIssue' => false,
            'fixed' => false,
            'currentParent' => 'Unknown',
            'dateColumns' => []
        ];
        
        if (!$className) {
            return $result;
        }
        
        try {
            // Check if class exists and can be reflected
            if (!class_exists($className)) {
                return $result;
            }
            
            $reflection = new ReflectionClass($className);
            $parentClass = $reflection->getParentClass();
            
            if ($parentClass) {
                $result['currentParent'] = $parentClass->getName();
                
                // Check if it doesn't extend BaseModel (but exclude BaseModel itself)
                if ($parentClass->getName() !== 'App\Models\BaseModel' && 
                    $parentClass->getName() === 'Illuminate\Database\Eloquent\Model' &&
                    $className !== 'App\Models\BaseModel') {
                    
                    $result['hasIssue'] = true;
                    
                    // Try to detect date columns by examining the model
                    $result['dateColumns'] = $this->detectDateColumns($className);
                    
                    if ($autoFix) {
                        $result['fixed'] = $this->fixModelFile($filePath, $content);
                    }
                }
            }
            
        } catch (\Exception $e) {
            // Skip problematic files
        }
        
        return $result;
    }
    
    /**
     * Extract class name from file content
     */
    private function extractClassName($content, $filePath)
    {
        // Extract namespace
        preg_match('/namespace\s+([^;]+);/', $content, $namespaceMatches);
        $namespace = $namespaceMatches[1] ?? 'App\Models';
        
        // Extract class name
        preg_match('/class\s+(\w+)/', $content, $classMatches);
        $className = $classMatches[1] ?? null;
        
        if ($className) {
            return $namespace . '\\' . $className;
        }
        
        return null;
    }
    
    /**
     * Detect potential date columns in a model
     */
    private function detectDateColumns($className)
    {
        try {
            $model = new $className;
            $table = $model->getTable();
            
            // Get table columns
            $columns = Schema::getColumnListing($table);
            $dateColumns = [];
            
            foreach ($columns as $column) {
                $columnType = Schema::getColumnType($table, $column);
                
                if (in_array(strtolower($columnType), ['date', 'datetime', 'timestamp']) ||
                    preg_match('/_date$|_at$|^date|_time$/', $column)) {
                    $dateColumns[] = $column;
                }
            }
            
            return $dateColumns;
        } catch (\Exception $e) {
            return [];
        }
    }
    
    /**
     * Fix model file to extend BaseModel
     */
    private function fixModelFile($filePath, $content)
    {
        try {
            // Replace "extends Model" with "extends BaseModel"
            $newContent = preg_replace(
                '/extends\s+Model(\s|{)/',
                'extends BaseModel$1',
                $content
            );
            
            // Make sure BaseModel is imported
            if (!str_contains($content, 'use App\Models\BaseModel;')) {
                // Find the last use statement
                $lines = explode("\n", $newContent);
                $lastUseIndex = -1;
                
                foreach ($lines as $index => $line) {
                    if (str_starts_with(trim($line), 'use ')) {
                        $lastUseIndex = $index;
                    }
                }
                
                if ($lastUseIndex >= 0) {
                    // Insert after last use statement
                    array_splice($lines, $lastUseIndex + 1, 0, 'use App\Models\BaseModel;');
                } else {
                    // Insert after namespace
                    foreach ($lines as $index => $line) {
                        if (str_starts_with(trim($line), 'namespace ')) {
                            array_splice($lines, $index + 2, 0, 'use App\Models\BaseModel;');
                            break;
                        }
                    }
                }
                
                $newContent = implode("\n", $lines);
            }
            
            // Remove the original Model import if it exists
            $newContent = preg_replace('/use\s+Illuminate\\\\Database\\\\Eloquent\\\\Model;\s*\n/', '', $newContent);
            
            File::put($filePath, $newContent);
            return true;
            
        } catch (\Exception $e) {
            return false;
        }
    }
} 