<?php

namespace App\Controllers;

use App\Core\Controller;
use App\Helpers\PaymentGateway;
use App\Helpers\Url;
use App\Models\Contribution;
use App\Models\Receipt;
use App\Models\Setting;
use App\Models\AuditLog;
use App\Models\LoanRepayment;
use App\Models\Loan;

class PublicPaymentController extends Controller
{
    // Public callback that gateways can call (no login required)
    public function callback()
    {
        $gateway = $_GET['gateway'] ?? '';
        $reference = $_GET['ref'] ?? $_GET['reference'] ?? '';

        if (!$gateway || !$reference) {
            $this->view('payment/callback', ['success' => false, 'message' => 'Missing payment parameters']);
            return;
        }

        $result = null;
        if ($gateway === 'paystack') {
            $result = PaymentGateway::verifyPaystackPayment($reference);
        } elseif ($gateway === 'hubtel') {
            $result = PaymentGateway::verifyHubtelPayment($reference);
        } else {
            $this->view('payment/callback', ['success' => false, 'message' => 'Unknown gateway']);
            return;
        }

        $contributionModel = new Contribution();
        $contributions = $contributionModel->raw(
            "SELECT * FROM contributions WHERE gateway_ref = ? ORDER BY id DESC LIMIT 1",
            [$reference]
        );

        if (empty($contributions)) {
            // If not a contribution, check if this reference maps to a loan repayment
            if (str_starts_with($reference, 'loan_lr_')) {
                $parts = explode('_', $reference);
                $repaymentId = $parts[2] ?? null;
                if ($repaymentId) {
                    $loanRepModel = new LoanRepayment();
                    if ($result['success']) {
                        $paidAmount = $result['amount'];
                        $loanRepModel->recordPayment((int)$repaymentId, $paidAmount, $gateway, $reference, 'Online payment');

                        $repRow = $loanRepModel->find((int)$repaymentId);
                        $loanId = $repRow->loan_id ?? 0;
                        $totals = $loanRepModel->getTotalsByLoan($loanId);
                        $loanModel = new Loan();
                        if ($totals && $totals->total_paid >= $totals->total_due) {
                            $loanModel->update($loanId, ['status' => 'completed']);
                        }

                        $audit = new AuditLog();
                        $audit->log(0, 'loan.repayment', 'loan_repayments', $repaymentId, "Online repayment via {$gateway}: GHS {$paidAmount} (ref: {$reference})");

                        $this->view('payment/callback', ['success' => true, 'message' => 'Loan repayment recorded', 'reference' => $reference]);
                        return;
                    } else {
                        $this->view('payment/callback', ['success' => false, 'message' => $result['message'] ?? 'Loan payment verification failed', 'reference' => $reference]);
                        return;
                    }
                }
            }

            $this->view('payment/callback', ['success' => false, 'message' => 'Payment record not found']);
            return;
        }

        $contribution = $contributions[0];

        if ($result['success']) {
            $newBalance = max(0, ($contribution->total_amount ?? $result['amount']) - $result['amount']);
            $status = ($newBalance <= 0) ? 'completed' : 'partial';

            $contributionModel->update($contribution->id, [
                'status' => $status,
                'balance' => $newBalance,
                'gateway_response' => json_encode($result['raw'] ?? []),
            ]);

            if ($contribution->paid_month && $contribution->contribution_type_id) {
                $contributionModel->updateBalanceForObligation(
                    $contribution->user_id,
                    $contribution->contribution_type_id,
                    $contribution->paid_month
                );
            }

            $receiptId = null;
            if ($status === 'completed') {
                $receiptModel = new Receipt();
                $receiptId = $receiptModel->create([
                    'contribution_id' => $contribution->id,
                    'receipt_number' => $receiptModel->generateNumber(),
                    'issued_date' => date('Y-m-d'),
                    'issued_by' => $contribution->user_id,
                ]);
            }

            $audit = new AuditLog();
            $audit->log($contribution->user_id, 'payment.completed', 'contributions', $contribution->id,
                "Online payment via {$gateway}: GHS {$result['amount']} (ref: {$reference})");

            $this->view('payment/callback', [
                'success' => true,
                'message' => 'Payment completed successfully',
                'amount' => $result['amount'],
                'reference' => $reference,
                'gateway' => $gateway,
                'status' => $status,
                'receiptId' => $receiptId,
                'contributionId' => $contribution->id,
            ]);
        } else {
            $contributionModel->update($contribution->id, [
                'status' => 'failed',
                'gateway_response' => json_encode($result['raw'] ?? []),
            ]);

            $audit = new AuditLog();
            $audit->log($contribution->user_id, 'payment.failed', 'contributions', $contribution->id,
                "Online payment failed via {$gateway}: {$result['message']} (ref: {$reference})");

            $this->view('payment/callback', [
                'success' => false,
                'message' => $result['message'] ?? 'Payment verification failed',
                'reference' => $reference,
            ]);
        }
    }

    // webhook endpoint for gateways
    public function webhook($params)
    {
        $gateway = $params['gateway'] ?? '';

        if ($gateway === 'paystack') {
            $raw = file_get_contents('php://input');

            // Verify Paystack signature if secret is configured
            $settingModel = new Setting();
            $secret = $settingModel->getValue('paystack_secret_key', '');
            if ($secret) {
                $sig = $_SERVER['HTTP_X_PAYSTACK_SIGNATURE'] ?? '';
                $expected = hash_hmac('sha512', $raw, $secret);
                if (!$sig || !hash_equals($expected, $sig)) {
                    http_response_code(403);
                    echo 'Invalid signature';
                    return;
                }
            }

            $input = json_decode($raw);
            if (!$input || !isset($input->event)) {
                http_response_code(400);
                echo 'Invalid event';
                return;
            }

            if ($input->event === 'charge.success') {
                $reference = $input->data->reference ?? '';
                $amount = ($input->data->amount ?? 0) / 100;

                $contributionModel = new Contribution();
                $contributions = $contributionModel->raw(
                    "SELECT * FROM contributions WHERE gateway_ref = ? AND status = 'pending' ORDER BY id DESC LIMIT 1",
                    [$reference]
                );

                if (!empty($contributions)) {
                    $c = $contributions[0];
                    $newBalance = max(0, ($c->total_amount ?? $amount) - $amount);
                    $status = ($newBalance <= 0) ? 'completed' : 'partial';

                    $contributionModel->update($c->id, [
                        'status' => $status,
                        'balance' => $newBalance,
                        'gateway_response' => json_encode($input),
                    ]);

                    if ($c->paid_month && $c->contribution_type_id) {
                        $contributionModel->updateBalanceForObligation(
                            $c->user_id, $c->contribution_type_id, $c->paid_month
                        );
                    }

                    if ($status === 'completed') {
                        $receiptModel = new Receipt();
                        $receiptModel->create([
                            'contribution_id' => $c->id,
                            'receipt_number' => $receiptModel->generateNumber(),
                            'issued_date' => date('Y-m-d'),
                            'issued_by' => $c->user_id,
                        ]);
                    }
                } elseif (str_starts_with($reference, 'loan_lr_')) {
                    $parts = explode('_', $reference);
                    $repaymentId = $parts[2] ?? null;
                    if ($repaymentId) {
                        $loanRepModel = new LoanRepayment();
                        $loanRepModel->recordPayment((int)$repaymentId, $amount, 'paystack', $reference, 'Webhook auto payment');

                        $repRow = $loanRepModel->find((int)$repaymentId);
                        $loanId = $repRow->loan_id ?? 0;
                        $totals = $loanRepModel->getTotalsByLoan($loanId);
                        $loanModel = new Loan();
                        if ($totals && $totals->total_paid >= $totals->total_due) {
                            $loanModel->update($loanId, ['status' => 'completed']);
                        }

                        $audit = new AuditLog();
                        $audit->log(0, 'loan.repayment', 'loan_repayments', $repaymentId, "Webhook repayment: GHS {$amount} (ref: {$reference})");
                    }
                }
            }

            http_response_code(200);
            echo 'OK';
        } elseif ($gateway === 'hubtel') {
            $input = json_decode(file_get_contents('php://input'));
            http_response_code(200);
            echo 'OK';
        } else {
            http_response_code(400);
            echo 'Unknown gateway';
        }
    }
}
