<?php

namespace App\Services\Payment\Methods;

use App\Exceptions\PaymentProcessingException;
use App\Models\PaymentMethod;
use App\Services\Payment\Payable;
use App\Services\Payment\Traits\PaymentServiceHelper;
use Illuminate\Http\Request;
use Mollie\Laravel\Facades\Mollie;

class MollieService extends AbstractPayment
{
    use PaymentServiceHelper;

    public function pay(Payable $payable, $rest = [])
    {
        $this->setUp($payable->getMethod());
        $response = $this->makePayment($payable, $rest);
        $payment = $this->createPayment($payable, $response->id);

        return [
            'payment' => $payment,
            'response' => [
                'payment_url' => $response->getCheckoutUrl(),
            ],
        ];
    }

    public function handleWebhook(Request $request)
    {
        $pid = $request->input('pid');

        if (! $pid) {
            throw new PaymentProcessingException(__('Invalid request'));
        }

        $payment = $this->getPaymentByPid($pid);

        $this->setUp($payment->paymentMethod);

        $mollie_object = Mollie::api()->payments->get($payment->gateway_id);

        if ($mollie_object->isPaid()) {
            return [
                'status' => 'success',
                'payment' => $payment,
            ];
        }

        if ($mollie_object->isFailed()) {
            return [
                'status' => 'failed',
                'payment' => $payment,
            ];
        }

        throw new PaymentProcessingException(__('Invalid request'), code: 1);
    }

    public function handleSuccess(Request $request)
    {
        $pid = $request->input('pid');

        $payment = $this->getPaymentByPid($pid);

        $this->setUp($payment->paymentMethod);

        $molliePayment = Mollie::api()->payments->get($payment->gateway_id);

        if (! $molliePayment->isPaid()) {
            throw new PaymentProcessingException('Payment is not successful');
        }

        return $pid;
    }

    public function handleFailed(Request $request)
    {
        $pid = $request->input('pid');

        $payment = $this->getPaymentByPid($pid);

        $this->setUp($payment->paymentMethod);

        $molliePayment = Mollie::api()->payments->get($payment->gateway_id);

        if (! $molliePayment->isFailed()) {
            throw new PaymentProcessingException('Payment is not successful');
        }

        return $pid;
    }

    private function makePayment(Payable $payable, $rest)
    {
        $payment = Mollie::api()->payments->create([
            'amount' => [
                'currency' => $payable->getCurrency(),
                'value' => $payable->getConvertedAmount(), // amount should be a string
            ],
            'method' => 'creditcard',
            'description' => 'Payment for order '.$payable->getPid(),
            'redirectUrl' => $this->getReturnUrl($payable->getMethod(), $payable->getPid(), 'success'),
            'cancelUrl' => $this->getReturnUrl($payable->getMethod(), $payable->getPid(), 'cancel'),
            'webhookUrl' => $this->getWebHookUrl($payable->getMethod()),
            'metadata' => [
                'pid' => $payable->getPid(),
            ],
        ]);

        return $payment;
    }

    private function setUp(PaymentMethod $paymentMethod)
    {
        config(['mollie.key' => $paymentMethod->meta['api_key']]);
    }
}
