<?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\Models\Discipline;
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 = [
            'q'              => trim((string) $request->get('q', '')),
            'month'          => trim((string) $request->get('month', '')),
            'discipline_id'  => trim((string) $request->get('discipline_id', '')),
            '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 = [];
        $joins = 'LEFT JOIN sa_players p ON p.id = s.player_id LEFT JOIN sa_groups g ON g.id = s.group_id';

        if ($filters['q'] !== '') {
            $where[] = '(p.full_name_ar LIKE ? OR p.national_id LIKE ?)';
            $params[] = '%' . $filters['q'] . '%';
            $params[] = '%' . $filters['q'] . '%';
        }

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

        if ($filters['discipline_id'] !== '') {
            $joins .= ' LEFT JOIN sa_programs pr ON pr.id = g.program_id';
            $where[] = 'pr.discipline_id = ?';
            $params[] = (int) $filters['discipline_id'];
        }

        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 {$joins} {$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
             {$joins}
             {$whereClause}
             ORDER BY s.period_start DESC, s.created_at DESC
             LIMIT {$perPage} OFFSET {$offset}",
            $params
        );

        $disciplines = Discipline::getActive();
        $groups = Group::getActive();

        $statsMonth = $filters['month'] !== '' ? $filters['month'] . '-01' : date('Y-m-01');
        $stats = $db->selectOne(
            "SELECT
                COUNT(*) as total,
                SUM(CASE WHEN payment_status = 'paid' THEN 1 ELSE 0 END) as paid,
                SUM(CASE WHEN payment_status = 'unpaid' THEN 1 ELSE 0 END) as unpaid,
                SUM(CASE WHEN payment_status = 'overdue' THEN 1 ELSE 0 END) as overdue,
                SUM(CASE WHEN payment_status = 'exempt' THEN 1 ELSE 0 END) as exempt,
                SUM(CASE WHEN payment_status = 'paid' THEN final_amount ELSE 0 END) as collected,
                SUM(CASE WHEN payment_status IN ('unpaid','overdue') THEN final_amount ELSE 0 END) as pending_amount
             FROM sa_subscriptions WHERE period_start = ?",
            [$statsMonth]
        );

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

    /**
     * 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('تم تسجيل الإعفاء بنجاح');
    }
}
