<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;

/**
 * Security Check Command
 * Performs comprehensive security audit of the application
 */
class SecurityCheckCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'system:security-check';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Perform comprehensive security audit of the application';

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        $this->info('🔒 Starting Security Audit...');
        $this->newLine();

        $issues = [];
        $warnings = [];
        $passed = [];

        // Check 1: Debug Mode
        $this->checkDebugMode($issues, $warnings, $passed);

        // Check 2: File Permissions
        $this->checkFilePermissions($issues, $warnings, $passed);

        // Check 3: Environment File Security
        $this->checkEnvironmentSecurity($issues, $warnings, $passed);

        // Check 4: HTTPS Usage
        $this->checkHttpsUsage($issues, $warnings, $passed);

        // Check 5: Database Security
        $this->checkDatabaseSecurity($issues, $warnings, $passed);

        // Check 6: Storage Security
        $this->checkStorageSecurity($issues, $warnings, $passed);

        // Check 7: PHP Version
        $this->checkPhpVersion($issues, $warnings, $passed);

        // Check 8: Session Security
        $this->checkSessionSecurity($issues, $warnings, $passed);

        // Display Results
        $this->displayResults($issues, $warnings, $passed);

        return count($issues) > 0 ? 1 : 0;
    }

    /**
     * Check if debug mode is disabled
     */
    private function checkDebugMode(array &$issues, array &$warnings, array &$passed): void
    {
        if (config('app.debug') === true && config('app.env') === 'production') {
            $issues[] = '❌ CRITICAL: Debug mode is enabled in production!';
        } elseif (config('app.debug') === true) {
            $warnings[] = '⚠️  WARNING: Debug mode is enabled (acceptable in development)';
        } else {
            $passed[] = '✅ Debug mode is disabled';
        }
    }

    /**
     * Check file permissions
     */
    private function checkFilePermissions(array &$issues, array &$warnings, array &$passed): void
    {
        $storagePath = storage_path();
        $bootstrapCachePath = base_path('bootstrap/cache');

        // Check storage permissions
        if (File::isWritable($storagePath)) {
            $passed[] = '✅ Storage directory is writable';
        } else {
            $issues[] = '❌ Storage directory is not writable';
        }

        // Check bootstrap/cache permissions
        if (File::isWritable($bootstrapCachePath)) {
            $passed[] = '✅ Bootstrap cache directory is writable';
        } else {
            $warnings[] = '⚠️  Bootstrap cache directory is not writable (may affect performance)';
        }

        // Check .env file permissions
        $envPath = base_path('.env');
        if (File::exists($envPath)) {
            $perms = substr(sprintf('%o', fileperms($envPath)), -4);
            if ($perms === '0644' || $perms === '0600') {
                $passed[] = '✅ .env file has secure permissions ('.$perms.')';
            } else {
                $warnings[] = '⚠️  .env file permissions are '.$perms.' (recommended: 0600 or 0644)';
            }
        }
    }

    /**
     * Check environment file security
     */
    private function checkEnvironmentSecurity(array &$issues, array &$warnings, array &$passed): void
    {
        $envPath = base_path('.env');

        if (! File::exists($envPath)) {
            $issues[] = '❌ .env file does not exist';

            return;
        }

        $envContent = File::get($envPath);

        // Check for exposed secrets
        if (str_contains($envContent, 'APP_KEY=') && ! str_contains($envContent, 'base64:')) {
            $warnings[] = '⚠️  APP_KEY may not be properly encrypted';
        } else {
            $passed[] = '✅ APP_KEY appears to be encrypted';
        }

        // Check for default values
        if (str_contains($envContent, 'APP_DEBUG=true') && config('app.env') === 'production') {
            $issues[] = '❌ APP_DEBUG is set to true in production';
        }

        // Check if sensitive data is exposed
        if (str_contains($envContent, 'password') && str_contains($envContent, '=')) {
            $passed[] = '✅ Database credentials are configured';
        }
    }

    /**
     * Check HTTPS usage
     */
    private function checkHttpsUsage(array &$issues, array &$warnings, array &$passed): void
    {
        $appUrl = config('app.url');

        if (config('app.env') === 'production') {
            if (str_starts_with($appUrl, 'https://')) {
                $passed[] = '✅ Application URL uses HTTPS';
            } else {
                $issues[] = '❌ Application URL does not use HTTPS in production';
            }
        } else {
            $warnings[] = '⚠️  HTTPS check skipped (development environment)';
        }
    }

    /**
     * Check database security
     */
    private function checkDatabaseSecurity(array &$issues, array &$warnings, array &$passed): void
    {
        try {
            $connection = DB::connection();
            $driver = $connection->getDriverName();

            $passed[] = '✅ Database connection successful ('.$driver.')';

            // Check if using prepared statements (Laravel uses PDO by default)
            if ($driver === 'mysql' || $driver === 'pgsql') {
                $passed[] = '✅ Database driver supports prepared statements';
            }

        } catch (\Exception $e) {
            $issues[] = '❌ Database connection failed: '.$e->getMessage();
        }
    }

    /**
     * Check storage security
     */
    private function checkStorageSecurity(array &$issues, array &$warnings, array &$passed): void
    {
        $storagePath = storage_path('app');
        $publicStoragePath = storage_path('app/public');

        if (File::exists($storagePath)) {
            $passed[] = '✅ Storage directory exists';
        } else {
            $issues[] = '❌ Storage directory does not exist';
        }

        // Check if storage/app/public is linked
        $publicLink = public_path('storage');
        if (File::exists($publicLink) || is_link($publicLink)) {
            $passed[] = '✅ Storage symlink exists';
        } else {
            $warnings[] = '⚠️  Storage symlink does not exist (run: php artisan storage:link)';
        }
    }

    /**
     * Check PHP version
     */
    private function checkPhpVersion(array &$issues, array &$warnings, array &$passed): void
    {
        $phpVersion = PHP_VERSION;
        $minVersion = '8.2.0';

        if (version_compare($phpVersion, $minVersion, '>=')) {
            $passed[] = '✅ PHP version is '.$phpVersion.' (meets requirement: >= '.$minVersion.')';
        } else {
            $issues[] = '❌ PHP version '.$phpVersion.' is below minimum requirement ('.$minVersion.')';
        }
    }

    /**
     * Check session security
     */
    private function checkSessionSecurity(array &$issues, array &$warnings, array &$passed): void
    {
        $sessionDriver = config('session.driver');
        $sessionSecure = config('session.secure');
        $sessionHttpOnly = config('session.http_only');

        if ($sessionDriver === 'database' || $sessionDriver === 'redis') {
            $passed[] = '✅ Session driver is secure ('.$sessionDriver.')';
        } else {
            $warnings[] = '⚠️  Session driver is '.$sessionDriver.' (consider using database or redis)';
        }

        if ($sessionHttpOnly) {
            $passed[] = '✅ Session cookies are HTTP-only';
        } else {
            $warnings[] = '⚠️  Session cookies are not HTTP-only';
        }

        if (config('app.env') === 'production' && ! $sessionSecure) {
            $warnings[] = '⚠️  Session cookies are not secure (should be true in production)';
        } elseif ($sessionSecure) {
            $passed[] = '✅ Session cookies are secure';
        }
    }

    /**
     * Display security audit results
     */
    private function displayResults(array $issues, array $warnings, array $passed): void
    {
        $this->newLine();
        $this->info('📊 Security Audit Results:');
        $this->newLine();

        if (count($passed) > 0) {
            $this->info('✅ Passed Checks ('.count($passed).'):');
            foreach ($passed as $check) {
                $this->line('   '.$check);
            }
            $this->newLine();
        }

        if (count($warnings) > 0) {
            $this->warn('⚠️  Warnings ('.count($warnings).'):');
            foreach ($warnings as $warning) {
                $this->line('   '.$warning);
            }
            $this->newLine();
        }

        if (count($issues) > 0) {
            $this->error('❌ Critical Issues ('.count($issues).'):');
            foreach ($issues as $issue) {
                $this->line('   '.$issue);
            }
            $this->newLine();
            $this->error('⚠️  Please fix the critical issues before deploying to production!');
        } else {
            $this->info('✅ No critical security issues found!');
        }

        $this->newLine();
        $this->info('Security audit completed.');
    }
}
