<?php

namespace App\Http\Controllers\Care;

use App\Http\Controllers\Care\Concerns\ScopesToAccount;
use App\Http\Controllers\Controller;
use App\Services\Care\CarePermissions;
use App\Services\Care\CarePricingService;
use App\Services\Care\PlanService;
use App\Services\Care\SpecialtyModuleService;
use App\Services\Care\SpecialtyShellService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class SettingsModulesController extends Controller
{
    use ScopesToAccount;

    public function edit(Request $request, SpecialtyModuleService $modules, PlanService $plans): View
    {
        $this->authorizeAbility($request, 'settings.view');
        $organization = $this->organization($request);
        $member = $this->member($request);
        $canManage = app(CarePermissions::class)->can($member, 'settings.manage');

        if ($modules->canManage($organization)) {
            $modules->ensureDefaultModulesProvisioned($organization, $this->ownerRef($request));
            $organization->refresh();
        }

        return view('care.settings.modules', [
            'organization' => $organization,
            'canManage' => $canManage,
            'canUseSpecialtyModules' => $modules->canManage($organization),
            'catalog' => $modules->catalog(),
            'enabled' => collect($modules->enabledKeys($organization))->flip()->all(),
            'planKey' => $plans->planKey($organization),
        ]);
    }

    public function show(
        Request $request,
        string $module,
        SpecialtyModuleService $modules,
        SpecialtyShellService $shell,
        CarePricingService $pricing,
    ): View {
        $this->authorizeAbility($request, 'settings.view');
        $module = $modules->normalizeKey($module);
        $definition = $modules->definition($module);
        abort_unless($definition, 404);

        $organization = $this->organization($request);
        $member = $this->member($request);
        $canManage = app(CarePermissions::class)->can($member, 'settings.manage');
        $canUse = $modules->canManage($organization);

        if ($canUse && $modules->isEnabled($organization, $module)) {
            $shell->seedServices($organization, $module);
            $organization->refresh();
        }

        $services = $canUse
            ? $shell->provisionedServices($organization, $module)
            : $shell->catalogServices($module);

        return view('care.settings.module-show', [
            'organization' => $organization,
            'moduleKey' => $module,
            'definition' => $definition,
            'services' => $services,
            'serviceLines' => $modules->serviceLines($module),
            'enabledServiceLines' => $modules->enabledServiceLines($organization, $module),
            'enabled' => $modules->isEnabled($organization, $module),
            'canManage' => $canManage && $canUse,
            'canUseSpecialtyModules' => $canUse,
            'canOpenWorkspace' => $modules->memberCanAccess($organization, $member, $module),
            'currency' => strtoupper((string) config('care.billing.currency', 'GHS')),
        ]);
    }

    public function updateServiceLines(
        Request $request,
        string $module,
        SpecialtyModuleService $modules,
    ): RedirectResponse {
        $this->authorizeAbility($request, 'settings.manage');
        $organization = $this->organization($request);
        abort_unless($modules->definition($module), 404);
        abort_unless($modules->canManage($organization), 403);
        abort_unless($modules->serviceLines($module) !== [], 404);

        $lines = $modules->serviceLines($module);
        $rules = ['lines' => ['required', 'array']];
        foreach (array_keys($lines) as $key) {
            $rules["lines.{$key}"] = ['nullable', 'boolean'];
        }
        $validated = $request->validate($rules);

        $desired = [];
        foreach (array_keys($lines) as $key) {
            $desired[$key] = (bool) ($validated['lines'][$key] ?? false);
        }

        $modules->syncServiceLines($organization, $module, $desired);

        return redirect()
            ->route('care.settings.modules.show', $module)
            ->with('success', 'Service lines saved.');
    }

    public function updateServices(
        Request $request,
        string $module,
        SpecialtyModuleService $modules,
        SpecialtyShellService $shell,
        CarePricingService $pricing,
    ): RedirectResponse {
        $this->authorizeAbility($request, 'settings.manage');
        $organization = $this->organization($request);
        abort_unless($modules->definition($module), 404);
        abort_unless($modules->canManage($organization), 403);

        $validated = $request->validate([
            'services' => ['required', 'array'],
            'services.*.code' => ['required', 'string', 'max:64'],
            'services.*.amount' => ['required', 'numeric', 'min:0', 'max:999999'],
            'services.*.label' => ['nullable', 'string', 'max:255'],
        ]);

        $shell->seedServices($organization, $module);
        $pricing->updateSpecialtyServices($organization->fresh(), $module, $validated['services'], $shell);

        return redirect()
            ->route('care.settings.modules.show', $module)
            ->with('success', 'Service prices saved.');
    }

    public function update(Request $request, SpecialtyModuleService $modules): RedirectResponse
    {
        $this->authorizeAbility($request, 'settings.manage');
        $organization = $this->organization($request);

        if (! $modules->canManage($organization)) {
            return redirect()
                ->route('care.pro.index')
                ->with('upsell', 'Specialty modules are part of Care Pro. Upgrade to activate dentistry, eye care, and other specialty practice surfaces.');
        }

        $keys = array_keys($modules->catalog());
        $desired = [];
        foreach ($keys as $key) {
            $desired[$key] = $request->boolean("modules.{$key}");
            if ($modules->isDefaultOnPaidPlans($key)) {
                $desired[$key] = true;
            }
        }

        $modules->ensureDefaultModulesProvisioned($organization, $this->ownerRef($request));
        $result = $modules->sync($organization->fresh(), $this->ownerRef($request), $desired);

        if ($result['errors'] !== []) {
            return back()->with('error', 'Some modules could not be updated: '.implode(' ', $result['errors']));
        }

        $parts = [];
        if ($result['activated'] !== []) {
            $parts[] = 'Activated '.count($result['activated']).' module(s)';
        }
        if ($result['deactivated'] !== []) {
            $parts[] = 'Deactivated '.count($result['deactivated']).' module(s)';
        }

        return back()->with('success', $parts !== [] ? implode('. ', $parts).'.' : 'Modules saved.');
    }
}
