<?php
declare(strict_types=1);

namespace App\Modules\Temporary\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Core\EventBus;
use App\Modules\Temporary\Models\TemporaryMember;
use App\Modules\Temporary\Services\TemporaryFeeCalculator;
use App\Modules\Members\Services\NationalIdParser;
use App\Modules\Cashier\Services\PaymentRequestService;
use App\Shared\Services\PhotoUploadService;
use App\Modules\Members\Services\MembershipRulesService;


class TemporaryController extends Controller
{
    private static function isSuperAdmin(): bool
    {
        $employee = App::getInstance()->currentEmployee();
        if (!$employee) return false;
        $db = App::getInstance()->db();
        $row = $db->selectOne(
            "SELECT 1 FROM employee_roles er JOIN roles r ON r.id = er.role_id WHERE er.employee_id = ? AND r.role_code = 'super_admin' AND er.is_active = 1 LIMIT 1",
            [(int) $employee->id]
        );
        return $row !== null;
    }

    private static function isLocked(array $member): bool
    {
        return !empty($member['membership_number']);
    }

    public function index(Request $request): Response
    {
        $db = App::getInstance()->db();
        $filters = [
            'category'  => $request->get('category', ''),
            'status'    => $request->get('status', ''),
            'q'         => trim((string) $request->get('q', '')),
        ];

        $where = 't.is_archived = 0';
        $params = [];

        if (!empty($filters['category'])) {
            $where .= ' AND t.category = ?';
            $params[] = $filters['category'];
        }
        if (!empty($filters['status'])) {
            $where .= ' AND t.status = ?';
            $params[] = $filters['status'];
        }
        if (!empty($filters['q'])) {
            $where .= ' AND (t.full_name_ar LIKE ? OR t.national_id LIKE ? OR m.full_name_ar LIKE ?)';
            $s = '%' . $filters['q'] . '%';
            $params = array_merge($params, [$s, $s, $s]);
        }

        $rows = $db->select(
            "SELECT t.*, m.full_name_ar as member_name, m.membership_number
             FROM temporary_members t
             JOIN members m ON m.id = t.member_id
             WHERE {$where}
             ORDER BY t.created_at DESC
             LIMIT 100",
            $params
        );

        return $this->view('Temporary.Views.index', [
            'rows'       => $rows,
            'filters'    => $filters,
            'categories' => TemporaryMember::getCategories(),
        ]);
    }

    public function create(Request $request, string $memberId): Response
    {
        $db = App::getInstance()->db();
        $member = $db->selectOne("SELECT * FROM members WHERE id = ? AND is_archived = 0", [(int) $memberId]);
        if (!$member) {
            return $this->redirect('/members')->withError('العضو غير موجود');
        }

        if (!MembershipRulesService::allowsDependents($member['membership_type'] ?? 'working')) {
            return $this->redirect("/members/{$memberId}")->withError('نوع العضوية لا يسمح بإضافة تابعين');
        }

        if (self::isLocked($member) && !self::isSuperAdmin()) {
            return $this->redirect("/members/{$memberId}")->withError('لا يمكن إضافة أعضاء مؤقتين بعد تفعيل العضوية — تواصل مع المشرف العام');
        }

        return $this->view('Temporary.Views.create', [
            'member'     => $member,
            'categories' => TemporaryMember::getCategories(),
        ]);
    }

    public function store(Request $request, string $memberId): Response
    {
        $db = App::getInstance()->db();
        $member = $db->selectOne("SELECT * FROM members WHERE id = ? AND is_archived = 0", [(int) $memberId]);
        if (!$member) {
            return $this->redirect('/members')->withError('العضو غير موجود');
        }

        if (!MembershipRulesService::allowsDependents($member['membership_type'] ?? 'working')) {
            return $this->redirect("/members/{$memberId}")->withError('نوع العضوية لا يسمح بإضافة تابعين');
        }

        if (self::isLocked($member) && !self::isSuperAdmin()) {
            return $this->redirect("/members/{$memberId}")->withError('لا يمكن إضافة أعضاء مؤقتين بعد تفعيل العضوية — تواصل مع المشرف العام');
        }

        $data = $request->all();
        unset($data['_csrf_token']);

        $errors = [];
        if (empty(trim($data['full_name_ar'] ?? ''))) $errors[] = 'الاسم مطلوب';
        if (empty($data['category'] ?? '')) $errors[] = 'الفئة مطلوبة';
        if (empty($data['date_of_birth'] ?? '')) $errors[] = 'تاريخ الميلاد مطلوب';
        if (empty($data['gender'] ?? '')) $errors[] = 'النوع مطلوب';
        elseif (!in_array($data['gender'], ['male', 'female'], true)) $errors[] = 'النوع يجب أن يكون ذكر أو أنثى';

        // Non-Egyptian: require passport instead of NID
        $isNonEgyptian = !empty($data['is_non_egyptian']);
        if ($isNonEgyptian && empty(trim($data['passport_number'] ?? ''))) {
            $errors[] = 'رقم جواز السفر مطلوب لغير المصريين';
        }

        $nid = trim($data['national_id'] ?? '');
        if (!$isNonEgyptian && $nid !== '') {
            $parsed = NationalIdParser::parse($nid);
            if (!$parsed['is_valid']) {
                $errors = array_merge($errors, $parsed['errors']);
            } else {
                $data['date_of_birth'] = $parsed['dob'];
                $data['age_years'] = $parsed['age_years'];
                $data['age_months'] = $parsed['age_months'];
                $data['gender'] = $parsed['gender'];
            }

            if ($nid === ($member['national_id'] ?? '')) {
                $errors[] = 'لا يمكن إضافة العضو نفسه';
            }

            $dup = TemporaryMember::nidExistsElsewhere($nid);
            if ($dup) {
                $errors[] = 'الرقم القومي مسجل بالفعل: ' . ($dup['data']['full_name_ar'] ?? '');
            }
        }

        if (!empty($data['date_of_birth']) && empty($data['age_years'])) {
            $age = age_from_dob($data['date_of_birth']);
            $data['age_years'] = $age['years'];
            $data['age_months'] = $age['months'];
        }

        $category = $data['category'] ?? '';
        $catErrors = TemporaryFeeCalculator::validateCategory($category, $data, $member);
        $errors = array_merge($errors, $catErrors);

        $photoFile = $_FILES['photo'] ?? [];
        if (!PhotoUploadService::isUploaded($photoFile)) {
            $errors[] = 'الصورة الشخصية مطلوبة';
        } else {
            $photoValidation = PhotoUploadService::validate($photoFile);
            if (!$photoValidation['valid']) {
                $errors = array_merge($errors, $photoValidation['errors']);
            }
        }

        if (!empty($errors)) {
            $session = App::getInstance()->session();
            $session->flash('_alerts', array_map(fn($e) => ['type' => 'error', 'message' => $e], $errors));
            $session->flash('_old_input', $data);
            return $this->redirect("/members/{$memberId}/temporary/create");
        }

        $feeCalc = TemporaryFeeCalculator::calculate((int) $memberId, $data);

        $totalFee = $feeCalc['total_fee'] ?? $feeCalc['fee'] ?? '0.00';
        $hasFee = bccomp($totalFee, '0', 2) > 0;

        $breakdownJson = !empty($feeCalc['breakdown']) ? json_encode($feeCalc['breakdown'], JSON_UNESCAPED_UNICODE) : null;

        $temp = TemporaryMember::create([
            'member_id'                => (int) $memberId,
            'category'                 => $category,
            'full_name_ar'             => trim($data['full_name_ar']),
            'full_name_en'             => trim($data['full_name_en'] ?? ''),
            'national_id'              => $nid ?: null,
            'passport_number'          => $data['passport_number'] ?? null,
            'date_of_birth'            => $data['date_of_birth'],
            'age_years'                => (int) ($data['age_years'] ?? 0),
            'age_months'               => (int) ($data['age_months'] ?? 0),
            'gender'                   => $data['gender'],
            'nationality'              => $data['nationality'] ?? 'مصري',
            'relationship_to_member'   => $data['relationship_to_member'] ?? null,
            'has_championship'         => !empty($data['has_championship']) ? 1 : 0,
            'disability_documentation' => !empty($data['disability_documentation']) ? 1 : 0,
            'addition_fee'             => $totalFee,
            'fee_breakdown_json'       => $breakdownJson,
            'can_separate'             => TemporaryFeeCalculator::canSeparate($category) ? 1 : 0,
            'can_get_independent'      => TemporaryFeeCalculator::canGetIndependent($category) ? 1 : 0,
            'status'                   => $hasFee ? 'pending_payment' : 'active',
            'notes'                    => $data['notes'] ?? null,
        ]);

        $photoResult = PhotoUploadService::upload($photoFile, 'temporary', (int) $temp->id);
        if ($photoResult) {
            $temp->update(['photo_path' => $photoResult['path']]);
        }

        EventBus::dispatch('temporary.added', [
            'member_id'    => (int) $memberId,
            'temporary_id' => (int) $temp->id,
            'category'     => $category,
            'fee'          => $totalFee,
        ]);

        if ($hasFee && !empty($member['membership_number'])) {
            $breakdown = $feeCalc['breakdown'] ?? [];
            PaymentRequestService::createRequest([
                'member_id'           => (int) $memberId,
                'amount'              => $totalFee,
                'payment_type'        => 'addition_fee',
                'related_entity_type' => 'temporary_members',
                'related_entity_id'   => (int) $temp->id,
                'description_ar'      => 'رسوم إضافة عضو مؤقت — ' . trim($data['full_name_ar']),
                'notes'               => json_encode(['fee_breakdown' => $breakdown], JSON_UNESCAPED_UNICODE),
            ]);
            return $this->redirect("/members/{$memberId}")
                ->withSuccess('تم إضافة العضو المؤقت — الرسوم: ' . money($totalFee) . ' — تم إرسالها للخزينة تلقائياً');
        }

        if ($hasFee) {
            return $this->redirect("/members/{$memberId}")
                ->withSuccess('تم إضافة العضو المؤقت — الرسوم: ' . money($totalFee) . ' — سيتم تحصيلها ضمن الفاتورة المجمعة');
        }

        return $this->redirect("/members/{$memberId}")
            ->withSuccess('تم إضافة العضو المؤقت — معفى من الرسوم');
    }

    public function show(Request $request, string $memberId, string $id): Response
    {
        $temp = TemporaryMember::find((int) $id);
        if (!$temp || (int) $temp->member_id !== (int) $memberId) {
            return $this->redirect("/members/{$memberId}")->withError('العضو المؤقت غير موجود');
        }

        $db = App::getInstance()->db();
        $member = $db->selectOne("SELECT * FROM members WHERE id = ?", [(int) $memberId]);

        return $this->view('Temporary.Views.show', ['member' => $member, 'temp' => $temp]);
    }

    public function archive(Request $request, string $memberId, string $id): Response
    {
        $temp = TemporaryMember::find((int) $id);
        if (!$temp || (int) $temp->member_id !== (int) $memberId) {
            return $this->redirect("/members/{$memberId}")->withError('العضو المؤقت غير موجود');
        }

        $db = App::getInstance()->db();
        $member = $db->selectOne("SELECT * FROM members WHERE id = ?", [(int) $memberId]);
        if (self::isLocked($member) && !self::isSuperAdmin()) {
            return $this->redirect("/members/{$memberId}")->withError('لا يمكن إزالة التابعين بعد تفعيل العضوية — تواصل مع المشرف العام');
        }

        $reason = trim((string) $request->post('reason', ''));
        if ($reason === '') {
            return $this->redirect("/members/{$memberId}")->withError('يجب إدخال سبب الإزالة');
        }

        $employee = App::getInstance()->currentEmployee();

        $db->update('temporary_members', [
            'is_archived' => 1,
            'archived_at' => date('Y-m-d H:i:s'),
            'archived_by' => $employee ? (int) $employee->id : null,
            'status'      => 'inactive',
            'updated_at'  => date('Y-m-d H:i:s'),
        ], '`id` = ?', [(int) $id]);

        EventBus::dispatch('temporary.removed', [
            'member_id'    => (int) $memberId,
            'temporary_id' => (int) $id,
            'reason'       => $reason,
        ]);

        return $this->redirect("/members/{$memberId}")->withSuccess('تم إزالة العضو المؤقت');
    }
}