<?php
declare(strict_types=1);

namespace App\Modules\Members\Services;

use App\Core\App;
use App\Core\Logger;

/**
 * Handles membership waiver (التنازل عن العضوية).
 * A waiver transfers the membership from one person to another with board approval.
 */
final class WaiverService
{
    private const WAIVER_FEE_PERCENTAGE = '30.00';

    /**
     * Calculate the waiver fee for a member based on their current membership value.
     * Fee = 30% of current membership value.
     *
     * @return array{membership_value: string, percentage: string, waiver_fee: string, annual_subscription_required: bool}
     */
    public static function calculateWaiverFee(int $memberId): array
    {
        $db = App::getInstance()->db();

        $member = $db->selectOne(
            "SELECT id, membership_value, qualification_id FROM members WHERE id = ? AND is_archived = 0",
            [$memberId]
        );

        if (!$member) {
            return [
                'membership_value'            => '0.00',
                'percentage'                   => self::WAIVER_FEE_PERCENTAGE,
                'waiver_fee'                   => '0.00',
                'annual_subscription_required' => true,
            ];
        }

        $membershipValue = $member['membership_value'] ?? '0.00';

        // If membership_value is zero or not set, try service_catalog based on qualification
        if (bccomp($membershipValue, '0', 2) <= 0 && !empty($member['qualification_id'])) {
            $qual = $db->selectOne(
                "SELECT code FROM qualifications WHERE id = ?",
                [(int) $member['qualification_id']]
            );

            if ($qual && !empty($qual['code'])) {
                $serviceCode = 'SVC_MEMBERSHIP_' . strtoupper($qual['code']);
                $catalogValue = \App\Modules\ServiceCatalog\Models\ServicePrice::getPrice($serviceCode);
                if ($catalogValue !== null) {
                    $membershipValue = $catalogValue;
                }
            }
        }

        $waiverFee = bcdiv(bcmul($membershipValue, self::WAIVER_FEE_PERCENTAGE, 4), '100', 2);

        return [
            'membership_value'            => $membershipValue,
            'percentage'                   => self::WAIVER_FEE_PERCENTAGE,
            'waiver_fee'                   => $waiverFee,
            'annual_subscription_required' => true,
        ];
    }

    /**
     * Get the list of conditions required for a membership waiver.
     *
     * @return array<int, string>
     */
    public static function getWaiverConditions(): array
    {
        return [
            'موافقة مجلس الإدارة مطلوبة',
            'لا يجوز أن يتجاوز عدد المرافقين للمتنازل إليه عدد مرافقي المتنازل',
            'يحتفظ بنفس رقم العضوية',
            'يجب سداد الاشتراك السنوي قبل التنازل',
            'يتم أرشفة بيانات العضو القديم (لا تُحذف)',
        ];
    }

    /**
     * Process a waiver request: validate source member, count dependants,
     * and create a transfer_request record.
     *
     * @param int   $sourceMemberId ID of the member transferring their membership
     * @param array $newMemberData  Data for the new member receiving the membership
     *
     * @return array{transfer_request_id: int, fee: string, conditions: array<int, string>}
     *
     * @throws \RuntimeException If source member is not active or not found
     */
    public static function processWaiver(int $sourceMemberId, array $newMemberData): array
    {
        $db = App::getInstance()->db();

        // Validate source member exists and is active
        $sourceMember = $db->selectOne(
            "SELECT id, status, membership_number, membership_value FROM members WHERE id = ? AND is_archived = 0",
            [$sourceMemberId]
        );

        if (!$sourceMember) {
            throw new \RuntimeException('العضو المصدر غير موجود');
        }

        if ($sourceMember['status'] !== 'active') {
            throw new \RuntimeException('العضو المصدر غير نشط - لا يمكن التنازل');
        }

        // Count dependants (spouses + children) on source
        $spouseCount = (int) ($db->selectOne(
            "SELECT COUNT(*) as cnt FROM spouses WHERE member_id = ? AND is_archived = 0",
            [$sourceMemberId]
        )['cnt'] ?? 0);

        $childCount = (int) ($db->selectOne(
            "SELECT COUNT(*) as cnt FROM children WHERE member_id = ? AND is_archived = 0",
            [$sourceMemberId]
        )['cnt'] ?? 0);

        $totalDependants = $spouseCount + $childCount;

        // Calculate fee
        $feeData = self::calculateWaiverFee($sourceMemberId);

        // Create transfer_request record
        $now = date('Y-m-d H:i:s');
        $db->insert('transfer_requests', [
            'source_member_id'        => $sourceMemberId,
            'transfer_type'           => 'waiver',
            'source_membership_number' => $sourceMember['membership_number'],
            'new_membership_value'    => $sourceMember['membership_value'] ?? '0.00',
            'fee_percentage'          => self::WAIVER_FEE_PERCENTAGE,
            'total_fee'               => $feeData['waiver_fee'],
            'status'                  => 'requested',
            'notes'                   => json_encode([
                'new_member_data'   => $newMemberData,
                'source_dependants' => $totalDependants,
                'spouse_count'      => $spouseCount,
                'child_count'       => $childCount,
            ], JSON_UNESCAPED_UNICODE),
            'created_at'              => $now,
            'updated_at'              => $now,
        ]);

        $transferRequestId = (int) $db->selectOne("SELECT LAST_INSERT_ID() as id")['id'];

        Logger::info('Waiver request created', [
            'transfer_request_id' => $transferRequestId,
            'source_member_id'    => $sourceMemberId,
            'fee'                 => $feeData['waiver_fee'],
            'dependants'          => $totalDependants,
        ]);

        return [
            'transfer_request_id' => $transferRequestId,
            'fee'                 => $feeData['waiver_fee'],
            'conditions'          => self::getWaiverConditions(),
        ];
    }
}
