<?php

namespace MercadoPago\Woocommerce\Notification;

use Exception;
use MercadoPago\Woocommerce\Configs\Seller;
use MercadoPago\Woocommerce\Configs\Store;
use MercadoPago\Woocommerce\Helpers\Requester;
use MercadoPago\Woocommerce\Libraries\Logs\Logs;
use MercadoPago\Woocommerce\Order\OrderStatus;
use MercadoPago\Woocommerce\Interfaces\MercadoPagoGatewayInterface;
use WC_Order;

if (!defined('ABSPATH')) {
    exit;
}

class WebhookNotification extends AbstractNotification
{
    public Requester $requester;

    /**
     * WebhookNotification constructor
     *
     * @param MercadoPagoGatewayInterface $gateway
     * @param Logs $logs
     * @param OrderStatus $orderStatus
     * @param Seller $seller
     * @param Store $store
     * @param Requester $requester
     */
    public function __construct(
        MercadoPagoGatewayInterface $gateway,
        Logs $logs,
        OrderStatus $orderStatus,
        Seller $seller,
        Store $store,
        Requester $requester
    ) {
        parent::__construct($gateway, $logs, $orderStatus, $seller, $store);

        $this->requester = $requester;
    }

    /**
     * Handle Notification Request
     *
     * @param $data
     *
     * @return void
     * @throws Exception
     */
    public function handleReceivedNotification($data)
    {
        parent::handleReceivedNotification($data);

        if (!isset($data['data_id']) || !isset($data['type'])) {
            $message = 'data_id or type not set';
            $this->logs->file->error($message, __CLASS__, $data);

            if (!isset($data['id']) || !isset($data['topic'])) {
                $message = 'Mercado Pago request failure';
                $this->logs->file->error($message, __CLASS__, $data);
                return $this->setResponse(422, $message);
            }
        }

        if ($data['type'] !== 'payment') {
            $message = 'Mercado Pago Invalid Requisition';
            return $this->setResponse(422, $message);
        }

        $payment_id = preg_replace('/\D/', '', $data['data_id']);

        $headers  = ['Authorization: Bearer ' .  $this->seller->getCredentialsAccessToken()];
        $response = $this->requester->get("/v1/payments/$payment_id", $headers);

        if ($response->getStatus() !== 200) {
            $message = 'Error when processing received data';
            $this->logs->file->error($message, __CLASS__, (array) $response);
            return $this->setResponse(422, $message);
        }

        $this->handleSuccessfulRequest($response->getData());
    }

    public function handleSuccessfulRequestInternal($data, $order): void
    {
        $oldOrderStatus = $order->get_status();
        $processedStatus = $this->getProcessedStatus($order, $data);

        $this->logs->file->info(
            sprintf(
                'Changing order status from %s to %s',
                $oldOrderStatus,
                $this->orderStatus->mapMpStatusToWoocommerceStatus(str_replace('_', '', $processedStatus))
            ),
            __CLASS__
        );

        $this->processStatus($processedStatus, $order, $data);
        $this->setResponse(200, 'Webhook Notification Successfully');
    }

    /**
     * Process status
     *
     * @param WC_Order $order
     * @param mixed $data
     *
     * @return string
     */
    public function getProcessedStatus(WC_Order $order, $data): string
    {
        $status        = $data['status'] ?? 'pending';
        $total_paid    = $data['transaction_details']['total_paid_amount'] ?? 0.00;
        $total_refund  = $data['transaction_amount_refunded'] ?? 0.00;
        $coupon_amount = $data['coupon_amount'] ?? 0.00;

        $this->updateMeta($order, '_used_gateway', get_class($this));

        if (!empty($data['payer']['email'])) {
            $this->updateMeta($order, 'Buyer email', $data['payer']['email']);
        }

        if (!empty($data['payment_type_id'])) {
            $this->updateMeta($order, 'Payment type', $data['payment_type_id']);
        }

        if (!empty($data['payment_method_id'])) {
            $this->updateMeta($order, 'Payment method', $data['payment_method_id']);
        }

        $this->updateMeta(
            $order,
            'Mercado Pago - Payment ' . $data['id'],
            '[Date ' . gmdate('Y-m-d H:i:s', strtotime($data['date_created'])) .
                ']/[Amount ' . $data['transaction_amount'] .
                ']/[Paid ' . $total_paid .
                ']/[Coupon ' . $coupon_amount .
                ']/[Refund ' . $total_refund . ']'
        );

        $this->updateMeta($order, '_Mercado_Pago_Payment_IDs', $data['id']);

        $order->save();

        return $status;
    }
}
