<?php

namespace IpagWoocommerce;

class TransactionResponseTransformer implements TransformerInterface
{
    private ?SerializerInterface $serializer = null;

    public function __construct(?SerializerInterface $serializer = null)
    {
        $this->serializer = $serializer ?? new JsonSerializer();
    }

    public function transform(array $response): array
    {
        $response_data = ArrUtils::get($response, 'body', []);

        if (!$response_data) {
            return $response;
        }

        if (is_string($response_data)) {
            try {
                $response_data = $this->serializer->deserialize($response_data);
            } catch (\Throwable $th) {
                $response_data = [];

            }
        }

        if (!is_array($response_data)) {
            return $response;
        }

        $pix_handler = function () use ($response_data) {
            $pix = ArrUtils::get($response_data, 'attributes.pix');

            return !$pix ? [] : [
                'qrcode' => ArrUtils::get($pix, 'qrcode'),
                'link' => ArrUtils::get($pix, 'link'),
            ];
        };

        $customer_handler = function () use ($response_data) {
            $customer = ArrUtils::get($response_data, 'attributes.customer');

            $billing_address = [
                'logradouro' => ArrUtils::get($customer, 'address.street') ?: ArrUtils::get($customer, 'billing_address.street'),
                'numero' => ArrUtils::get($customer, 'address.number') ?: ArrUtils::get($customer, 'billing_address.number'),
                'bairro' => ArrUtils::get($customer, 'address.district') ?: ArrUtils::get($customer, 'billing_address.district'),
                'complemento' => ArrUtils::get($customer, 'address.complement') ?: ArrUtils::get($customer, 'billing_address.complement'),
                'cidade' => ArrUtils::get($customer, 'address.city') ?: ArrUtils::get($customer, 'billing_address.city'),
                'estado' => ArrUtils::get($customer, 'address.state') ?: ArrUtils::get($customer, 'billing_address.state'),
                'cep' => ArrUtils::get($customer, 'address.zip_code') ?: ArrUtils::get($customer, 'billing_address.zip_code'),
            ];

            return !$customer ? [] : [
                'nome' => ArrUtils::get($customer, 'name'),
                'email' => ArrUtils::get($customer, 'email'),
                'telefone' => ArrUtils::get($customer, 'phone'),
                'cpf_cnpj' => ArrUtils::get($customer, 'cpf_cnpj'),
                'endereco' => $billing_address,
            ];
        };

        $card_handler = function () use ($response_data) {
            $card = ArrUtils::get($response_data, 'attributes.card');

            return !$card ? [] : [
                'titular' => ArrUtils::get($card, 'holder'),
                'numero' => ArrUtils::get($card, 'number'),
                'vencimento' => ArrUtils::get($card, 'expiry_month') . '/' . ArrUtils::get($card, 'expiry_year'),
                'bandeira' => ArrUtils::get($card, 'brand'),
            ];
        };

        $products_handler = function () use ($response_data) {
            $items = ArrUtils::get($response_data, 'attributes.products', []);
            $products = [];

            foreach ($items as $item) {
                $products[] = [
                    'nome' => ArrUtils::get($item, 'name'),
                    'quantidade' => ArrUtils::get($item, 'quantity'),
                    'valor' => ArrUtils::get($item, 'unit_price'),
                ];
            }

            return $products;
        };

        $antifraud_handler = function () use ($response_data) {
            $antifraud = ArrUtils::get($response_data, 'attributes.antifraud');

            return !$antifraud ? [] : [
                'score' => ArrUtils::get($antifraud, 'score'),
                'status' => ArrUtils::get($antifraud, 'status'),
                'message' => ArrUtils::get($antifraud, 'message'),
            ];
        };

        $split_rules_handler = function () use ($response_data) {
            $split_rules = ArrUtils::get($response_data, 'attributes.split_rules', []);
            $rules = [];

            foreach ($split_rules as $rule) {
                $rules[] = [
                    'rule' => ArrUtils::get($rule, 'id'),
                    'seller_id' => ArrUtils::get($rule, 'attributes.receiver.id'),
                    'amount' => ArrUtils::get($rule, 'attributes.amount'),
                    'percentage' => ArrUtils::get($rule, 'attributes.percentage'),
                    'liable' => ArrUtils::get($rule, 'attributes.liable'),
                    'charge_processing_fee' => ArrUtils::get($rule, 'attributes.charge_processing_fee'),
                    'hold_receivables' => ArrUtils::get($rule, 'attributes.hold_receivables'),
                ];
            }

            return $rules;
        };

        $subscription_handler = function () use ($response_data) {
            $subscription = ArrUtils::get($response_data, 'attributes.subscription');

            $invoice_handler = function () use ($subscription) {
                $invoice = ArrUtils::get($subscription, 'attributes.last_invoice');

                return !$invoice ? [] : [
                    'numero' => ArrUtils::get($invoice, 'number'),
                    'valor' => ArrUtils::get($invoice, 'amount'),
                    'valor_pago' => ArrUtils::get($invoice, 'payment.amount'),
                    'desconto' => ArrUtils::get($invoice, 'discount'),
                    'data_pagamento' => ArrUtils::get($invoice, 'payment.paid_at'),
                    'descricao' => ArrUtils::get($invoice, 'description'),
                ];

            };

            return !$subscription ? [] : [
                'id' => ArrUtils::get($subscription, 'id'),
                'profile_id' => ArrUtils::get($subscription, 'attributes.profile_id'),
                'ativo' => ArrUtils::get($subscription, 'attributes.is_active'),
                'descricao' => ArrUtils::get($subscription, 'attributes.description'),
                'valor' => ArrUtils::get($subscription, 'attributes.amount'),
                'frequencia' => ArrUtils::get($subscription, 'attributes.frequency'),
                'intervalo' => ArrUtils::get($subscription, 'attributes.interval'),
                'inicio' => ArrUtils::get($subscription, 'attributes.starting_date'),
                'vencimento' => ArrUtils::get($subscription, 'attributes.closing_date'),
                'card_token' => ArrUtils::get($subscription, 'attributes.creditcard.token'),
                'criada_em' => ArrUtils::get($subscription, 'attributes.created_at'),
                'parcela' => $invoice_handler(),
            ];
        };

        $history_handler = function () use ($response_data) {
            $histories = ArrUtils::get($response_data, 'attributes.history', []);
            $history_items = [];

            foreach ($histories as $key => $history) {
                $history_items["historico_{$key}"] = [
                    'valor' => ArrUtils::get($history, 'amount'),
                    'tipo' => ArrUtils::get($history, 'type'),
                    'status' => ArrUtils::get($history, 'status'),
                    'codigo_resposta' => ArrUtils::get($history, 'response_code'),
                    'mensagem_resposta' => ArrUtils::get($history, 'response_message'),
                    'codigo_autorizacao' => ArrUtils::get($history, 'authorization_code'),
                    'id_autorizacao' => ArrUtils::get($history, 'authorization_id'),
                    'nsu_autorizacao' => ArrUtils::get($history, 'authorization_nsu'),
                    'criado_em' => ArrUtils::get($history, 'created_at'),
                ];
            }

            return $history_items;
        };

        $tokenExpiresMonth = ArrUtils::get($response_data, 'attributes.card.expiry_month');
        $tokenExpiresYear = ArrUtils::get($response_data, 'attributes.card.expiry_year');

        //eq: 2031-01-31 23:59:59
        $expiresAt = ArrUtils::get($response_data, 'attributes.subscription.creditcard.attributes.expires_at');

        if (!$tokenExpiresMonth && !$tokenExpiresYear && $expiresAt) {
            try {
                $dt = new \DateTime($expiresAt);

                $tokenExpiresMonth = $dt->format('m');
                $tokenExpiresYear = $dt->format('Y');
            } catch (\Throwable $e) {
                //do nothing
            }
        }

        $card = $card_handler();

        $token =
            ArrUtils::get($response_data, 'attributes.subscription.creditcard.token')
            ?: ArrUtils::get($response_data, 'attributes.card.token');

        $last4 = ArrUtils::get($response_data, 'attributes.subscription.creditcard.attributes.card.last4')
            ?: ArrUtils::get($response_data, 'attributes.card.attributes.last4')
            ?: substr(ArrUtils::get($response_data, 'attributes.card.number', ''), -4);

        $parsed = [
            'id' => ArrUtils::get($response_data, 'id'),
            'uuid' => ArrUtils::get($response_data, 'uuid'),
            'id_librepag' => ArrUtils::get($response_data, 'id'),
            'nsu' => ArrUtils::get($response_data, 'attributes.nsu'),
            'valor' => ArrUtils::get($response_data, 'attributes.amount'),
            'metodo' => ArrUtils::get($response_data, 'attributes.method'),
            'id_transacao' => ArrUtils::get($response_data, 'attributes.tid'),
            'num_pedido' => ArrUtils::get($response_data, 'attributes.order_id'),
            'criado_em' => ArrUtils::get($response_data, 'attributes.created_at'),
            'parcelas' => ArrUtils::get($response_data, 'attributes.installments'),
            'operadora' => ArrUtils::get($response_data, 'attributes.acquirer.name'),
            'url_retorno' => ArrUtils::get($response_data, 'attributes.callback_url'),
            'status_pagamento' => ArrUtils::get($response_data, 'attributes.status.code'),
            'id_assinatura' => ArrUtils::get($response_data, 'attributes.subscription.id'),
            'autorizacao_id' => ArrUtils::get($response_data, 'attributes.authorization_id'),
            'mensagem_transacao' => ArrUtils::get($response_data, 'attributes.status.message'),
            'operadora_mensagem' => ArrUtils::get($response_data, 'attributes.acquirer.message'),
            'url_autenticacao' => ArrUtils::get($response_data, 'attributes.url_authentication'),
            'linha_digitavel' => ArrUtils::get($response_data, 'attributes.boleto.digitable_line'),
            'profile_id' => ArrUtils::get($response_data, 'attributes.subscription.attributes.profile_id'),
            'last4' => $last4,
            'token' => $token,
            'mes' => $tokenExpiresMonth,
            'ano' => $tokenExpiresYear,
            'pix' => $pix_handler(),
            'cliente' => $customer_handler(),
            'cartao' => $card,
            'produtos' => $products_handler(),
            'antifraude' => $antifraud_handler(),
            'split_rules' => $split_rules_handler(),
            'assinatura' => $subscription_handler(),
            'historicos' => $history_handler(),

        ];

        $response['body'] = $parsed;

        return $response;
    }
}