<?php

namespace App\Services;

use App\Contracts\PaymentGatewayInterface;
use App\Models\Order;
use App\Services\Gateways\ExactlyGateway;
use App\Services\Gateways\FenopayGateway;
use Illuminate\Support\Facades\DB;

class PaymentService
{
    /**
     * Returns all configured gateway instances keyed by id.
     */
    public function gatewayInstances(): array
    {
        $settings = DB::table('store_settings')->pluck('value', 'key');
        $instances = [];

        $exactly = $this->makeExactly($settings);
        if ($exactly) $instances['exactly'] = $exactly;

        $fenopay = $this->makeFenopay($settings);
        if ($fenopay) $instances['fenopay'] = $fenopay;

        return $instances;
    }

    /**
     * Returns list of active gateways with id and display label for the UI.
     */
    public function activeGateways(): array
    {
        $labels = [
            'exactly' => 'Exactly Payments',
            'fenopay' => 'Fenopay',
        ];

        return array_values(array_map(
            fn($id) => ['id' => $id, 'label' => $labels[$id]],
            array_keys($this->gatewayInstances())
        ));
    }

    /**
     * Returns the active gateway instance, or null if not configured.
     * @deprecated Use gatewayInstances() for multi-gateway support.
     */
    public function gateway(): ?PaymentGatewayInterface
    {
        $settings = DB::table('store_settings')->pluck('value', 'key');
        $active = $settings->get('payment_gateway', 'none');
        return match ($active) {
            'exactly' => $this->makeExactly($settings),
            'fenopay' => $this->makeFenopay($settings),
            default   => null,
        };
    }

    /**
     * Returns true when at least one gateway is configured.
     */
    public function isActive(): bool
    {
        return count($this->gatewayInstances()) > 0;
    }

    /**
     * Initiate payment for an order.
     * $selectedGateway: 'exactly' | 'fenopay' | null (auto-pick first active)
     */
    public function initiatePayment(Order $order, string $returnUrl, string $cancelUrl, ?string $selectedGateway = null): array
    {
        $instances = $this->gatewayInstances();

        if (empty($instances)) {
            return [
                'test_mode'    => true,
                'order_number' => $order->order_number,
                'redirect_url' => null,
                'session_id'   => null,
            ];
        }

        // Use selected gateway if valid, otherwise first available
        $gatewayId = ($selectedGateway && isset($instances[$selectedGateway]))
            ? $selectedGateway
            : array_key_first($instances);

        $gateway = $instances[$gatewayId];
        $session = $gateway->createSession($order, $returnUrl, $cancelUrl);

        $order->update([
            'payment_reference' => $session['session_id'],
            'payment_method'    => $gatewayId,
        ]);

        return [
            'test_mode'    => false,
            'order_number' => $order->order_number,
            'redirect_url' => $session['redirect_url'],
            'session_id'   => $session['session_id'],
        ];
    }

    /**
     * Verify a payment session after the user returns from the gateway.
     * Returns 'paid', 'pending', or 'failed'.
     */
    public function verifySession(string $sessionId): string
    {
        $gateway = $this->gateway();
        if (!$gateway) return 'pending';
        return $gateway->getSessionStatus($sessionId);
    }

    /**
     * Handle an incoming webhook payload from the gateway.
     * Returns the order_number if the payment was confirmed, null otherwise.
     */
    public function handleWebhook(string $gatewayName, array $payload, string $rawBody, string $signature): ?string
    {
        $gateway = match ($gatewayName) {
            'exactly' => $this->makeExactlyFromSettings(),
            'fenopay' => $this->makeFenopayFromSettings(),
            default   => null,
        };

        return $gateway?->handleWebhook($payload, $rawBody, $signature);
    }

    private function activeGatewayName(): string
    {
        return DB::table('store_settings')->where('key', 'payment_gateway')->value('value') ?? 'none';
    }

    private function makeExactly($settings): ?ExactlyGateway
    {
        $key    = $settings->get('exactly_api_key', '');
        $mid    = $settings->get('exactly_merchant_id', '');
        $secret = $settings->get('exactly_webhook_secret', '');
        if (!$key || !$mid) return null;
        return new ExactlyGateway($key, $mid, $secret);
    }

    private function makeFenopay($settings): ?FenopayGateway
    {
        $key    = $settings->get('fenopay_api_key', '');
        $mid    = $settings->get('fenopay_merchant_id', '');
        $secret = $settings->get('fenopay_webhook_secret', '');
        if (!$key || !$mid) return null;
        return new FenopayGateway($key, $mid, $secret);
    }

    private function makeExactlyFromSettings(): ?ExactlyGateway
    {
        $settings = DB::table('store_settings')->pluck('value', 'key');
        return $this->makeExactly($settings);
    }

    private function makeFenopayFromSettings(): ?FenopayGateway
    {
        $settings = DB::table('store_settings')->pluck('value', 'key');
        return $this->makeFenopay($settings);
    }
}
