<?php
declare(strict_types=1);

namespace App\Modules\Payments\Controllers\Api;

use App\Core\ApiController;
use App\Core\App;
use App\Core\Request;
use App\Core\Response;
use App\Core\Contracts\PaymentProcessorInterface;
use App\Core\Exceptions\ValidationException;

final class PaymentApiV1Controller extends ApiController
{
    private PaymentProcessorInterface $payments;

    public function __construct(Request $request)
    {
        parent::__construct();
        $this->request = $request;
        $this->payments = App::getInstance()->resolve(PaymentProcessorInterface::class);
    }

    public function index(Request $request): Response
    {
        $this->authorize('payment.view');

        $page = max(1, $this->queryInt('page', 1));
        $perPage = min(100, max(1, $this->queryInt('per_page', 25)));
        $memberId = $this->queryParam('member_id');
        $paymentType = $this->queryParam('payment_type');
        $dateFrom = $this->queryParam('date_from');
        $dateTo = $this->queryParam('date_to');

        $db = App::getInstance()->db();
        $where = ['p.is_archived = 0'];
        $params = [];

        if ($memberId) {
            $where[] = 'p.member_id = ?';
            $params[] = (int) $memberId;
        }

        if ($paymentType) {
            $where[] = 'p.payment_type = ?';
            $params[] = $paymentType;
        }

        if ($dateFrom) {
            $where[] = 'p.payment_date >= ?';
            $params[] = $dateFrom;
        }

        if ($dateTo) {
            $where[] = 'p.payment_date <= ?';
            $params[] = $dateTo;
        }

        $whereSql = implode(' AND ', $where);

        $countRow = $db->selectOne("SELECT COUNT(*) as total FROM payments p WHERE {$whereSql}", $params);
        $total = (int) ($countRow['total'] ?? 0);

        $offset = ($page - 1) * $perPage;
        $rows = $db->select(
            "SELECT p.id, p.member_id, p.payment_type, p.payment_method, p.amount, p.payment_date, p.receipt_number, p.status, p.created_at
             FROM payments p
             WHERE {$whereSql}
             ORDER BY p.id DESC
             LIMIT {$perPage} OFFSET {$offset}",
            $params
        );

        return $this->paginatedResponse($rows, $total, $page, $perPage);
    }

    public function show(Request $request, string $id): Response
    {
        $this->authorize('payment.view');

        $db = App::getInstance()->db();
        $payment = $db->selectOne(
            "SELECT p.*, m.full_name_ar as member_name, m.membership_number
             FROM payments p
             LEFT JOIN members m ON m.id = p.member_id
             WHERE p.id = ? AND p.is_archived = 0",
            [(int) $id]
        );

        if (!$payment) {
            return $this->errorResponse('الدفعة غير موجودة', 404);
        }

        return $this->successResponse($payment);
    }

    public function store(Request $request): Response
    {
        $this->authorize('payment.process_cash');

        try {
            $data = $this->validatedJson([
                'member_id' => 'required|integer',
                'amount' => 'required|numeric',
                'payment_type' => 'required|string',
                'payment_method' => 'nullable|in:cash,check,visa,transfer',
                'check_number' => 'nullable|string',
                'check_bank' => 'nullable|string',
                'notes' => 'nullable|string',
            ]);
        } catch (ValidationException $e) {
            return $this->errorResponse('بيانات غير صالحة', 422, $e->errors());
        }

        $result = $this->payments->processPayment($data);

        if (!($result['success'] ?? false)) {
            return $this->errorResponse($result['error'] ?? 'فشل في معالجة الدفع', 422);
        }

        return $this->successResponse($result, 201);
    }

    public function void(Request $request, string $id): Response
    {
        $this->authorize('payment.void_receipt');

        try {
            $data = $this->validatedJson([
                'reason' => 'required|string',
            ]);
        } catch (ValidationException $e) {
            return $this->errorResponse('سبب الإلغاء مطلوب', 422, $e->errors());
        }

        $result = $this->payments->voidPayment((int) $id, $data['reason']);

        if (!($result['success'] ?? false)) {
            return $this->errorResponse($result['error'] ?? 'فشل في إلغاء الدفعة', 422);
        }

        return $this->successResponse($result);
    }
}
