<?php

namespace Modules\MedBloodBank\Http\Controllers;

use App\Http\Controllers\Controller;
use App\System;
use Composer\Semver\Comparator;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;

/**
 * Standard module install/update/repair endpoints, mirroring the MedBilling
 * InstallController. The install gate is the LOWERCASE `medbloodbank_version`
 * System property — the exact key the core's ModuleUtil::isModuleInstalled()
 * reads (strtolower(name).'_version').
 */
class InstallController extends Controller
{
    private $module_name;

    private $app_version;

    private $version_key;

    public function __construct()
    {
        $this->module_name = config('medbloodbank.name', 'MedBloodBank');
        $this->app_version = config('medbloodbank.module_version', '1.0.0');
        $this->version_key = strtolower($this->module_name) . '_version'; // medbloodbank_version
    }

    public function index()
    {
        if (! auth()->user()->can('superadmin')) {
            abort(403, 'Unauthorized action.');
        }

        ini_set('max_execution_time', 0);
        ini_set('memory_limit', '512M');
        config(['app.debug' => true]);
        Artisan::call('config:clear');

        $is_installed = System::getProperty($this->version_key);

        if (empty($is_installed)) {
            DB::statement('SET default_storage_engine=INNODB;');
            Artisan::call('module:migrate', ['module' => $this->module_name]);
            Artisan::call('module:publish', ['module' => $this->module_name]);
            Artisan::call('module:seed', ['module' => $this->module_name]);
            System::addProperty($this->version_key, $this->app_version);
            $this->assignPermissionsToAdmin();
        }

        $output = ['success' => 1, 'msg' => 'MedBloodBank module installed successfully'];

        return redirect()
            ->action('\App\Http\Controllers\Install\ModulesController@index')
            ->with('status', $output);
    }

    public function install()
    {
        if (! auth()->user()->can('superadmin')) {
            abort(403, 'Unauthorized action.');
        }

        try {
            $is_installed = System::getProperty($this->version_key);
            if (! empty($is_installed)) {
                abort(404);
            }

            ini_set('max_execution_time', 0);
            ini_set('memory_limit', '512M');

            DB::statement('SET default_storage_engine=INNODB;');
            Artisan::call('module:migrate', ['module' => $this->module_name]);
            Artisan::call('module:publish', ['module' => $this->module_name]);
            Artisan::call('module:seed', ['module' => $this->module_name]);
            System::addProperty($this->version_key, $this->app_version);
            $this->assignPermissionsToAdmin();

            $output = ['success' => 1, 'msg' => 'MedBloodBank module installed successfully'];
        } catch (\Exception $e) {
            \Log::emergency('File:' . $e->getFile() . ' Line:' . $e->getLine() . ' Message:' . $e->getMessage());
            $output = ['success' => false, 'msg' => $e->getMessage()];
        }

        return redirect()
            ->action('\App\Http\Controllers\Install\ModulesController@index')
            ->with('status', $output);
    }

    public function uninstall()
    {
        if (! auth()->user()->can('superadmin')) {
            abort(403, 'Unauthorized action.');
        }

        try {
            // Unregister only — mbb_* tables and data are kept.
            System::removeProperty($this->version_key);
            $output = ['success' => true, 'msg' => 'MedBloodBank module uninstalled'];
        } catch (\Exception $e) {
            $output = ['success' => false, 'msg' => $e->getMessage()];
        }

        return redirect()->back()->with(['status' => $output]);
    }

    public function update()
    {
        if (! auth()->user()->can('superadmin')) {
            abort(403, 'Unauthorized action.');
        }

        $current_version = System::getProperty($this->version_key);

        if (! Comparator::greaterThan($this->app_version, $current_version)) {
            $output = ['success' => false, 'msg' => 'Already on latest version v' . $this->app_version . '. Use Repair if you need to re-run migrations.'];

            return redirect()->back()->with(['status' => $output]);
        }

        try {
            ini_set('max_execution_time', 0);
            ini_set('memory_limit', '512M');

            config(['app.debug' => true]);
            Artisan::call('config:clear');
            Artisan::call('cache:clear');

            DB::statement('SET default_storage_engine=INNODB;');
            Artisan::call('module:migrate', ['module' => $this->module_name]);
            Artisan::call('module:publish', ['module' => $this->module_name]);
            Artisan::call('module:seed', ['module' => $this->module_name]);

            System::setProperty($this->version_key, $this->app_version);
            $this->assignPermissionsToAdmin();

            $output = ['success' => 1, 'msg' => 'MedBloodBank updated to v' . $this->app_version];
        } catch (\Exception $e) {
            \Log::emergency('File:' . $e->getFile() . ' Line:' . $e->getLine() . ' Message:' . $e->getMessage());
            $output = ['success' => false, 'msg' => $e->getMessage()];
        }

        return redirect()->back()->with(['status' => $output]);
    }

    public function repair()
    {
        if (! auth()->user()->can('superadmin')) {
            abort(403, 'Unauthorized action.');
        }

        try {
            ini_set('max_execution_time', 0);
            ini_set('memory_limit', '512M');

            config(['app.debug' => true]);
            Artisan::call('config:clear');
            Artisan::call('cache:clear');

            DB::statement('SET default_storage_engine=INNODB;');

            $migrationPath = base_path('Modules/MedBloodBank/Database/Migrations');
            $files = glob($migrationPath . '/*.php');
            if (! empty($files)) {
                $migrationNames = array_map(fn ($f) => pathinfo($f, PATHINFO_FILENAME), $files);
                DB::table('migrations')->whereIn('migration', $migrationNames)->delete();
            }

            Artisan::call('module:migrate', ['module' => $this->module_name]);
            Artisan::call('module:publish', ['module' => $this->module_name]);
            Artisan::call('module:seed', ['module' => $this->module_name]);

            System::setProperty($this->version_key, $this->app_version);
            $this->assignPermissionsToAdmin();

            $output = ['success' => 1, 'msg' => 'MedBloodBank repaired to v' . $this->app_version];
        } catch (\Exception $e) {
            \Log::emergency('File:' . $e->getFile() . ' Line:' . $e->getLine() . ' Message:' . $e->getMessage());
            $output = ['success' => false, 'msg' => $e->getMessage()];
        }

        return redirect()->back()->with(['status' => $output]);
    }

    private function assignPermissionsToAdmin()
    {
        try {
            $adminRole = Role::where('name', 'Admin')->first();
            if ($adminRole) {
                $permissions = Permission::where('name', 'LIKE', 'mbb.%')->get();
                foreach ($permissions as $permission) {
                    if (! $adminRole->hasPermissionTo($permission)) {
                        $adminRole->givePermissionTo($permission);
                    }
                }
            }
        } catch (\Exception $e) {
            \Log::warning('Could not assign MedBloodBank permissions to Admin: ' . $e->getMessage());
        }
    }
}
