<?php
declare(strict_types=1);

namespace App\Modules\Subscriptions\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Core\EventBus;
use App\Modules\Subscriptions\Models\Subscription;
use App\Modules\Subscriptions\Services\SubscriptionGenerator;
use App\Modules\Subscriptions\Services\SubscriptionCalculator;
use App\Modules\Payments\Services\PaymentService;

class SubscriptionController extends Controller
{
    public function index(Request $request): Response
    {
        $filters = [
            'search'         => trim((string) $request->get('q', '')),
            'financial_year' => $request->get('financial_year', ''),
            'status'         => $request->get('status', ''),
            'person_type'    => $request->get('person_type', ''),
        ];
        $page = max(1, (int) $request->get('page', 1));
        $result = Subscription::search($filters, 30, $page);

        $currentYear = self::currentFinancialYear();

        return $this->view('Subscriptions.Views.index', [
            'rows'        => $result['data'],
            'pagination'  => $result['pagination'],
            'filters'     => $filters,
            'currentYear' => $currentYear,
        ]);
    }

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

        $subscriptions = Subscription::getForMember((int) $memberId);
        $unpaidYears = Subscription::getUnpaidYears((int) $memberId);
        $lateFine = SubscriptionCalculator::calculateLateFine((int) $memberId, self::currentFinancialYear());

        return $this->view('Subscriptions.Views.member-subscriptions', [
            'member'        => $member,
            'subscriptions' => $subscriptions,
            'unpaidYears'   => $unpaidYears,
            'lateFine'      => $lateFine,
        ]);
    }

    public function pay(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $sub = $db->selectOne("SELECT s.*, m.full_name_ar as member_name FROM subscriptions s JOIN members m ON m.id = s.member_id WHERE s.id = ?", [(int) $id]);
        if (!$sub) return $this->redirect('/subscriptions')->withError('الاشتراك غير موجود');
        if ($sub['status'] === 'paid') return $this->redirect('/subscriptions')->withError('الاشتراك مدفوع بالفعل');

        $amount = bcsub(bcadd($sub['total_amount'], $sub['fine_amount'], 2), $sub['paid_amount'], 2);

        $data = $request->all();
        $data['member_id'] = (int) $sub['member_id'];
        $data['amount'] = $amount;
        $data['payment_type'] = 'annual_subscription';
        $data['payment_method'] = $data['payment_method'] ?? 'cash';
        $data['related_entity_type'] = 'subscriptions';
        $data['related_entity_id'] = (int) $id;
        $data['description'] = 'اشتراك سنوي ' . $sub['financial_year'] . ' — ' . ($sub['person_name'] ?? $sub['member_name']);

        $result = PaymentService::processPayment($data);
        if (!$result['success']) {
            return $this->redirect("/members/{$sub['member_id']}/subscriptions")->withError($result['error']);
        }

        $db->update('subscriptions', [
            'paid_amount' => bcadd($sub['paid_amount'], $amount, 2),
            'payment_id'  => $result['payment_id'],
            'status'      => 'paid',
            'paid_at'     => date('Y-m-d H:i:s'),
            'updated_at'  => date('Y-m-d H:i:s'),
        ], '`id` = ?', [(int) $id]);

        EventBus::dispatch('subscription.paid', [
            'subscription_id' => (int) $id,
            'member_id'       => (int) $sub['member_id'],
            'year'            => $sub['financial_year'],
            'amount'          => $amount,
        ]);

        return $this->redirect("/members/{$sub['member_id']}/subscriptions")->withSuccess('تم تسجيل الاشتراك — إيصال: ' . $result['receipt_number']);
    }

    public function exempt(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $sub = $db->selectOne("SELECT * FROM subscriptions WHERE id = ?", [(int) $id]);
        if (!$sub) return $this->redirect('/subscriptions')->withError('الاشتراك غير موجود');

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

        $employee = App::getInstance()->currentEmployee();
        $db->update('subscriptions', [
            'status'           => 'exempt',
            'exempted_by'      => $employee ? (int) $employee->id : null,
            'exemption_reason' => $reason,
            'updated_at'       => date('Y-m-d H:i:s'),
        ], '`id` = ?', [(int) $id]);

        return $this->redirect("/members/{$sub['member_id']}/subscriptions")->withSuccess('تم إعفاء الاشتراك');
    }

    public function batchGenerateForm(Request $request): Response
    {
        $db = App::getInstance()->db();
        $branches = $db->select("SELECT id, name_ar FROM branches WHERE is_active = 1 ORDER BY name_ar");
        return $this->view('Subscriptions.Views.batch-generate', ['branches' => $branches, 'result' => null]);
    }

    public function batchGenerate(Request $request): Response
    {
        $year = trim((string) $request->post('financial_year', ''));
        $branchId = $request->post('branch_id', '') !== '' ? (int) $request->post('branch_id') : null;

        if ($year === '') return $this->redirect('/subscriptions/batch-generate')->withError('السنة المالية مطلوبة');

        $result = SubscriptionGenerator::generateForYear($year, $branchId);

        $db = App::getInstance()->db();
        $branches = $db->select("SELECT id, name_ar FROM branches WHERE is_active = 1 ORDER BY name_ar");

        return $this->view('Subscriptions.Views.batch-generate', ['branches' => $branches, 'result' => $result]);
    }

    private static function currentFinancialYear(): string
    {
        $month = (int) date('n');
        $year = (int) date('Y');
        if ($month >= 7) return $year . '/' . ($year + 1);
        return ($year - 1) . '/' . $year;
    }
}