<?php
declare(strict_types=1);

namespace App\Modules\SportsActivity\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Core\Pagination;
use App\Modules\SportsActivity\Models\Subscription;
use App\Modules\SportsActivity\Models\Group;
use App\Modules\SportsActivity\Services\SubscriptionGeneratorService;
use App\Modules\SportsActivity\Services\SaPaymentService;

class SubscriptionController extends Controller
{
    /**
     * List subscriptions with filters and pagination.
     */
    public function index(Request $request): Response
    {
        $db = App::getInstance()->db();

        $filters = [
            'month'          => trim((string) $request->get('month', '')),
            'group_id'       => trim((string) $request->get('group_id', '')),
            'payment_status' => trim((string) $request->get('payment_status', '')),
        ];

        $page = max(1, (int) $request->get('page', 1));
        $perPage = 25;

        $where = [];
        $params = [];

        if ($filters['month'] !== '') {
            $periodStart = $filters['month'] . '-01';
            $where[] = "s.period_start = ?";
            $params[] = $periodStart;
        }

        if ($filters['group_id'] !== '') {
            $where[] = "s.group_id = ?";
            $params[] = (int) $filters['group_id'];
        }

        if ($filters['payment_status'] !== '') {
            $where[] = "s.payment_status = ?";
            $params[] = $filters['payment_status'];
        }

        $whereClause = !empty($where) ? 'WHERE ' . implode(' AND ', $where) : '';

        $total = (int) ($db->selectOne(
            "SELECT COUNT(*) as cnt FROM sa_subscriptions s {$whereClause}",
            $params
        )['cnt'] ?? 0);

        $pagination = Pagination::paginate($total, $perPage, $page);
        $offset = ($page - 1) * $perPage;

        $subscriptions = $db->select(
            "SELECT s.*, p.full_name_ar as player_name, g.name_ar as group_name
             FROM sa_subscriptions s
             LEFT JOIN sa_players p ON p.id = s.player_id
             LEFT JOIN sa_groups g ON g.id = s.group_id
             {$whereClause}
             ORDER BY s.period_start DESC, s.created_at DESC
             LIMIT {$perPage} OFFSET {$offset}",
            $params
        );

        $groups = Group::getActive();

        return $this->view('SportsActivity.Views.subscriptions.index', [
            'subscriptions'  => $subscriptions,
            'pagination'     => $pagination,
            'filters'        => $filters,
            'groups'         => $groups,
            'statusOptions'  => Subscription::getPaymentStatusOptions(),
        ]);
    }

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

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

        if ($yearMonth === '' || !preg_match('/^\d{4}-\d{2}$/', $yearMonth)) {
            return $this->redirect('/sa/subscriptions')->withError('يرجى تحديد شهر صالح');
        }

        $result = SubscriptionGeneratorService::generateForMonth($yearMonth);

        $message = sprintf(
            'تم توليد %d اشتراك جديد (تم تخطي %d موجود مسبقا) لشهر %s',
            $result['generated'],
            $result['skipped'],
            $yearMonth
        );

        return $this->redirect('/sa/subscriptions?month=' . $yearMonth)->withSuccess($message);
    }

    /**
     * Show subscription detail.
     */
    public function show(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();

        $subscription = $db->selectOne(
            "SELECT s.*, p.full_name_ar as player_name, p.registration_serial as player_code,
                    g.name_ar as group_name, g.code as group_code
             FROM sa_subscriptions s
             LEFT JOIN sa_players p ON p.id = s.player_id
             LEFT JOIN sa_groups g ON g.id = s.group_id
             WHERE s.id = ?",
            [(int) $id]
        );

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

        return $this->view('SportsActivity.Views.subscriptions.show', [
            'subscription'  => $subscription,
            'statusOptions' => Subscription::getPaymentStatusOptions(),
        ]);
    }

    /**
     * Process subscription payment via PaymentService (creates receipt + accounting entry).
     */
    public function pay(Request $request, string $id): Response
    {
        $paymentMethod = trim((string) $request->post('payment_method', 'cash'));
        if (!in_array($paymentMethod, ['cash', 'check', 'visa', 'bank_transfer'], true)) {
            return $this->redirect('/sa/subscriptions/' . $id)->withError('طريقة الدفع غير صالحة');
        }

        $extra = [
            'check_number'       => $request->post('check_number'),
            'check_bank'         => $request->post('check_bank'),
            'check_date'         => $request->post('check_date'),
            'visa_reference'     => $request->post('visa_reference'),
            'transfer_reference' => $request->post('transfer_reference'),
            'transfer_bank'      => $request->post('transfer_bank'),
        ];

        $result = SaPaymentService::paySubscription((int) $id, $paymentMethod, $extra);

        if (!$result['success']) {
            return $this->redirect('/sa/subscriptions/' . $id)->withError($result['error'] ?? 'فشل تسجيل الدفع');
        }

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

    /**
     * Void a subscription payment.
     */
    public function void(Request $request, string $id): Response
    {
        $result = SaPaymentService::voidSubscriptionPayment((int) $id);

        if (!$result['success']) {
            return $this->redirect('/sa/subscriptions/' . $id)->withError($result['error'] ?? 'فشل إلغاء الدفع');
        }

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

    /**
     * Mark subscription as exempt.
     */
    public function exempt(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();

        $subscription = $db->selectOne(
            "SELECT * FROM sa_subscriptions WHERE id = ?",
            [(int) $id]
        );

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

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

        $session = App::getInstance()->session();
        $employeeId = (int) ($session->get('employee_id') ?? 0);

        $db->update('sa_subscriptions', [
            'payment_status'   => 'exempt',
            'exemption_reason' => $reason,
            'exempted_by'      => $employeeId,
            'updated_at'       => date('Y-m-d H:i:s'),
        ], 'id = ?', [(int) $id]);

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