<?php

namespace Modules\MedRegistry\Http\Controllers;

use Illuminate\Http\Request;
use Modules\MedRegistry\Entities\MedregModule;
use Modules\MedRegistry\Entities\MedregModuleInstance;
use Modules\MedRegistry\Services\ModuleLifecycleService;

/**
 * Per-business module instance manager (P1-T2): tenant × location matrix with
 * enable / disable / soft-lock / uninstall actions; department granularity via
 * a select (clc_departments, when ClinicCore is present).
 */
class InstanceController extends MedRegistryBaseController
{
    /** @var ModuleLifecycleService */
    protected $lifecycle;

    public function __construct(ModuleLifecycleService $lifecycle)
    {
        parent::__construct();
        $this->lifecycle = $lifecycle;
    }

    public function index()
    {
        $this->guard('medreg.registry.manage');
        $this->guardSubscription();

        $businessId = $this->businessId();

        $modules = MedregModule::where('is_present', true)
            ->orderByRaw("FIELD(category, 'medical', 'specialty', 'facility', 'support', 'integration', 'core')")
            ->orderBy('sort_order')
            ->orderBy('module_key')
            ->get();

        // instance lookup: module_id → 'loc:<id>' / 'dept:<id>' / 'tenant' → instance
        $instances = [];
        foreach (MedregModuleInstance::where('business_id', $businessId)->get() as $instance) {
            if (! is_null($instance->department_id)) {
                $scope = 'dept:' . $instance->department_id;
            } elseif (! is_null($instance->business_location_id)) {
                $scope = 'loc:' . $instance->business_location_id;
            } else {
                $scope = 'tenant';
            }
            $instances[$instance->module_id][$scope] = $instance;
        }

        return view('medregistry::instances.index', [
            'modules'     => $modules,
            'instances'   => $instances,
            'locations'   => $this->locations(),
            'departments' => $this->departments(),
        ]);
    }

    /**
     * Apply a lifecycle action to a module × scope (tenant / location /
     * department). Creates the instance row on demand; uninstall deletes the
     * row and keeps data (D4).
     */
    public function set(Request $request)
    {
        $this->guard('medreg.registry.manage');
        $this->guardSubscription();

        $data = $this->validate($request, [
            'module_id'     => 'required|integer',
            'location_id'   => 'nullable|integer',
            'department_id' => 'nullable|integer',
            'action'        => 'required|in:install,enable,disable,soft_lock,uninstall',
        ]);

        $businessId = $this->businessId();

        try {
            $module = MedregModule::findOrFail($data['module_id']);

            $locationId = ! empty($data['location_id']) ? (int) $data['location_id'] : null;
            $departmentId = ! empty($data['department_id']) ? (int) $data['department_id'] : null;

            // Scope must belong to this business.
            if ($locationId && ! array_key_exists($locationId, $this->locations())) {
                abort(403, 'Unauthorized action.');
            }
            if ($departmentId && ! array_key_exists($departmentId, $this->departments())) {
                abort(403, 'Unauthorized action.');
            }

            $instance = $this->lifecycle->instance($module->id, $businessId, $locationId, $departmentId);
            $this->lifecycle->apply($instance, $data['action']);

            $output = $this->ok(__('medregistry::lang.instance_updated'));
        } catch (\InvalidArgumentException $e) {
            $output = $this->fail($e->getMessage());
        } catch (\Exception $e) {
            \Log::emergency($e->getMessage());
            $output = $this->fail();
        }

        return redirect()->route('medreg.instances.index')->with('status', $output);
    }
}
