<?php

namespace App\Services\Payment\Methods;

use App\Enums\PaymentStatusEnum;
use App\Exceptions\PaymentProcessingException;
use App\Models\Payment;
use App\Services\Payment\Payable;
use App\Services\Payment\Traits\PaymentServiceHelper;
use App\Traits\MediaUploader;
use App\Traits\PaymentHelper;
use Illuminate\Support\Facades\DB;

class ManualPaymentService extends AbstractPayment
{
    use MediaUploader, PaymentHelper, PaymentServiceHelper;

    public function pay(Payable $payable, ?array $rest = [])
    {
        $meta = $this->makePayment($rest);

        $payment = $this->createPayment($payable, meta: $meta);

        return [
            'payment' => $payment,
            'response' => [
                'status' => true,
                'message' => __('Payment created successfully'),
            ],
        ];
    }

    private function makePayment($rest)
    {
        if (! isset($rest['fields']) || empty($rest['fields'])) {
            throw new PaymentProcessingException('Payment failed');
        }

        $fields = [];

        foreach ($rest['fields'] as $key => $field) {

            if ($field['type'] === 'file') {

                $fields[$key]['value'] = $this->upload($field['value']);
            } elseif ($field['type'] === 'image') {

                $fields[$key]['value'] = $this->upload($field['value']);
            } else {

                $fields[$key]['value'] = $field['value'];
            }

            $fields[$key]['label'] = $field['label'];
            $fields[$key]['type'] = $field['type'];
        }

        return $fields;
    }

    public function handleSuccess($pid)
    {
        $payment = Payment::where('payment_identifier', $pid)->first();

        if (! $payment) {
            throw new PaymentProcessingException(__('Payment not found'));
        }

        if ($payment->status === PaymentStatusEnum::PAID) {
            throw new PaymentProcessingException(__('Payment already processed'));
        }

        try {
            DB::beginTransaction();

            $this->quizDepositHandler($payment, PaymentStatusEnum::PAID);

            $this->updatePaymentStatus($payment, PaymentStatusEnum::PAID);

            $this->paidPayment($payment);

            DB::commit();
        } catch (\Throwable $th) {
            DB::rollBack();

            throw new PaymentProcessingException($th->getMessage());
        }
    }

    public function handleFailed($pid)
    {
        $payment = Payment::where('payment_identifier', $pid)->first();

        if (! $payment) {
            throw new PaymentProcessingException(__('Payment not found'));
        }

        if ($payment->status === PaymentStatusEnum::PAID) {
            throw new PaymentProcessingException(__('Payment already processed'));
        }

        try {
            DB::beginTransaction();

            $this->quizDepositHandler($payment, PaymentStatusEnum::CANCELLED);

            $this->updatePaymentStatus($payment, PaymentStatusEnum::CANCELLED);

            $this->cancelPayment($payment);

            DB::commit();
        } catch (\Throwable $th) {
            DB::rollBack();

            throw new PaymentProcessingException($th->getMessage());
        }
    }
}
