<?php

namespace App\Controllers\Api;

use App\Libraries\JwtAuth;
use CodeIgniter\HTTP\ResponseInterface;

class MobileMoneyController extends BaseApiController
{
    /**
     * POST api/payments/mobile-money/request
     * Body: msisdn (e.g. +256700123456) or phone (e.g. 700123456) and amount.
     * Proxies to mm.finflo.online and returns the gateway response as-is.
     */
    public function request(): ResponseInterface
    {
        $user = JwtAuth::user();
        if (! $user) {
            return $this->error('Unauthorized', 401);
        }

        $json = $this->request->getJSON(true) ?: [];
        $phone = $json['msisdn'] ?? $json['phone'] ?? '';
        $amount = isset($json['amount']) ? (float) $json['amount'] : null;

        if ($amount === null || $amount <= 0) {
            return $this->error('amount is required and must be positive', 400);
        }

        $msisdn = $this->normalizeMsisdn($phone);
        if ($msisdn === null) {
            return $this->error('Invalid phone. Use 7XXXXXXXX (9 digits starting with 7).', 400);
        }

        $config = config('MobileMoney');
        $baseUrl = $config->baseUrl;
        $url     = rtrim($baseUrl, '/') . '/pay';

        $body = [
            'msisdn' => $msisdn,
            'amount' => round($amount, 2),
        ];

        $client = service('curlrequest');
        $headers = [
            'Content-Type' => 'application/json',
            'Accept'       => 'application/json',
        ];
        if ($config->apiKey !== null && $config->apiKey !== '') {
            $headers['X-API-Key'] = $config->apiKey;
        }

        $requestOptions = [
            'headers' => $headers,
            'json'    => $body,
            'timeout' => 15,
        ];
        if (! $config->verifySSL) {
            $requestOptions['verify'] = false;
        }
        $response = $client->request('POST', $url, $requestOptions);

        $statusCode = $response->getStatusCode();
        $bodyStr    = $response->getBody();

        $decoded = json_decode($bodyStr, true);
        if ($decoded !== null) {
            return $this->response->setStatusCode($statusCode)->setJSON($decoded);
        }

        return $this->response->setStatusCode($statusCode)->setBody($bodyStr);
    }

    /**
     * GET api/payments/mobile-money/status/:reference
     * Proxies to mm.finflo.online and returns the gateway response as-is.
     */
    public function status(string $reference): ResponseInterface
    {
        $user = JwtAuth::user();
        if (! $user) {
            return $this->error('Unauthorized', 401);
        }

        $reference = trim($reference);
        if ($reference === '') {
            return $this->error('reference is required', 400);
        }

        $config = config('MobileMoney');
        $baseUrl = $config->baseUrl;
        $url     = rtrim($baseUrl, '/') . '/status/' . rawurlencode($reference);

        $client = service('curlrequest');
        $headers = [
            'Accept' => 'application/json',
        ];
        if ($config->apiKey !== null && $config->apiKey !== '') {
            $headers['X-API-Key'] = $config->apiKey;
        }

        $statusOptions = [
            'headers' => $headers,
            'timeout' => 10,
        ];
        if (! $config->verifySSL) {
            $statusOptions['verify'] = false;
        }
        $response = $client->request('GET', $url, $statusOptions);

        $statusCode = $response->getStatusCode();
        $bodyStr    = $response->getBody();

        $decoded = json_decode($bodyStr, true);
        if ($decoded !== null) {
            return $this->response->setStatusCode($statusCode)->setJSON($decoded);
        }

        return $this->response->setStatusCode($statusCode)->setBody($bodyStr);
    }

    /**
     * Normalize phone to +256XXXXXXXXX (Uganda).
     * Accepts: 700123456, 256700123456, +256700123456.
     */
    private function normalizeMsisdn(?string $phone): ?string
    {
        if ($phone === null || $phone === '') {
            return null;
        }
        $digits = preg_replace('/\D/', '', $phone);
        if (strlen($digits) === 9 && str_starts_with($digits, '7')) {
            return '+256' . $digits;
        }
        if (strlen($digits) === 12 && str_starts_with($digits, '256')) {
            return '+' . $digits;
        }
        return null;
    }
}
