<?php

namespace App\Services\Care;

use App\Models\Branch;
use App\Models\Organization;
use Carbon\Carbon;

class PlanService
{
    public function planKey(Organization $organization): string
    {
        $settings = $organization->settings ?? [];
        $plan = (string) ($settings['plan'] ?? 'free');

        if (in_array($plan, ['pro', 'enterprise'], true) && ! empty($settings['plan_expires_at'])) {
            if (Carbon::parse($settings['plan_expires_at'])->isPast()) {
                return 'free';
            }
        }

        return array_key_exists($plan, config('care.plans', [])) ? $plan : 'free';
    }

    public function plan(Organization $organization): string
    {
        return $this->planKey($organization);
    }

    public function isPro(Organization $organization): bool
    {
        return $this->planKey($organization) === 'pro';
    }

    public function isEnterprise(Organization $organization): bool
    {
        return $this->planKey($organization) === 'enterprise';
    }

    public function hasPaidPlan(Organization $organization): bool
    {
        return in_array($this->planKey($organization), ['pro', 'enterprise'], true);
    }

    /** Lab, pharmacy, billing, and in-app service queues require Pro or Enterprise. */
    public function canUseProModules(Organization $organization): bool
    {
        return $this->hasPaidPlan($organization);
    }

    public function canUseQueueIntegration(Organization $organization): bool
    {
        return $this->hasPaidPlan($organization);
    }

    /** Specialty practice modules (dentistry, eye care, …) — Pro/Enterprise expansions. */
    public function canUseSpecialtyModules(Organization $organization): bool
    {
        return $this->hasFeature($organization, 'specialty_modules');
    }

    /** Own payment gateway (Paystack / Flutterwave / Hubtel) for encounter billing requires Pro or Enterprise. */
    public function canUsePaymentGateway(Organization $organization): bool
    {
        return $this->hasPaidPlan($organization) && $this->hasFeature($organization, 'billing');
    }

    public function hasFeature(Organization $organization, string $feature): bool
    {
        $features = config('care.plans.'.$this->planKey($organization).'.features', []);

        return in_array($feature, $features, true);
    }

    public function activeBranchCount(Organization $organization): int
    {
        return Branch::query()
            ->where('organization_id', $organization->id)
            ->where('is_active', true)
            ->count();
    }

    public function maxBranches(Organization $organization): ?int
    {
        $plan = config('care.plans.'.$this->planKey($organization));
        $max = $plan['max_branches'] ?? null;

        return $max === null ? null : (int) $max;
    }

    public function canAddBranch(Organization $organization, int $currentCount): bool
    {
        $max = $this->maxBranches($organization);

        return $max === null || $currentCount < $max;
    }

    public function branchLimitMessage(Organization $organization): string
    {
        $max = $this->maxBranches($organization);
        $key = $this->planKey($organization);

        if ($key === 'free') {
            return 'Your Free plan allows 1 branch. Upgrade to Care Pro for unlimited branches (billed per branch).';
        }

        if ($key === 'pro' && $max !== null) {
            return "Your Pro plan allows up to {$max} branches (billed per branch).";
        }

        return 'Branch limit reached for your current plan.';
    }

    public function proPricePerBranchMinor(): int
    {
        return (int) config(
            'care.plans.pro.price_minor_per_branch',
            config('care.plans.pro.price_minor', 249000),
        );
    }

    /** @deprecated Prefer proPricePerBranchMinor() — Pro is billed per branch. */
    public function proPriceMinor(): int
    {
        return $this->proPricePerBranchMinor();
    }

    public function enterprisePricePerBranchMinor(): int
    {
        return (int) config(
            'care.plans.enterprise.price_minor_per_branch',
            config('care.plans.enterprise.price_minor', 499000),
        );
    }

    /** Total monthly amount for Pro = active branches × per-branch rate (min 1). */
    public function proPriceTotalMinor(Organization $organization): int
    {
        return $this->priceForBranches('pro', $this->activeBranchCount($organization));
    }

    /** Total monthly amount for Enterprise = active branches × per-branch rate (min 1). */
    public function enterprisePriceMinor(Organization $organization): int
    {
        return $this->priceForBranches('enterprise', $this->activeBranchCount($organization));
    }

    public function monthlyPriceMinor(Organization $organization, string $plan): int
    {
        return $this->priceForBranches($plan, $this->activeBranchCount($organization));
    }

    /** Fixed branch count × per-branch rate (for checkout when the user picks branch seats). */
    public function priceForBranches(string $plan, int $branches): int
    {
        $branches = max(1, $branches);
        $rate = $plan === 'enterprise'
            ? $this->enterprisePricePerBranchMinor()
            : $this->proPricePerBranchMinor();

        return $branches * $rate;
    }

    public function resolveCheckoutBranches(Organization $organization, int $requested): int
    {
        $branches = max(1, $requested);
        // Don't under-bill vs sites already configured in the account.
        $active = max(1, $this->activeBranchCount($organization));

        return max($branches, $active);
    }

    public function canSubscribeEnterprise(Organization $organization): bool
    {
        // Enterprise is a feature tier (not branch-gated). min_branches defaults to 1.
        return $this->activeBranchCount($organization) >= (int) config('care.enterprise.min_branches', 1);
    }
}
