<?php
declare(strict_types=1);

namespace App\Modules\Transfers\Services;

use App\Core\App;
use App\Core\EventBus;
use App\Core\Logger;
use App\Modules\Archive\Services\ArchiveService;
use App\Modules\Members\Services\MemberNumberGenerator;
use App\Modules\Transfers\Models\TransferRequest;

final class TransferProcessor
{
    /**
     * Execute a complete transfer/separation.
     * 1. Take archive snapshot
     * 2. Create new member record
     * 3. Assign new membership number
     * 4. Record number chain
     * 5. Update source records
     * 6. Mark transfer complete
     */
    public static function execute(int $transferRequestId): array
    {
        $db = App::getInstance()->db();
        $employee = App::getInstance()->currentEmployee();

        $request = $db->selectOne("SELECT * FROM transfer_requests WHERE id = ?", [$transferRequestId]);
        if (!$request) {
            return ['success' => false, 'error' => 'طلب التحويل غير موجود'];
        }

        if ($request['status'] !== 'approved' && $request['status'] !== 'fee_paid') {
            return ['success' => false, 'error' => 'طلب التحويل غير مُعتمد أو لم يتم السداد'];
        }

        $sourceMember = $db->selectOne("SELECT * FROM members WHERE id = ?", [(int) $request['source_member_id']]);
        if (!$sourceMember) {
            return ['success' => false, 'error' => 'العضو المصدر غير موجود'];
        }

        $db->beginTransaction();
        try {
            // 1. Take archive snapshot of source member
            $snapshotId = ArchiveService::takeSnapshot(
                'members',
                (int) $sourceMember['id'],
                $request['transfer_type'],
                'لقطة أرشيفية قبل التحويل/الفصل — طلب #' . $transferRequestId,
                null,
                $sourceMember['membership_number']
            );

            // 2. Determine the subject of transfer
            $subjectName = $sourceMember['full_name_ar'];
            $subjectData = $sourceMember;

            if ($request['child_id']) {
                $child = $db->selectOne("SELECT * FROM children WHERE id = ?", [(int) $request['child_id']]);
                if ($child) {
                    $subjectName = $child['full_name_ar'];
                    $subjectData = $child;
                }
            } elseif ($request['spouse_id']) {
                $spouse = $db->selectOne("SELECT * FROM spouses WHERE id = ?", [(int) $request['spouse_id']]);
                if ($spouse) {
                    $subjectName = $spouse['full_name_ar'];
                    $subjectData = $spouse;
                }
            }

            // 3. Create new member record
            $newMemberData = [
                'full_name_ar'     => $subjectData['full_name_ar'] ?? $subjectName,
                'full_name_en'     => $subjectData['full_name_en'] ?? null,
                'national_id'      => $subjectData['national_id'] ?? null,
                'passport_number'  => $subjectData['passport_number'] ?? null,
                'id_type'          => $subjectData['id_type'] ?? 'national_id',
                'date_of_birth'    => $subjectData['date_of_birth'],
                'age_years'        => $subjectData['age_years'] ?? null,
                'age_months'       => $subjectData['age_months'] ?? null,
                'gender'           => $subjectData['gender'],
                'nationality'      => $subjectData['nationality'] ?? 'مصري',
                'branch_id'        => (int) $sourceMember['branch_id'],
                'membership_type'  => 'working',
                'member_category'  => 'working_member',
                'status'           => 'active',
                'qualification_id' => $subjectData['qualification_id'] ?? $sourceMember['qualification_id'],
                'phone_mobile'     => $subjectData['mobile'] ?? $subjectData['phone_mobile'] ?? $sourceMember['phone_mobile'],
                'membership_value' => $request['new_membership_value'],
                'created_at'       => date('Y-m-d H:i:s'),
                'updated_at'       => date('Y-m-d H:i:s'),
                'created_by'       => $employee ? (int) $employee->id : null,
            ];

            // Transfer the SAME membership number to the new member
            $sameNumber = $sourceMember['membership_number'];
            $newMemberData['membership_number'] = $sameNumber;

            $newMemberId = $db->insert('members', $newMemberData);

            // 4. Clear membership number from source and archive
            $db->update('members', [
                'membership_number' => null,
                'status'            => 'transferred',
                'is_archived'       => 1,
                'archived_at'       => date('Y-m-d H:i:s'),
                'updated_at'        => date('Y-m-d H:i:s'),
            ], '`id` = ?', [(int) $sourceMember['id']]);

            $newNumber = $sameNumber;

            // 5. Record number chain
            ArchiveService::recordNumberTransfer(
                $newNumber,
                $request['transfer_type'],
                'members',
                $newMemberId,
                null
            );

            // 6. Update source dependents — mark as separated if it's a child/spouse separation
            if ($request['child_id']) {
                $db->update('children', [
                    'status'        => 'separated',
                    'classification'=> 'separated',
                    'updated_at'    => date('Y-m-d H:i:s'),
                ], '`id` = ?', [(int) $request['child_id']]);
            } elseif ($request['spouse_id']) {
                $db->update('spouses', [
                    'status'     => 'separated',
                    'updated_at' => date('Y-m-d H:i:s'),
                ], '`id` = ?', [(int) $request['spouse_id']]);
            }

            // Transfer all dependents from source to new member (full membership transfer)
            if (!$request['child_id'] && !$request['spouse_id']) {
                $db->query("UPDATE spouses SET member_id = ?, updated_at = NOW() WHERE member_id = ? AND is_archived = 0", [$newMemberId, (int) $sourceMember['id']]);
                $db->query("UPDATE children SET member_id = ?, updated_at = NOW() WHERE member_id = ? AND is_archived = 0", [$newMemberId, (int) $sourceMember['id']]);
                $db->query("UPDATE temporary_members SET member_id = ?, updated_at = NOW() WHERE member_id = ? AND is_archived = 0", [$newMemberId, (int) $sourceMember['id']]);
            }

            // 7. Mark transfer request complete
            $db->update('transfer_requests', [
                'target_member_id'     => $newMemberId,
                'new_membership_number'=> $newNumber,
                'archive_snapshot_id'  => $snapshotId,
                'completed_at'         => date('Y-m-d H:i:s'),
                'status'               => 'completed',
                'updated_at'           => date('Y-m-d H:i:s'),
                'updated_by'           => $employee ? (int) $employee->id : null,
            ], '`id` = ?', [$transferRequestId]);

            $db->commit();

            EventBus::dispatch('transfer.completed', [
                'transfer_id'      => $transferRequestId,
                'source_member_id' => (int) $request['source_member_id'],
                'target_member_id' => $newMemberId,
                'new_number'       => $newNumber,
                'transfer_type'    => $request['transfer_type'],
                'fee_amount'       => $request['total_fee'] ?? $request['separation_fee'] ?? '0.00',
                'old_number'       => $sourceMember['membership_number'] ?? null,
            ]);

            Logger::info("Transfer completed", [
                'transfer_id' => $transferRequestId,
                'new_member'  => $newMemberId,
                'new_number'  => $newNumber,
            ]);

            return [
                'success'          => true,
                'new_member_id'    => $newMemberId,
                'new_number'       => $newNumber,
                'snapshot_id'      => $snapshotId,
                'transfer_id'      => $transferRequestId,
            ];

        } catch (\Throwable $e) {
            $db->rollBack();
            Logger::error("Transfer failed: " . $e->getMessage(), ['transfer_id' => $transferRequestId]);
            return ['success' => false, 'error' => 'فشل في إتمام التحويل: ' . $e->getMessage()];
        }
    }
}