<?php

namespace Modules\ClinicSite\Http\Controllers;

use App\System;
use App\Http\Controllers\Controller;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
use Modules\ClinicSite\Entities\CsSite;
use Modules\ClinicSite\Entities\CsPage;
use Modules\ClinicSite\Support\BlockRegistry;

class InstallController extends Controller
{
    private $module_name;
    private $app_version;

    public function __construct()
    {
        $this->module_name = config('clinicsite.name');
        $this->app_version = config('clinicsite.module_version');
    }

    private function ensureClinicCoreInstalled()
    {
        // ClinicCore is the human-clinic core this website extends. Detect it by
        // its installed schema (the version system-property isn't always set).
        if (! \Illuminate\Support\Facades\Schema::hasTable('clc_patients')) {
            return 'The ClinicCore module must be installed before ClinicSite. Please install ClinicCore first.';
        }
        return null;
    }

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

        if ($gateMsg = $this->ensureClinicCoreInstalled()) {
            return redirect()
                ->action('\App\Http\Controllers\Install\ModulesController@index')
                ->with('status', ['success' => 0, 'msg' => $gateMsg]);
        }

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

        $is_installed = System::getProperty($this->module_name . '_version');

        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]);
            System::addProperty($this->module_name . '_version', $this->app_version);
            $this->assignPermissionsToAdmin();
            $this->seedDefaultSite();
        }

        return redirect()
            ->action('\App\Http\Controllers\Install\ModulesController@index')
            ->with('status', ['success' => 1, 'msg' => 'ClinicSite module installed successfully']);
    }

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

        try {
            if ($gateMsg = $this->ensureClinicCoreInstalled()) {
                return redirect()
                    ->action('\App\Http\Controllers\Install\ModulesController@index')
                    ->with('status', ['success' => 0, 'msg' => $gateMsg]);
            }

            $is_installed = System::getProperty($this->module_name . '_version');
            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]);
            System::addProperty($this->module_name . '_version', $this->app_version);
            $this->assignPermissionsToAdmin();
            $this->seedDefaultSite();

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

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

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

        try {
            if ($gateMsg = $this->ensureClinicCoreInstalled()) {
                return redirect()->back()->with('status', ['success' => 0, 'msg' => $gateMsg]);
            }

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

            Artisan::call('module:migrate', ['module' => $this->module_name]);
            System::setProperty($this->module_name . '_version', $this->app_version);
            $this->assignPermissionsToAdmin();

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

        return redirect()->back()->with('status', $output);
    }

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

        try {
            System::removeProperty($this->module_name . '_version');
            $output = ['success' => 1, 'msg' => 'ClinicSite module uninstalled successfully'];
        } catch (\Exception $e) {
            \Log::emergency('File:' . $e->getFile() . ' Line:' . $e->getLine() . ' Message:' . $e->getMessage());
            $output = ['success' => 0, 'msg' => $e->getMessage()];
        }

        return redirect()->back()->with('status', $output);
    }

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

        ini_set('max_execution_time', 0);
        Artisan::call('module:migrate', ['module' => $this->module_name]);
        $this->assignPermissionsToAdmin();

        return redirect()
            ->action('\App\Http\Controllers\Install\ModulesController@index')
            ->with('status', ['success' => 1, 'msg' => 'ClinicSite module repaired']);
    }

    private function assignPermissionsToAdmin(): void
    {
        $permissions = [
            'clinic_site.access_module',
            'clinic_site.manage_content',
            'clinic_site.manage_design',
            'clinic_site.manage_settings',
        ];

        foreach ($permissions as $permission) {
            Permission::firstOrCreate(['name' => $permission, 'guard_name' => 'web']);
        }

        $business_id = request()->session()->get('user.business_id');
        if (!empty($business_id)) {
            $role = Role::where('name', 'Admin#' . $business_id)->first();
            if ($role) {
                $role->givePermissionTo($permissions);
            }
        }
    }

    /** Give the business a ready-to-edit website so the CMS isn't empty. */
    private function seedDefaultSite(): void
    {
        $businessId = request()->session()->get('user.business_id');
        if (empty($businessId)) {
            return;
        }

        $business = \App\Business::find($businessId);
        $name = $business->name ?? 'Our Clinic';

        $site = CsSite::firstOrCreate(
            ['business_id' => $businessId],
            [
                'enabled' => false,
                'status'  => 'draft',
                'theme'   => 'aurora',
                'name'    => $name,
                'tagline' => 'Compassionate, modern care for you and your family.',
                'subdomain_slug' => Str::slug($name) ?: ('clinic-' . $businessId),
                'contact' => [
                    'phone'   => $business->mobile ?? '',
                    'email'   => $business->email ?? '',
                    'address' => '',
                ],
                'social'  => [],
                'hours'   => BlockRegistry::defaults('hours')['items'] ?? [],
            ]
        );

        if ($site->pages()->count() === 0) {
            $order = ['hero', 'services', 'about', 'stats', 'team', 'testimonials', 'gallery', 'faq', 'hours', 'cta', 'contact'];
            $blocks = [];
            foreach ($order as $type) {
                $blocks[] = [
                    'id'   => Str::random(8),
                    'type' => $type,
                    'data' => BlockRegistry::defaults($type),
                ];
            }

            CsPage::create([
                'site_id'     => $site->id,
                'business_id' => $businessId,
                'title'       => 'Home',
                'slug'        => 'home',
                'is_home'     => true,
                'status'      => 'published',
                'sort'        => 0,
                'show_in_nav' => true,
                'blocks'      => $blocks,
            ]);
        }
    }
}
