<?php

declare(strict_types=1);

use Bot\Domain\Service\AnalyticsService;
use Bot\Domain\Service\PaymentService;
use Bot\Domain\Service\UserService;
use Bot\Infrastructure\Payment\NextPayGateway;
use Bot\Infrastructure\Payment\ZarinPalGateway;
use Bot\Infrastructure\Repository\InMemoryAnalyticsRepository;
use Bot\Infrastructure\Repository\InMemoryPaymentRepository;
use Bot\Infrastructure\Repository\InMemoryUserRepository;
use Dotenv\Dotenv;

require __DIR__ . '/../vendor/autoload.php';

// Load environment variables
$dotenv = Dotenv::createImmutable(__DIR__ . '/..');
$dotenv->load();

// Initialize repositories and services
$userRepo = new InMemoryUserRepository();
$paymentRepo = new InMemoryPaymentRepository();
$analyticsRepo = new InMemoryAnalyticsRepository();

$userService = new UserService($userRepo);
$paymentService = new PaymentService($paymentRepo);
$analyticsService = new AnalyticsService($analyticsRepo);

// Get gateway configuration
$nextpayApiKey = $_ENV['NEXTPAY_API_KEY'] ?? '';
$zarinpalMerchantId = $_ENV['ZARINPAL_MERCHANT_ID'] ?? '';
$zarinpalSandbox = isset($_ENV['ZARINPAL_SANDBOX']) && $_ENV['ZARINPAL_SANDBOX'] === 'true';

// Get gateway type from query parameter
$gateway = $_GET['gateway'] ?? '';

if ($gateway === 'nextpay') {
    handleNextPayCallback($paymentService, $userService, $analyticsService, $nextpayApiKey);
} elseif ($gateway === 'zarinpal') {
    handleZarinPalCallback($paymentService, $userService, $analyticsService, $zarinpalMerchantId, $zarinpalSandbox);
} else {
    http_response_code(400);
    echo json_encode(['error' => 'Invalid gateway']);
}

function handleNextPayCallback(
    PaymentService $paymentService,
    UserService $userService,
    AnalyticsService $analyticsService,
    string $apiKey,
): void {
    $transId = $_POST['trans_id'] ?? $_GET['trans_id'] ?? '';
    $orderId = $_POST['order_id'] ?? $_GET['order_id'] ?? '';

    if (empty($transId) || empty($orderId)) {
        http_response_code(400);
        echo json_encode(['error' => 'Missing parameters']);
        return;
    }

    // Find payment by order_id (which is the payload)
    $payment = $paymentService->findByPayload($orderId);
    if ($payment === null) {
        http_response_code(404);
        echo json_encode(['error' => 'Payment not found']);
        return;
    }

    // Verify payment
    $nextpay = new NextPayGateway($apiKey);
    $verifyResult = $nextpay->verifyPayment($transId, $payment->getAmount(), $orderId);

    if (!$verifyResult['verified']) {
        $paymentService->markFailed($payment);
        http_response_code(400);
        echo json_encode(['error' => $verifyResult['error'] ?? 'Payment verification failed']);
        return;
    }

    // Mark payment as successful
    $paymentService->markSuccess($payment, $transId);

    // Upgrade user to premium
    $user = $userService->getOrCreateByTelegramId($payment->getUserId());
    $userService->upgradeToPremium($user);

    // Record analytics
    $analyticsService->recordPayment($user->getId(), $payment->getId());

    http_response_code(200);
    echo json_encode(['success' => true, 'message' => 'Payment verified successfully']);
}

function handleZarinPalCallback(
    PaymentService $paymentService,
    UserService $userService,
    AnalyticsService $analyticsService,
    string $merchantId,
    bool $sandbox,
): void {
    $authority = $_GET['Authority'] ?? '';
    $status = $_GET['Status'] ?? '';

    if (empty($authority)) {
        http_response_code(400);
        echo json_encode(['error' => 'Missing Authority parameter']);
        return;
    }

    // Find payment by authority (stored in external_id)
    $payment = $paymentService->findByExternalId($authority);
    if ($payment === null) {
        http_response_code(404);
        echo json_encode(['error' => 'Payment not found']);
        return;
    }

    if ($status !== 'OK') {
        $paymentService->markFailed($payment);
        http_response_code(400);
        echo json_encode(['error' => 'Payment was cancelled or failed']);
        return;
    }

    // Verify payment
    $zarinpal = new ZarinPalGateway($merchantId, $sandbox);
    $verifyResult = $zarinpal->verifyPayment($authority, $payment->getAmount());

    if (!$verifyResult['verified']) {
        $paymentService->markFailed($payment);
        http_response_code(400);
        echo json_encode(['error' => $verifyResult['error'] ?? 'Payment verification failed']);
        return;
    }

    // Mark payment as successful
    $refId = $verifyResult['ref_id'] ?? $authority;
    $paymentService->markSuccess($payment, $refId);

    // Upgrade user to premium
    $user = $userService->getOrCreateByTelegramId($payment->getUserId());
    $userService->upgradeToPremium($user);

    // Record analytics
    $analyticsService->recordPayment($user->getId(), $payment->getId());

    http_response_code(200);
    echo json_encode(['success' => true, 'message' => 'Payment verified successfully']);
}

