<?php
declare(strict_types=1);

namespace App\Modules\ActivitySubscriptions\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Modules\ActivitySubscriptions\Models\ActivitySubscription;
use App\Modules\ActivitySubscriptions\Models\ActivityPricing;
use App\Modules\ActivitySubscriptions\Services\ActivitySubscriptionService;
use App\Modules\ActivitySubscriptions\Services\ActivityPricingService;
use App\Modules\Payments\Services\PaymentService;
use App\Modules\Sales\Services\InventoryPaymentService;
use App\Modules\Disciplines\Models\SportDiscipline;
use App\Modules\Academies\Models\Academy;

class ActivitySubscriptionController extends Controller
{
    /**
     * List activity subscriptions with status tabs, month filter, search, and pagination.
     */
    public function index(Request $request): Response
    {
        $filters = [
            'q'                  => trim((string) $request->get('q', '')),
            'status'             => trim((string) $request->get('status', '')),
            'subscription_month' => trim((string) $request->get('subscription_month', '')),
            'discipline_id'      => trim((string) $request->get('discipline_id', '')),
            'player_type'        => trim((string) $request->get('player_type', '')),
        ];

        $page = max(1, (int) $request->get('page', 1));
        $result = ActivitySubscription::search($filters, 25, $page);

        // Collection summary for selected month (or current month)
        $summaryMonth = $filters['subscription_month'] ?: date('Y-m');
        $db = App::getInstance()->db();
        $collectionSummary = $db->selectOne("
            SELECT
                COUNT(*) AS total,
                SUM(CASE WHEN status = 'paid' THEN 1 ELSE 0 END) AS paid,
                SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) AS pending,
                SUM(CASE WHEN status = 'overdue' THEN 1 ELSE 0 END) AS overdue,
                SUM(CASE WHEN status = 'exempt' THEN 1 ELSE 0 END) AS exempt,
                SUM(CASE WHEN status = 'revoked' THEN 1 ELSE 0 END) AS revoked,
                COALESCE(SUM(total_amount), 0) AS total_expected,
                COALESCE(SUM(CASE WHEN status = 'paid' THEN total_amount ELSE 0 END), 0) AS total_collected,
                COALESCE(SUM(CASE WHEN status IN ('pending', 'overdue') THEN total_amount ELSE 0 END), 0) AS total_outstanding
            FROM activity_subscriptions
            WHERE subscription_month = ?
        ", [$summaryMonth]) ?: [];

        return $this->view('ActivitySubscriptions.Views.index', [
            'subscriptions'     => $result['data'],
            'pagination'        => $result['pagination'],
            'filters'           => $filters,
            'statuses'          => ActivitySubscription::getStatuses(),
            'disciplines'       => SportDiscipline::allActive(),
            'collectionSummary' => $collectionSummary,
            'summaryMonth'      => $summaryMonth,
        ]);
    }

    /**
     * Show subscription detail with payment/exemption actions.
     */
    public function show(Request $request, string $id): Response
    {
        $sub = ActivitySubscription::find((int) $id);
        if (!$sub) {
            return $this->redirect('/activity-subscriptions')->withError('الاشتراك غير موجود');
        }

        $db = App::getInstance()->db();
        $player = $db->selectOne("SELECT * FROM `players` WHERE `id` = ?", [(int) $sub->player_id]);
        $discipline = $sub->discipline_id ? SportDiscipline::find((int) $sub->discipline_id) : null;

        return $this->view('ActivitySubscriptions.Views.show', [
            'subscription' => $sub,
            'player'       => $player,
            'discipline'   => $discipline,
            'statuses'     => ActivitySubscription::getStatuses(),
        ]);
    }

    /**
     * Process payment for a subscription.
     */
    public function pay(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $sub = $db->selectOne(
            "SELECT s.*, p.full_name_ar as player_name
             FROM `activity_subscriptions` s
             JOIN `players` p ON p.id = s.player_id
             WHERE s.`id` = ?",
            [(int) $id]
        );

        if (!$sub) {
            return $this->redirect('/activity-subscriptions')->withError('الاشتراك غير موجود');
        }

        if ($sub['status'] === 'paid') {
            return $this->redirect('/activity-subscriptions')->withError('الاشتراك مدفوع بالفعل');
        }

        $amount = (string) ($sub['total_amount'] ?? '0.00');
        $paymentMethod = $request->post('payment_method', 'cash');
        $description = 'اشتراك نشاط ' . ($sub['subscription_month'] ?? '') . ' — ' . ($sub['player_name'] ?? '');

        // Look up player's member_id — member players go through PaymentService,
        // non-member players go through InventoryPaymentService (guest path)
        $player = $db->selectOne("SELECT member_id FROM players WHERE id = ?", [(int) $sub['player_id']]);
        $playerMemberId = $player ? (int) ($player['member_id'] ?? 0) : 0;

        if ($playerMemberId > 0) {
            $result = PaymentService::processPayment([
                'member_id'           => $playerMemberId,
                'amount'              => $amount,
                'payment_type'        => 'activity_subscription',
                'payment_method'      => $paymentMethod,
                'related_entity_type' => 'activity_subscriptions',
                'related_entity_id'   => (int) $id,
                'description'         => $description,
            ]);
        } else {
            $result = InventoryPaymentService::processGuestPayment([
                'amount'              => $amount,
                'payment_type'        => 'activity_subscription',
                'payment_method'      => $paymentMethod,
                'guest_name'          => $sub['player_name'] ?? 'لاعب',
                'related_entity_type' => 'activity_subscriptions',
                'related_entity_id'   => (int) $id,
                'description'         => $description,
            ]);
        }
        if (!$result['success']) {
            return $this->redirect('/activity-subscriptions/' . $id)->withError($result['error']);
        }

        ActivitySubscriptionService::paySubscription((int) $id, (int) $result['payment_id']);

        return $this->redirect('/activity-subscriptions/' . $id)
            ->withSuccess('تم تسجيل الدفع بنجاح — إيصال: ' . $result['receipt_number']);
    }

    /**
     * Grant an exemption on a subscription.
     */
    public function exempt(Request $request, string $id): Response
    {
        $sub = ActivitySubscription::find((int) $id);
        if (!$sub) {
            return $this->redirect('/activity-subscriptions')->withError('الاشتراك غير موجود');
        }

        $reason = trim((string) $request->post('exemption_reason', ''));
        if ($reason === '') {
            return $this->redirect('/activity-subscriptions/' . $id)->withError('يجب إدخال سبب الإعفاء');
        }

        $employee = App::getInstance()->currentEmployee();
        $exemptedBy = $employee ? (int) ($employee->id ?? ($employee['id'] ?? 0)) : 0;

        ActivitySubscriptionService::grantExemption((int) $id, $exemptedBy, $reason);

        return $this->redirect('/activity-subscriptions/' . $id)->withSuccess('تم إعفاء الاشتراك بنجاح');
    }

    /**
     * Generate monthly subscriptions for a specified month.
     */
    public function generate(Request $request): Response
    {
        $month = trim((string) $request->post('month', ''));

        if ($month !== '' && !preg_match('/^\d{4}-\d{2}$/', $month)) {
            $parsed = date_create_from_format('F Y', $month) ?: date_create_from_format('M Y', $month);
            if ($parsed) {
                $month = $parsed->format('Y-m');
            }
        }

        if ($month === '' || !preg_match('/^\d{4}-\d{2}$/', $month)) {
            return $this->redirect('/activity-subscriptions')->withError('يجب تحديد شهر صحيح بصيغة YYYY-MM');
        }

        $count = ActivitySubscriptionService::generateMonthlySubscriptions($month);

        return $this->redirect('/activity-subscriptions?subscription_month=' . urlencode($month))
            ->withSuccess('تم توليد ' . $count . ' اشتراك لشهر ' . $month);
    }

    /**
     * List all pricing records with edit capability.
     */
    public function pricing(Request $request): Response
    {
        $filters = [
            'pricing_type' => trim((string) $request->get('pricing_type', '')),
            'is_active'    => $request->get('is_active', ''),
        ];

        $page = max(1, (int) $request->get('page', 1));
        $result = ActivityPricing::search($filters, 25, $page);

        // Build name lookup maps so the view shows real names instead of "#1"
        $academies   = Academy::allActive();
        $disciplines = SportDiscipline::allActive();

        $academyNames = [];
        foreach ($academies as $a) {
            $id = (int) ($a['id'] ?? $a->id ?? 0);
            $academyNames[$id] = $a['name_ar'] ?? $a->name_ar ?? '';
        }
        $disciplineNames = [];
        foreach ($disciplines as $d) {
            $id = (int) ($d['id'] ?? $d->id ?? 0);
            $disciplineNames[$id] = $d['name_ar'] ?? $d->name_ar ?? '';
        }

        return $this->view('ActivitySubscriptions.Views.pricing', [
            'pricings'        => $result['data'],
            'pagination'      => $result['pagination'],
            'filters'         => $filters,
            'pricingTypes'    => ActivityPricing::getPricingTypes(),
            'academyNames'    => $academyNames,
            'disciplineNames' => $disciplineNames,
            'academies'       => $academies,
            'disciplines'     => $disciplines,
        ]);
    }

    /**
     * Update pricing rates.
     */
    public function updatePricing(Request $request): Response
    {
        $pricingType  = trim((string) $request->post('pricing_type', ''));
        $referenceId  = (int) $request->post('reference_id', 0);

        if (!array_key_exists($pricingType, ActivityPricing::getPricingTypes())) {
            return $this->redirect('/activity-subscriptions/pricing')->withError('نوع التسعير غير صالح');
        }
        if ($referenceId <= 0) {
            return $this->redirect('/activity-subscriptions/pricing')->withError('المرجع غير صالح');
        }

        $rates = [
            'member_rate'       => trim((string) $request->post('member_rate', '0')),
            'nonmember_rate'    => trim((string) $request->post('nonmember_rate', '0')),
            'member_rate_pm'    => trim((string) $request->post('member_rate_pm', '0')),
            'nonmember_rate_pm' => trim((string) $request->post('nonmember_rate_pm', '0')),
            'effective_from'    => trim((string) $request->post('effective_from', date('Y-m-d'))),
            'effective_to'      => $request->post('effective_to') ?: null,
        ];

        ActivityPricingService::setRate($pricingType, $referenceId, $rates);

        return $this->redirect('/activity-subscriptions/pricing')->withSuccess('تم تحديث التسعير بنجاح');
    }
}
