<?php

namespace Database\Seeders;

use App\Enums\Gateway\SMSGatewayEnum;
use App\Models\User;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Database\Seeders\Core\CountrySeeder;
use Database\Seeders\Core\LangSeeder;
use Database\Seeders\Core\MailGatewaySeeder;
use Database\Seeders\Core\SettingsSeeder;
use Database\Seeders\Core\SMSGatewaySeeder;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
use App\Helpers\InstallationLogger;
use Exception;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     */
    public function run(): void
    {
        // Start installation logging session
        InstallationLogger::startSession();
        InstallationLogger::info('=== DATABASE SEEDING STARTED ===');

        try {
            // Log system information
            $this->logSystemInfo();

            // Check database connection
            if (!$this->checkDatabaseConnection()) {
                InstallationLogger::error('Database connection failed - aborting seeding');
                throw new Exception('Database connection failed during seeding');
            }

            // Core installation seeders - Required for system functionality
            $seeders = [
                SettingsSeeder::class,
                PlatformSeeder::class, 
                LangSeeder::class
            ];

            InstallationLogger::info('Will run ' . count($seeders) . ' core seeders');

            $successCount = 0;
            $failCount = 0;

            foreach ($seeders as $seederClass) {
                if ($this->runSeederWithLogging($seederClass)) {
                    $successCount++;
                } else {
                    $failCount++;
                }
            }

            InstallationLogger::info("Seeding Summary: {$successCount} successful, {$failCount} failed");

            if ($failCount > 0) {
                InstallationLogger::warning("Some seeders failed but installation continued");
                InstallationLogger::endSession(false);
            } else {
                InstallationLogger::info('=== DATABASE SEEDING COMPLETED SUCCESSFULLY ===');
                InstallationLogger::endSession(true);
            }

        } catch (Exception $e) {
            InstallationLogger::error('Fatal error during database seeding: ' . $e->getMessage());
            InstallationLogger::error('Stack trace: ' . $e->getTraceAsString());
            InstallationLogger::endSession(false);
            throw $e;
        }

        // Note: Demo data seeders have been moved to DemoSeeder.php
        // Run manually after installation: php artisan db:seed --class=DemoSeeder
    }

    /**
     * Run a seeder with comprehensive logging
     */
    private function runSeederWithLogging(string $seederClass): bool
    {
        $startTime = microtime(true);
        $seederName = class_basename($seederClass);

        InstallationLogger::info("Starting seeder: {$seederName}");

        try {
            // Start transaction for this seeder
            DB::beginTransaction();

            $this->call($seederClass);

            // Commit if successful
            DB::commit();

            $duration = round((microtime(true) - $startTime) * 1000, 2);
            InstallationLogger::info("{$seederName} completed successfully in {$duration}ms");

            return true;

        } catch (Exception $e) {
            // Rollback on error
            DB::rollBack();

            $duration = round((microtime(true) - $startTime) * 1000, 2);
            InstallationLogger::error("{$seederName} FAILED after {$duration}ms");
            InstallationLogger::error("{$seederName} Error: " . $e->getMessage());
            InstallationLogger::error("{$seederName} File: " . $e->getFile() . " Line: " . $e->getLine());
            InstallationLogger::debug("{$seederName} Stack trace: " . $e->getTraceAsString());

            // Continue with other seeders instead of stopping
            InstallationLogger::warning("Continuing with remaining seeders despite {$seederName} failure");

            return false;
        }
    }

    /**
     * Check database connection
     */
    private function checkDatabaseConnection(): bool
    {
        try {
            DB::connection()->getPdo();
            InstallationLogger::info('Database connection verified');

            // Log database info
            $dbName = DB::connection()->getDatabaseName();
            $driver = DB::connection()->getDriverName();
            InstallationLogger::info("Connected to {$driver} database: {$dbName}");

            // Test a simple query
            $tableCount = DB::select("SELECT COUNT(*) as count FROM information_schema.tables WHERE table_schema = ?", [$dbName])[0]->count ?? 0;
            InstallationLogger::info("Database has {$tableCount} tables");

            return true;
        } catch (Exception $e) {
            InstallationLogger::error('Database connection failed: ' . $e->getMessage());
            return false;
        }
    }

    /**
     * Log system information for debugging
     */
    private function logSystemInfo(): void
    {
        InstallationLogger::info('=== SYSTEM INFORMATION ===');
        InstallationLogger::info('PHP Version: ' . PHP_VERSION);
        InstallationLogger::info('Laravel Version: ' . app()->version());
        InstallationLogger::info('Environment: ' . app()->environment());
        InstallationLogger::info('Memory Limit: ' . ini_get('memory_limit'));
        InstallationLogger::info('Max Execution Time: ' . ini_get('max_execution_time'));
        InstallationLogger::info('Server Software: ' . ($_SERVER['SERVER_SOFTWARE'] ?? 'Unknown'));

        // Log environment variables that might affect seeding
        InstallationLogger::info('=== DATABASE CONFIGURATION ===');
        InstallationLogger::info('DB_CONNECTION: ' . env('DB_CONNECTION', 'not set'));
        InstallationLogger::info('DB_HOST: ' . env('DB_HOST', 'not set'));
        InstallationLogger::info('DB_PORT: ' . env('DB_PORT', 'not set'));
        InstallationLogger::info('DB_DATABASE: ' . env('DB_DATABASE', 'not set'));
        InstallationLogger::info('DB_USERNAME: ' . (env('DB_USERNAME') ? 'set' : 'not set'));

        // Log file permissions
        $this->logFilePermissions();
    }

    /**
     * Check and log file permissions
     */
    private function logFilePermissions(): void
    {
        InstallationLogger::info('=== FILE PERMISSIONS ===');

        $paths = [
            'storage' => storage_path(),
            'bootstrap/cache' => base_path('bootstrap/cache'),
            'config' => config_path(),
            'database' => database_path(),
        ];

        foreach ($paths as $name => $path) {
            if (file_exists($path)) {
                $perms = fileperms($path);
                $readable = is_readable($path) ? 'readable' : 'not readable';
                $writable = is_writable($path) ? 'writable' : 'not writable';
                InstallationLogger::info("{$name}: {$readable}, {$writable} (perms: " . decoct($perms) . ")");
            } else {
                InstallationLogger::warning("{$name}: path does not exist ({$path})");
            }
        }
    }
}
