<?php

namespace App\Controller;

use App\Controller\HelloAssoApiController;
use App\Entity\GlobalParameter;
use App\Entity\HelloAsso;
use App\Enum\HelloassoStateEnum;
use Doctrine\ORM\EntityManagerInterface;
use Sonata\AdminBundle\Controller\CRUDController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\SerializerInterface;

class HelloAssoController extends CRUDController
{
    private $router;
    private $em;
    private $serializer;
    private $updatedData;
    private $newData;
    private $isTest;

    public function __construct(RouterInterface $router, EntityManagerInterface $em, SerializerInterface $serializer)
    {
        $this->router = $router;
        $this->em = $em;
        $this->serializer = $serializer;
        $this->updatedData = [];
        $this->newData = [];
        $this->isTest = false;
    }

    public function synchroTestAction(Request $request): Response
    {
        return $this->synchroAction($request);
    }

    public function synchroAction(Request $request): Response
    {
        if (empty($this->em->getRepository(GlobalParameter::class)->val(GlobalParameter::HELLOASSO_CLIENTID)) ||
            empty($this->em->getRepository(GlobalParameter::class)->val(GlobalParameter::HELLOASSO_CLIENTSECRET))) {
            $this->addFlash(
                'error',
                'Vous devez configurer HelloAsso (Administration => Configuration => HelloAsso ClientId et HelloAsso ClientSecret) !'
            );

            return $this->redirect($request->headers->get('referer'));
        }
        if (null != $request->get('test')) {
            $this->isTest = ('true' == $request->get('test'));
        }
        $this->updatedData = [];
        $this->newData = [];
        $currentPage = 1;
        $totalPages = 100;
        $data = [];
        // Get all datas from API HELLOASSP
        for ($currentPage = 1; $currentPage <= $totalPages; ++$currentPage) {
            $jsonData = $this->forward('App\Controller\HelloAssoApiController::synchroItems', [
                'pageIndex' => $currentPage,
                'request' => $request,
            ]);
            $result = json_decode($jsonData->getContent(), true)['data'];
            $data = array_merge($data, array_values($result['data']));
            $pagination = $result['pagination'];
            $totalPages = $pagination['totalPages'];
            ++$currentPage;
        }

        // Synchronize with kohinos database => update status of paiement...
        foreach ($data as $item) {
            $helloasso = $this->em->getRepository(HelloAsso::class)->findOneBy(['helloassoid' => $item['id']]);
            if (!empty($helloasso)) {
                // UPDATE STATE AND PROCEED

                // state : "Waiting", "Processed", "Registered", "Deleted", "Refunded", "Unknown", "Canceled", "Contested"
                $itemState = $item['state'];
                $payments = isset($item['payments']) ? $item['payments'] : null;
                // statePayment : "Pending", "Authorized", "Refused", "Unknown", "Registered", "Error", "Refunded", "Refunding", "Waiting", "Canceled", "Contested", "WaitingBankValidation", "WaitingBankWithdraw"
                $statePayment = 'NONE';
                $paymentReceiptUrl = '';
                if (null != $payments) {
                    $statePayment = isset($payments[0]['state']) ? $payments[0]['state'] : 'NONE';
                }
                if ($helloasso->getStatePayment() != $statePayment) {
                    if (HelloAssoApiController::STATE_REFUNDING == $statePayment) {
                        $helloasso->setPaymentReceiptUrl('');
                        $this->logError($helloasso, 'REMBOURSEMENT EN COURS VIA HELLOASSO => Prendre les mesures nécessaires sur le Kohinos manuellement !');
                    } elseif (HelloAssoApiController::STATE_CONTESTED == $itemState && HelloAssoApiController::STATE_REFUNDED == $statePayment) {
                        $this->logError($helloasso, 'PAIEMENT CONTESTÉ VIA HELLOASSO => Prendre les mesures nécessaires sur le Kohinos manuellement !');
                        $helloasso->setPaymentReceiptUrl('');
                    } elseif (HelloAssoApiController::STATE_CANCELED == $itemState && HelloAssoApiController::STATE_REFUNDED == $statePayment) {
                        $this->logError($helloasso, 'PAIEMENT ANNULÉ VIA HELLOASSO => Prendre les mesures nécessaires sur le Kohinos manuellement !');
                        $helloasso->setPaymentReceiptUrl('');
                    } elseif (HelloAssoApiController::STATE_REFUNDED == $statePayment) {
                        $this->logError($helloasso, 'REMBOURSEMENT EFFECTUE VIA HELLOASSO => Prendre les mesures nécessaires sur le Kohinos manuellement !');
                        $helloasso->setPaymentReceiptUrl('');
                    } elseif ($helloasso->getState() != $itemState) {
                        $this->logError($helloasso, 'CHANGEMENT DE STATUS : ' . $helloasso->getState() . ' => ' . $itemState);
                        $helloasso->setPaymentReceiptUrl('');
                    } else {
                        $this->logError($helloasso, 'CHANGEMENT DE STATUS DU PAIEMENT : ' . $helloasso->getStatePayment() . ' => ' . $statePayment);
                        $helloasso->setPaymentReceiptUrl('');
                    }
                }
                $helloasso->setState($itemState);
                $helloasso->setStatePayment($statePayment);
                if (!$this->isTest) {
                    $this->em->persist($helloasso);
                    $this->em->flush();
                }
            } else {
                // Create one line in Helloasso with historical = true !
                $helloasso = new HelloAsso();
                $helloasso->setHistorical(true);
                $helloasso->setData($item);

                $helloasso->setHelloassoid((int) $item['id']);
                $itemMontant = floatval($item['amount']) / 100;
                $helloasso->setAmount($itemMontant);

                $payer = $item['payer'];
                $helloasso->setUserfirstname(isset($payer['company']) ? $payer['company'] : '');
                $helloasso->setPayeremail(isset($payer['email']) ? $payer['email'] : '');
                $helloasso->setPayerfirstname(isset($payer['firstName']) ? $payer['firstName'] : '');
                $helloasso->setPayerlastname(isset($payer['lastName']) ? $payer['lastName'] : '');

                // type : "Donation", "Payment", "Registration", "Membership", "MonthlyDonation", "MonthlyPayment", "OfflineDonation", "Contribution", "Bonus"
                $itemType = $item['type'];
                $itemState = $item['state'];
                $payments = isset($item['payments']) ? $item['payments'] : null;
                // statePayment : "Pending", "Authorized", "Refused", "Unknown", "Registered", "Error", "Refunded", "Refunding", "Waiting", "Canceled", "Contested", "WaitingBankValidation", "WaitingBankWithdraw"
                $statePayment = 'NONE';
                $paymentReceiptUrl = '';
                if (null != $payments) {
                    $statePayment = isset($payments[0]['state']) ? $payments[0]['state'] : 'NONE';
                }
                $helloasso->setType($itemType);

                $userFirstname = '';
                $userLastname = '';
                $userEmail = '';
                $userAdress = '';
                $userZipcode = '';
                $userCity = '';
                if ('Membership' == $itemType) {
                    $customFields = isset($item['customFields']) ? $item['customFields'] : [];
                    foreach ($customFields as $customField) {
                        if ('Email' == $customField['name']) {
                            $helloasso->setUseremail($customField['answer']);
                        } elseif ('Adresse' == $customField['name']) {
                            $userAdress = $customField['answer'];
                        } elseif ('Code Postal' == $customField['name']) {
                            $userZipcode = $customField['answer'];
                        } elseif ('Ville' == $customField['name']) {
                            $userCity = $customField['answer'];
                        }
                    }
                    $user = $item['user'];
                    $helloasso->setUserfirstname($user['firstName']);
                    $helloasso->setUserlastname($user['lastName']);
                    $this->logError($helloasso, 'Nouvelle adhésion de ' . $helloasso->getUserfirstname() . ' ' . $helloasso->getUserLastname(), true);
                } elseif ('Donation' == $itemType) {
                    $this->logError($helloasso, 'Nouveau don de ' . $helloasso->getUserfirstname() . ' ' . $helloasso->getUserLastname(), true);
                }

                $helloasso->setState($itemState);
                $helloasso->setStatePayment($statePayment);
                $helloasso->setOperationState(HelloassoStateEnum::HELLOASSO_STATE_HISTORICAL);
                if (!$this->isTest) {
                    $this->em->persist($helloasso);
                    $this->em->flush();
                }
            }
        }

        return $this->renderWithExtraParams('@kohinos/admin/helloasso_synchro.html.twig', [
            'test' => $this->isTest,
            'updatedData' => $this->updatedData,
            'newData' => $this->newData,
        ]);
    }

    public function logError(HelloAsso $helloasso, $message = '', $isNew = false)
    {
        $helloassoNormalize = $this->serializer->normalize($helloasso, null, [AbstractNormalizer::ATTRIBUTES => [
            'user' => ['name', 'email'],
            'prestataire' => ['id', 'raison'],
            'adherent' => ['id', 'name'],
            'errors',
            'data',
            'amount',
            'type',
            'state',
            'statePayment',
            'paymentReceiptUrl',
            'helloassoid',
            'userfirstname',
            'userlastname',
            'useremail',
            'operationState',
            'historical',
        ]]);
        if (!empty($message)) {
            $helloasso->setErrors($message);
            if ($isNew) {
                $this->newData[] = [
                    'data' => $helloassoNormalize,
                    'message' => $message,
                ];
            } else {
                $this->updatedData[$helloasso->getId()->__toString()] = [
                    'data' => $helloassoNormalize,
                    'message' => $message,
                ];
            }
        }
    }
}