<?php

namespace App\Http\Controllers\Care;

use App\Http\Controllers\Care\Concerns\ScopesToAccount;
use App\Http\Controllers\Controller;
use App\Models\Branch;
use App\Models\Organization;
use App\Services\Billing\PlatformEmailClient;
use App\Services\Billing\PlatformSmsClient;
use App\Services\Care\AppointmentPatientNotifier;
use App\Services\Care\AuditLogger;
use App\Services\Care\CareFeatures;
use App\Services\Care\CarePermissions;
use App\Services\Care\CareQueueBridge;
use App\Services\Care\CareQueueContexts;
use App\Services\Care\CareQueueProvisioner;
use App\Services\Care\PlanService;
use App\Services\Care\Workflow\WorkflowTemplateInstaller;
use App\Services\Care\Workflow\WorkflowTemplateRegistry;
use App\Services\Messaging\MessagingCredentialsService;
use App\Support\OrganizationBranding;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class SettingsController extends Controller
{
    use ScopesToAccount;

    public function edit(
        Request $request,
        MessagingCredentialsService $credentials,
        PlatformEmailClient $platformEmail,
        PlatformSmsClient $platformSms,
    ): View {
        $this->authorizeAbility($request, 'settings.view');
        $organization = $this->organization($request);
        $member = $this->member($request);
        $permissions = app(CarePermissions::class);
        $canManage = $permissions->can($member, 'settings.manage');
        $credential = $credentials->forOrganization($organization);

        $branchCount = Branch::owned($this->ownerRef($request))
            ->where('organization_id', $organization->id)
            ->count();

        $plans = app(PlanService::class);

        // Suite platform keys (zero-config) OR optional product credentials.
        $suiteEmailReady = $platformEmail->isConfigured();
        $suiteSmsReady = $platformSms->isConfigured();

        $careFeatures = app(CareFeatures::class);

        return view('care.settings.edit', [
            'organization' => $organization,
            'canManage' => $canManage,
            'branchCount' => $branchCount,
            'canViewBranches' => $permissions->can($member, 'admin.branches.view'),
            'canViewTeam' => $permissions->can($member, 'admin.members.view'),
            'canViewDevices' => $permissions->can($member, 'devices.view'),
            'canViewDisplays' => $permissions->can($member, 'displays.view'),
            'canManageLabCatalog' => $permissions->can($member, 'lab.catalog.manage'),
            'hasBranchesFeature' => $plans->hasFeature($organization, 'branches'),
            'hasClinicalDevicesFeature' => $plans->hasFeature($organization, 'clinical_devices'),
            'canUseQueueIntegration' => $plans->canUseQueueIntegration($organization),
            'queueIntegrationEnabled' => (bool) data_get($organization->settings, 'queue_integration_enabled'),
            'canUseSpecialtyModules' => $plans->canUseSpecialtyModules($organization),
            'assessmentsEngineEnabled' => $careFeatures->enabled($organization, CareFeatures::ASSESSMENTS_ENGINE),
            'workflowEngineEnabled' => $careFeatures->enabled($organization, CareFeatures::WORKFLOW_ENGINE),
            'financialGatesEnabled' => $careFeatures->enabled($organization, CareFeatures::FINANCIAL_GATES),
            'hasBillingFeature' => $plans->hasFeature($organization, 'billing'),
            'messagingSmsReady' => $suiteSmsReady || $credential->hasValidSms(),
            'messagingEmailReady' => $suiteEmailReady || $credential->hasValidBird(),
            'suiteMessagingReady' => $suiteEmailReady || $suiteSmsReady,
            'messagingSettingsUrl' => function_exists('ladill_account_url')
                ? ladill_account_url('/account/settings/messaging')
                : (string) config('smtp.messaging_settings_url', 'https://account.ladill.com/account/settings/messaging'),
            'facilityTypes' => app(WorkflowTemplateRegistry::class)->categoryOptions(),
        ]);
    }

    public function update(Request $request): RedirectResponse
    {
        $this->authorizeAbility($request, 'settings.manage');
        $organization = $this->organization($request);
        $owner = $this->ownerRef($request);
        $plans = app(PlanService::class);

        $validated = $request->validate([
            'name' => ['required', 'string', 'max:255'],
            'timezone' => ['required', 'timezone'],
            'facility_type' => [
                'required',
                'string',
                'in:'.implode(',', array_keys(app(WorkflowTemplateRegistry::class)->categories())),
            ],
            'logo' => ['nullable', 'image', 'mimes:jpeg,png,jpg,webp,svg', 'max:2048'],
            'remove_logo' => ['nullable', 'boolean'],
            'queue_integration_enabled' => ['nullable', 'boolean'],
            'assessments_engine' => ['nullable', 'boolean'],
            'workflow_engine' => ['nullable', 'boolean'],
            'financial_gates' => ['nullable', 'boolean'],
            'notify_appointment_booked_sms' => ['nullable', 'boolean'],
            'notify_appointment_booked_email' => ['nullable', 'boolean'],
            'notify_video_scheduled_sms' => ['nullable', 'boolean'],
            'notify_video_scheduled_email' => ['nullable', 'boolean'],
        ]);

        $settings = $organization->settings ?? [];
        $settings['onboarded'] = true;
        $settings['facility_type'] = $validated['facility_type'];
        $settings['facility_category'] = $validated['facility_type'];
        $settings['modules'] = app(WorkflowTemplateRegistry::class)
            ->modulesForCategory($validated['facility_type']);

        $rollout = is_array($settings['rollout'] ?? null) ? $settings['rollout'] : [];
        // Explicit save so opt-out is stored (engine defaults ON when unset).
        $rollout[CareFeatures::ASSESSMENTS_ENGINE] = $request->boolean('assessments_engine');
        $rollout[CareFeatures::WORKFLOW_ENGINE] = $request->boolean('workflow_engine');
        $rollout[CareFeatures::FINANCIAL_GATES] = $request->boolean('financial_gates')
            && $rollout[CareFeatures::WORKFLOW_ENGINE]
            && $plans->hasFeature($organization, 'billing');
        $settings['rollout'] = $rollout;
        if ($rollout[CareFeatures::ASSESSMENTS_ENGINE]) {
            app(CareFeatures::class)->ensureAssessmentCatalog();
        }

        // Queue integration is Pro/Enterprise only — free plans cannot enable it.
        $wantsQueue = $request->boolean('queue_integration_enabled');
        if ($wantsQueue && ! $plans->canUseQueueIntegration($organization)) {
            return redirect()
                ->route('care.pro.index')
                ->with('upsell', 'In-app service queues are part of Care Pro. Upgrade to enable ticket numbers and Call next.');
        }
        if (! $plans->canUseQueueIntegration($organization)) {
            $wantsQueue = false;
        }
        $settings['queue_integration_enabled'] = $wantsQueue;
        $queueWasEnabled = (bool) data_get($organization->settings, 'queue_integration_enabled');
        $queueJustEnabled = $wantsQueue && ! $queueWasEnabled;

        $settings[AppointmentPatientNotifier::SETTING_BOOKED_SMS] = $request->boolean('notify_appointment_booked_sms');
        $settings[AppointmentPatientNotifier::SETTING_BOOKED_EMAIL] = $request->boolean('notify_appointment_booked_email');
        $settings[AppointmentPatientNotifier::SETTING_VIDEO_SMS] = $request->boolean('notify_video_scheduled_sms');
        $settings[AppointmentPatientNotifier::SETTING_VIDEO_EMAIL] = $request->boolean('notify_video_scheduled_email');

        $logoPath = $organization->logo_path;

        if ($request->boolean('remove_logo')) {
            OrganizationBranding::deleteStoredLogo($organization);
            $logoPath = null;
        }

        if ($request->hasFile('logo')) {
            $logoPath = OrganizationBranding::storeLogo($organization, $request->file('logo'));
        }

        $organization->update([
            'name' => $validated['name'],
            'timezone' => $validated['timezone'],
            'logo_path' => $logoPath,
            'settings' => $settings,
        ]);

        if ($rollout[CareFeatures::WORKFLOW_ENGINE] && ! $organization->facilityWorkflows()->where('is_active', true)->exists()) {
            $branch = Branch::owned($owner)
                ->where('organization_id', $organization->id)
                ->orderBy('id')
                ->first();
            if ($branch) {
                app(WorkflowTemplateInstaller::class)->install(
                    $organization->fresh(),
                    $branch,
                    (string) ($settings['workflow_template'] ?? config('care_workflows.default_template', 'legacy_clinic')),
                    ['category' => $settings['facility_category'] ?? $settings['facility_type'] ?? 'clinic'],
                );
            }
        }

        // Queue department sync + waiting-ticket backfill — run after the redirect.
        if ($wantsQueue) {
            $organizationId = (int) $organization->id;
            $backfillTickets = $queueJustEnabled;
            dispatch(function () use ($organizationId, $owner, $backfillTickets) {
                $organization = Organization::query()->find($organizationId);
                if (! $organization) {
                    return;
                }

                try {
                    app(CareQueueProvisioner::class)->provisionOrganization($organization);
                } catch (\Throwable) {
                    return;
                }

                if (! $backfillTickets) {
                    return;
                }

                try {
                    $bridge = app(CareQueueBridge::class);
                    $branches = Branch::owned($owner)
                        ->where('organization_id', $organization->id)
                        ->where('is_active', true)
                        ->pluck('id');
                    foreach ($branches as $branchId) {
                        try {
                            $bridge->syncMissingAppointmentTickets($organization, (int) $branchId, 50);
                        } catch (\Throwable) {
                            // Continue other branches.
                        }
                        foreach (array_keys(CareQueueContexts::departments()) as $context) {
                            if (in_array($context, [
                                CareQueueContexts::RECEPTION,
                                CareQueueContexts::CONSULTATION,
                                CareQueueContexts::TRIAGE,
                            ], true)) {
                                continue;
                            }
                            try {
                                $bridge->syncMissingTickets($organization, $context, (int) $branchId, 25);
                            } catch (\Throwable) {
                                // Continue other contexts/branches.
                            }
                        }
                    }
                } catch (\Throwable) {
                    // Best-effort; role pages will lazy-ensure on next use.
                }
            })->afterResponse();
        }

        AuditLogger::record($owner, 'organization.updated', $organization->id, $owner, Organization::class, $organization->id);

        return back()->with('success', 'Settings saved.');
    }
}
