<?php
declare(strict_types=1);

namespace App\Modules\Members\Services;

use App\Core\App;
use App\Modules\Rules\Services\RuleEngine;
use App\Modules\ServiceCatalog\Models\ServicePrice;

/**
 * Determines whether a dependant addition needs a form fee (570 EGP).
 *
 * Business rule:
 * - During initial membership creation (member status = potential / under_review),
 *   all additions are on the same initial form — no additional form fee.
 * - After activation, any modification needs a "form addition" (570 EGP).
 * - Multiple additions within the SAME form session share one form fee.
 *   A form session is "open" if a form fee was paid (or is pending) within
 *   the configured validity window (default 30 days).
 */
final class FormFeeService
{
    /**
     * Check if the member is still on the initial membership form.
     */
    public static function isOnInitialForm(array $member): bool
    {
        return in_array($member['status'] ?? '', ['potential', 'under_review'], true);
    }

    /**
     * Check if there's an active (open) addition form session for this member.
     *
     * An addition form is "open" if any addition_fee payment request was created
     * within the configured validity window. The form fee is embedded in the first
     * addition's total — subsequent additions within the same window share it.
     */
    public static function hasOpenAdditionForm(int $memberId): bool
    {
        $db = App::getInstance()->db();
        $validityDays = (int) (RuleEngine::getValue('ADDITION_FORM_VALIDITY_DAYS', 'value') ?? 30);
        $cutoff = date('Y-m-d H:i:s', strtotime("-{$validityDays} days"));

        $existing = $db->selectOne(
            "SELECT id FROM payment_requests
             WHERE member_id = ? AND payment_type = 'addition_fee' AND is_voided = 0
             AND status IN ('pending', 'processing', 'completed')
             AND created_at >= ?
             LIMIT 1",
            [$memberId, $cutoff]
        );
        if ($existing) return true;

        $paid = $db->selectOne(
            "SELECT id FROM payments
             WHERE member_id = ? AND payment_type = 'addition_fee' AND is_voided = 0
             AND created_at >= ?
             LIMIT 1",
            [$memberId, $cutoff]
        );

        return $paid !== null;
    }

    /**
     * Get the form fee that should be charged for an addition.
     * Returns '0.00' if on initial form or if an addition form is already open.
     */
    public static function getFormFee(int $memberId, array $member): string
    {
        if (self::isOnInitialForm($member)) {
            return '0.00';
        }

        if (self::hasOpenAdditionForm($memberId)) {
            return '0.00';
        }

        $feeData = RuleEngine::get('FORM_ADDITION_FEE');
        return $feeData['amount'] ?? ServicePrice::getPrice('SVC_ADDITION_FORM', '570.00');
    }

    /**
     * Check if this is a "free" spouse slot on the initial form.
     * Rule: first N spouses are free (default N=1) during initial creation.
     */
    public static function isSpouseFreeOnInitialForm(int $memberId, int $spouseOrder, array $member): bool
    {
        if (!self::isOnInitialForm($member)) {
            return false;
        }
        $maxFree = (int) (RuleEngine::getValue('INITIAL_FREE_SPOUSES_COUNT', 'value') ?? 1);
        return $spouseOrder <= $maxFree;
    }

    /**
     * Check if this child is in a "free" slot on the initial form.
     * Rule: first N children under max age are free (default N=2, age<18).
     * Uses INITIAL_FREE_CHILDREN_COUNT for the initial form specifically,
     * and CHILD_INCLUDED_MAX_COUNT / CHILD_INCLUDED_MAX_AGE for general classification.
     */
    public static function isChildFreeOnInitialForm(int $memberId, int $childOrder, int $childAge, array $member): bool
    {
        if (!self::isOnInitialForm($member)) {
            return false;
        }
        $maxFreeCount = (int) (RuleEngine::getValue('INITIAL_FREE_CHILDREN_COUNT', 'value') ?? 2);
        $maxFreeAge = (int) (RuleEngine::getValue('CHILD_INCLUDED_MAX_AGE', 'value') ?? 18);
        return $childOrder <= $maxFreeCount && $childAge < $maxFreeAge;
    }
}
