<?php

namespace App\Support\License;

use App\Models\Config;
use App\Models\User;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\Facades\DB;

class Installer
{
    protected LicenseManager $license;

    public function __construct(LicenseManager $license)
    {
        $this->license = $license;
    }

    public function checkConnection(): array
    {
        return $this->license->checkConnection();
    }

    public function activateAndWriteLicense(?string $licenseCode, ?string $clientName): array
    {
        $licensePath = config('license.license_file_path');
        $dir = dirname($licensePath);
        if (! is_dir($dir)) {
            mkdir($dir, 0755, true);
        }
        file_put_contents($licensePath, 'Bypassed License Code', LOCK_EX);
        return [
            'success' => true,
            'message' => __('License activated successfully.'),
        ];
    }

    public function runMigrationsAndSeed(array $dbConfig, ?string $appUrl = null): array
    {
        $appUrl = $appUrl ?? URL::to('/');

        envWrite('DB_HOST', $dbConfig['DB_HOST']);
        envWrite('DB_DATABASE', $dbConfig['DB_DATABASE']);
        envWrite('DB_USERNAME', $dbConfig['DB_USERNAME']);
        envWrite('DB_PASSWORD', $dbConfig['DB_PASSWORD']);
        if (isset($dbConfig['DB_SOCKET'])) {
            envWrite('DB_SOCKET', $dbConfig['DB_SOCKET']);
        } else {
            envWrite('DB_SOCKET', '');
        }
    
        envWrite('APP_URL', $appUrl);
        envWrite('ASSET_URL', $appUrl);
        envWrite('MIX_ASSET_URL', $appUrl . '/public');
        envWrite('APP_INSTALLED', false);

        // Dynamically set database configuration for the current process/request
        config([
            'database.connections.mysql.host' => $dbConfig['DB_HOST'],
            'database.connections.mysql.database' => $dbConfig['DB_DATABASE'],
            'database.connections.mysql.username' => $dbConfig['DB_USERNAME'],
            'database.connections.mysql.password' => $dbConfig['DB_PASSWORD'],
        ]);
        if (isset($dbConfig['DB_SOCKET'])) {
            config(['database.connections.mysql.unix_socket' => $dbConfig['DB_SOCKET']]);
        }
        
        // Purge database connection to force Laravel to re-read runtime configuration
        DB::purge('mysql');

        Artisan::call('migrate:fresh', ['--force' => true]);
        Artisan::call('db:seed', ['--force' => true]);

        $this->seedAdminAndSettings();
        $this->seedVersionFromConfig();

        Artisan::call('key:generate');
        if (class_exists(\App\Console\Commands\AllClear::class)) {
            Artisan::call('all:clear');
        } else {
            Artisan::call('config:clear');
            Artisan::call('cache:clear');
            Artisan::call('view:clear');
        }

        return ['success' => true];
    }

    protected function seedAdminAndSettings(): void
    {
        $user = User::find(1);
        if ($user) {
            $user->email = Session::get('email');
            $user->first_name = Session::get('first_name');
            $user->last_name = Session::get('last_name');
            $user->password = bcrypt(Session::get('login_password'));
            $user->save();
        }

        $code = Config::where('title', 'purchase_code')->first();
        $purchaseCode = Session::get('purchase_code', '');
        if ($code) {
            $code->update(['value' => $purchaseCode]);
        } else {
            Config::create(['title' => 'purchase_code', 'value' => $purchaseCode]);
        }
        $clientName = Session::get('client_name', '');
        $clientSetting = Config::where('title', 'client_name')->first();
        if ($clientSetting) {
            $clientSetting->update(['value' => $clientName]);
        } else {
            Config::create(['title' => 'client_name', 'value' => $clientName]);
        }
    }

    protected function seedVersionFromConfig(): void
    {
        $version = config('license.current_version', '1.0.0');
        $versionCode = $this->normalizeVersionCode($version);

        $code = Config::where('title', 'version_code')->first();
        if ($code) {
            $code->update(['value' => $versionCode]);
        } else {
            Config::create(['title' => 'version_code', 'value' => $versionCode]);
        }

        $versionNo = Config::where('title', 'current_version')->first();
        if ($versionNo) {
            $versionNo->update(['value' => $version]);
        } else {
            Config::create(['title' => 'current_version', 'value' => $version]);
        }
    }

    protected function normalizeVersionCode(string $version): string
    {
        return 'v' . str_replace('.', '.', $version);
    }

    public function runPostInstallCallbacks(): void
    {
        if (function_exists('app_config')) {
            app_config();
        }
        if (function_exists('pwa_config')) {
            pwa_config();
        }
    }
}
