<?php
/**
 * Stripe Gateway
 *
 * @package NemtlyBooking
 */

namespace NemtlyBooking\Gateways;

use NemtlyBooking\Interfaces\Payment_Gateway_Interface;
use NemtlyBooking\Services\Settings_Service;
use Stripe\Stripe;
use Stripe\PaymentIntent;
use Stripe\Refund;
use Stripe\Webhook;

/**
 * Class Stripe_Gateway
 */
class Stripe_Gateway implements Payment_Gateway_Interface {
    /**
     * Settings service
     *
     * @var Settings_Service
     */
    private $settings_service;

    /**
     * Stripe Secret Key
     *
     * @var string
     */
    private $secret_key;

    /**
     * Stripe Publishable Key
     *
     * @var string
     */
    private $publishable_key;

    /**
     * Webhook Secret
     *
     * @var string
     */
    private $webhook_secret;

    /**
     * Constructor
     *
     * @param Settings_Service $settings_service Settings service.
     */
    public function __construct( Settings_Service $settings_service ) {
        $this->settings_service = $settings_service;
        $this->init_stripe();
    }

    /**
     * Initialize Stripe
     */
    private function init_stripe() {
        $this->secret_key      = $this->settings_service->get_setting( 'stripe_secret_key' );
        $this->publishable_key = $this->settings_service->get_setting( 'stripe_publishable_key' );
        $this->webhook_secret  = $this->settings_service->get_setting( 'stripe_webhook_secret' );

        if ( $this->secret_key ) {
            Stripe::setApiKey( $this->secret_key );
        }
    }

    /**
     * Get gateway ID
     *
     * @return string
     */
    public function get_id() {
        return 'stripe';
    }

    /**
     * Get gateway name
     *
     * @return string
     */
    public function get_name() {
        return 'Stripe';
    }

    /**
     * Process a payment (create PaymentIntent)
     *
     * @param float  $amount   Amount to charge.
     * @param string $currency Currency code.
     * @param array  $metadata Additional metadata.
     *
     * @return array Result.
     */
    public function process_payment( $amount, $currency, $metadata = [] ) {
        try {
            $client_secret = $this->create_payment_intent( $amount, $currency, $metadata );
            return [
                'success'       => true,
                'client_secret' => $client_secret,
                'message'       => __( 'Payment intent created', 'nemtly-booking' ),
            ];
        } catch ( \Exception $e ) {
            return [
                'success' => false,
                'message' => $e->getMessage(),
            ];
        }
    }

    /**
     * Refund a payment
     *
     * @param string $transaction_id Transaction ID.
     * @param float  $amount         Amount to refund.
     *
     * @return bool
     */
    public function refund_payment( $transaction_id, $amount = null ) {
        if ( ! $this->secret_key ) {
            return false;
        }

        try {
            $params = [ 'payment_intent' => $transaction_id ];
            if ( $amount ) {
                $params['amount'] = $this->calculate_amount( $amount, 'USD' ); // Assuming USD for now or check currency
            }

            Refund::create( $params );
            return true;
        } catch ( \Exception $e ) {
            return false;
        }
    }

    /**
     * Create a payment intent
     *
     * @param float  $amount   Amount.
     * @param string $currency Currency.
     * @param array  $metadata Metadata.
     *
     * @return string Client secret.
     * @throws \Exception Stripe exception.
     */
    public function create_payment_intent( $amount, $currency, $metadata = [] ) {
        if ( ! $this->secret_key ) {
            throw new \Exception( __( 'Stripe is not configured', 'nemtly-booking' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
        }

        $intent = PaymentIntent::create(
            [
				'amount'                    => $this->calculate_amount( $amount, $currency ),
				'currency'                  => strtolower( $currency ),
				'metadata'                  => $metadata,
				'automatic_payment_methods' => [
					'enabled' => true,
				],
			]
        );

        return $intent->client_secret;
    }

    /**
     * Verify webhook signature
     *
     * @param string $payload    Raw payload.
     * @param string $sig_header Signature header.
     *
     * @return mixed Event object.
     * @throws \Exception Webhook exception.
     */
    public function verify_webhook( $payload, $sig_header ) {
        if ( ! $this->webhook_secret ) {
            throw new \Exception( 'Webhook secret not configured' );
        }

        return Webhook::constructEvent(
            $payload,
            $sig_header,
            $this->webhook_secret
        );
    }

    /**
     * Calculate amount in smallest currency unit (e.g. cents)
     *
     * @param float  $amount   Amount.
     * @param string $currency Currency.
     *
     * @return int
     */
    private function calculate_amount( $amount, $currency ) {
        // Zero-decimal currencies
        $zero_decimal = [ 'BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'UGX', 'VND', 'VUV', 'XAF', 'XOF', 'XPF' ];

        if ( in_array( strtoupper( $currency ), $zero_decimal, true ) ) {
            return (int) $amount;
        }

        return (int) round( $amount * 100 );
    }
}
