<?php

declare(strict_types=1);

/**
 * Created by Aurélien RICHAUD (13/02/2018 17:04).
 */
require_once __DIR__
    . \DIRECTORY_SEPARATOR . '..'
    . \DIRECTORY_SEPARATOR . '..'
    . \DIRECTORY_SEPARATOR . 'classes'
    . \DIRECTORY_SEPARATOR . 'OAuthAccessToken.php';
require_once __DIR__
    . \DIRECTORY_SEPARATOR . '..'
    . \DIRECTORY_SEPARATOR . '..'
    . \DIRECTORY_SEPARATOR . 'classes'
    . \DIRECTORY_SEPARATOR . 'Clinique.php';

class AdminMyVetShopCliniqueSSOSelfController extends AdminController
{
    /**
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    protected function getCliniqueByAccessToken(OAuthAccessToken $accessToken): Clinique
    {
        $employee = new Employee($accessToken->id_employee);

        $ret = Clinique::getCliniqueByEmployeeId((int) $employee->id);

        if (!$ret) {
            throw new Exception('Clinic not found');
        }

        return $ret;
    }

    /**
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    protected function processGet(OAuthAccessToken $accessToken): void
    {
        $employee = new Employee($accessToken->id_employee);

        $logo = _PS_EMPLOYEE_IMG_DIR_ . $employee->id . '.jpg';
        // Création de la miniature au besoin
        ImageManager::thumbnail(
            $logo,
            'employee_' . (int) $employee->id . '.' . $this->imageType,
            150,
            $this->imageType,
            false,
            false
        );

        $ret = [
            'id' => $employee->id,
            'firstname' => $employee->firstname,
            'lastname' => $employee->lastname,
            'email' => $employee->email,
            'fullname' => $employee->firstname . ' ' . $employee->lastname,
            'logo' => 'https://' . strval(Configuration::get('PS_SHOP_DOMAIN_SSL'))
                . '/img/tmp/employee_' . (int) $employee->id . '.' . $this->imageType,
            'photo' => '',
            'theme' => '',
            'code_privilege' => '',
            'centrale' => 'centrale',
        ];

        $clinique = Clinique::getCliniqueByEmployeeId((int) $employee->id);

        if ($clinique) {
            // Photo de la clinique
            $photo = _PS_STORE_IMG_DIR_ . $clinique->id_store . '.jpg';
            ImageManager::thumbnail(
                $photo,
                'store_' . (int) $clinique->id_store . '.' . $this->imageType,
                300,
                $this->imageType,
                true,
                true
            );

            $theme = $clinique->getTheme();

            $ret['photo'] = 'https://' . Configuration::get('PS_SHOP_DOMAIN_SSL')
                . '/img/tmp/store_' . (int) $clinique->id_store . '.' . $this->imageType;

            if ($theme) {
                $ret['theme'] = 'theme' . $clinique->id_theme;
            }

            $ret['code_privilege'] = $clinique->code_privilege;
            $ret['centrale'] = $clinique->centrale;
        }

        echo \json_encode($ret);
        exit;
    }

    /**
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    protected function processPost(OAuthAccessToken $accessToken): void
    {
        if (!isset($_POST['action'])) {
            $_POST['action'] = null;
        }

        switch ($_POST['action']) {
            case 'retour-produit':
                echo \json_encode(['success' => false, 'message' => 'Mettez à jour votre application VetZen.']);
                exit;

            case 'retour-produit-new':
                $this->processPostRetourProduitNew($accessToken);
                break;

            case 'contact-vetzen':
                $this->processPostContactVetzen($accessToken);
                break;

            default:
        }

        echo \json_encode(['success' => false, 'message' => "Cette action n'est pas supportée."]);
        exit;
    }

    /**
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    protected function processPostRetourProduitNew(OAuthAccessToken $accessToken): void
    {
        $context = Context::getContext();
        \assert(null !== $context);

        if (!isset($_POST['commande']) || empty($_POST['commande'])) {
            header('HTTP/1.0 400 Bad Request');
            echo json_encode(['success' => false, 'message' => 'Le numéro de commande doit être rempli']);
            exit;
        }
        if (!isset($_POST['return_quantity']) || empty($_POST['return_quantity']) || !is_array($_POST['return_quantity'])) {
            \header('HTTP/1.0 400 Bad Request');
            echo \json_encode(['success' => false, 'message' => 'Veuillez indiquer le nombre de produits à retourner']);
            exit;
        }
        if (!isset($_POST['raison']) || empty($_POST['raison'])) {
            \header('HTTP/1.0 400 Bad Request');
            echo \json_encode(['success' => false, 'message' => 'Veuillez indiquer la raison du retour produit']);
            exit;
        }
        $order = new Order((int) $_POST['commande']);
        if (!$order->date_add) {
            \header('HTTP/1.0 400 Bad Request');
            echo \json_encode(['success' => false, 'message' => "Le numéro de commande n'est pas valide"]);
            exit;
        }

        switch ($_POST['raison']) {
            case 'Erreur de commande client':
            case 'Animal décédé':
                $titre = 'Demande de retour produit';
                $message = "L'équipe de VetZen se chargera d'effectuer le remboursement du ou des produits retourné(s) à la centrale directement sur la carte bancaire du client.";
                break;

            case 'Erreur de livraison centrale':
                $titre = "ALERTE CENTRALE\u{a0}- Demande de retour produit";
                $message
                    = "La Centrale doit renvoyer dans les meilleurs délais le ou les bons produits et informer l'équipe VetZen ainsi que la clinique du client. La clinique informera son client à la réception du ou des nouveaux produits.";
                break;

            case 'Produit défectueux ou non conforme':
                $titre = 'Demande de retour produit';
                $message
                    = "ATTENTION : le remboursement n'est pas systématique pour ce type de retour. Dans le cas d'un problème de conditionnement (exemple : sac abimé à la livraison), la centrale devra prendre en charge l'échange du produit. Dans le cas d'un problème qualité sur le produit, le fournisseur ou le laboratoire doit prendre en charge la réclamation.";
                break;

            default:
                $titre = 'Demande de retour produit';
                $message
                    = "Si la raison du retour est éligible, l'équipe de VetZen se chargera d'effectuer le remboursement du ou des produits retourné(s) à la centrale directement sur la carte bancaire du client.";
        }
        /*
                TODO : Activer la sécurité sur les retour commande
                $clinique = Clinique::getCliniqueByCarrierId((int) $order->id_carrier);

                if ((int) $clinique->id_employee !== (int) $accessToken->id_employee) {
                    header('HTTP/1.0 403 Forbidden');
                    echo json_encode(
                        ['success' => false, 'message' => "Vous n'êtes pas autorisé à créer un retour pour cette commande"]
                    );

                    exit();
                }
        */
        // Vérifie qu'un retour ne soit pas déjà en cours pour cette commande
        $idOrderReturn = Db::getInstance()
            ->getValue('SELECT `id_order_return` FROM `ps_order_return` WHERE `id_customer` = ' . (int) $order->id_customer . ' AND `id_order` = ' . (int) $order->id . ' AND `state` IN (1,2)');

        if ($idOrderReturn) {
            \header('HTTP/1.0 400 Bad Request');
            echo \json_encode(
                ['success' => false, 'message' => 'Un retour est déjà en cours pour cette commande']
            );

            exit;
        }

        $employee = new Employee($accessToken->id_employee);
        $clinique = $this->getCliniqueByAccessToken($accessToken);
        $supplier = null;
        switch ($clinique->centrale) {
            case 'centravet':
                // @phpstan-ignore-next-line
                $supplier = new Supplier(1);
                break;

            case 'alcyon':
                // @phpstan-ignore-next-line
                $supplier = new Supplier(2);
                break;

            case 'coveto':
                // @phpstan-ignore-next-line
                $supplier = new Supplier(3);
                break;
        }

        if (!$supplier) {
            \header('HTTP/1.0 500 Internal Server Error');
            echo \json_encode(
                [
                    'success' => true,
                    'message' => 'Erreur serveur lors de la récupération de la centrale.'
                        . " Contactez l'équipe pour obtenir de l'aide !",
                ]
            );

            // TODO : Mail automatique à l'équipe pour indiquer le bug
            return;
        }

        // / Génération des références de retour
        $total_retour = 0;
        $returns = [];
        foreach ($order->getOrderDetailList() as $orderDetail) {
            if (isset($_POST['return_quantity'][$orderDetail['id_order_detail']])) {
                $qty = $_POST['return_quantity'][$orderDetail['id_order_detail']];

                $ref = Db::getInstance(false)->getValue(
                    'SELECT `product_supplier_reference`'
                    . ' FROM `' . _DB_PREFIX_ . 'product_supplier`'
                    . ' WHERE `id_product` = ' . (int) $orderDetail['product_id']
                    . ' AND `id_product_attribute` = ' . (int) $orderDetail['product_attribute_id']
                    . ' AND `id_supplier` = ' . (int) $supplier->id
                );

                $returns[$ref] = [
                    'name' => $orderDetail['product_name'],
                    'quantity' => $qty,
                    'id_order_detail' => $orderDetail['id_order_detail'],
                ];
                $total_retour += $qty;
            }
        }

        if (0 == $total_retour) {
            header('HTTP/1.0 400 Bad Request');
            echo json_encode(
                ['success' => false, 'message' => 'Veuillez indiquer le nombre de produits à retourner']
            );

            return;
        }

        $references = [];
        foreach ($returns as $ref => $infos) {
            $references[] = $ref . ' x' . $infos['quantity'] . ' (' . $infos['name'] . ')';
        }
        $references = \nl2br(\implode("\r\n", $references));

        $emails = [
            $employee->email => ['name' => $employee->firstname . ' ' . $employee->lastname, 'titre' => 'Demande de retour produit'],
            'sav@vetinweb.com' => ['name' => 'SAV VetInWeb', 'titre' => 'Demande de retour produit'],
        ];
        $centrale_email = '';

        switch ($clinique->centrale) {
            case 'alcyon':
                $centrale_email = 'relationboutique.alcyon@alcyon.com';
                $emails['relationboutique.alcyon@alcyon.com'] = ['name' => 'Retour Alcyon', 'titre' => $titre];
                break;

            case 'centravet':
                $centrale_email = 'saveboutique@centravet.fr';
                $emails['saveboutique@centravet.fr'] = ['name' => 'Retour Centravet', 'titre' => $titre];
                break;

            case 'coveto':
                $centrale_email = 'commandecolisage@coveto.fr';
                $emails['commandecolisage@coveto.fr'] = ['name' => 'Retour CoVeto', 'titre' => $titre];
                break;
        }

        foreach ($emails as $email => $infos) {
            $templateVars = [
                '{clinique_name}' => $employee->firstname . ' ' . $employee->lastname,
                '{clinique_email}' => $employee->email,
                '{clinique_centrale}' => $clinique->centrale,
                '{clinique_code_client}' => $clinique->code_client,
                '{clinique_code_filiere}' => $clinique->code_filiere,
                '{clinique_centrale_email}' => $centrale_email,
                '{clinique_centrale_name}' => $emails[$centrale_email]['name'],
                '{commande}' => $order->id . ' (' . $order->invoice_date . ')',
                '{references}' => $references,
                '{raison}' => $_POST['raison'],
                '{informations}' => $_POST['informations'],
                '{message}' => $message,
            ];

            $titre = $infos['titre'];
            $name = $infos['name'];

            Mail::Send(
                $context->language->id,
                'app-retour-produit',
                $titre,
                $templateVars, /* @phpstan-ignore-line */
                $email,
                $name,
                null,
                'MyVetShop',
                null,
                null,
                _PS_MAIL_DIR_,
                false,
                null,
                null,
                'sav@vetinweb.com'
            );
        }

        $contacts = \array_filter(
            Contact::getContacts(1),
            fn ($contact) => \str_contains($contact['email'], 'sav@vetinweb.com')
        );

        $contact = \reset($contacts);
        if ($contact) {
            $contact = new Contact($contact['id_contact']);
        } else {
            $contact = new Contact(1);
        }

        // / Création du message SAV
        $thread = new CustomerThread();
        $thread->id_shop = $order->id_shop;
        $thread->id_lang = 1;
        $thread->id_customer = $order->id_customer;
        $thread->id_order = $order->id;
        $thread->id_product = 0;
        $thread->status = 'open';
        $thread->id_contact = $contact->id;
        $thread->email = $contact->email;
        $thread->token = Tools::passwdGen(12);

        // Ajoute le nouveau message SAV
        $thread->add();

        $message = new CustomerMessage();
        $message->id_customer_thread = (int) $thread->id;
        $message->id_employee = 0;
        $message->message = 'Votre clinique ' . $employee->firstname . ' ' . $employee->lastname
            . ' a fait une demande de service après-vente pour votre commande ' . $order->id . ' du ' . $order->date_add . "\n"
            . 'Raison indiquée : ' . $_POST['raison'] . "\n\n";

        switch ($_POST['raison']) {
            case 'Erreur de commande client':
            case 'Animal décédé':
                $message->message .= "Après réception au dépôt du ou des produits retournés, l'équipe MyVetshop se chargera d'effectuer le remboursement des produits éligibles directement sur votre carte bancaire. L'équipe MyVetshop reste à votre disposition pour toute information complémentaire.";
                break;

            case 'Erreur de livraison centrale':
            case 'Produit défectueux ou non conforme':
                $message->message .= 'Votre clinique vous tiendra informée de la réception du ou des nouveaux produits éligibles à un échange. Nous vous remercions de votre compréhension et votre clinique reste à votre disposition pour toute information complémentaire.';
                break;

            default:
                $message->message .= "L'équipe MyVetshop et votre clinique sont à votre disposition pour toute information complémentaire.";
        }
        $message->message = \htmlspecialchars($message->message);

        $message->ip_address = \strval(ip2long(Tools::getRemoteAddr()) ?: 0);
        $message->user_agent = $_SERVER['HTTP_USER_AGENT'];

        $message->add();

        // Ajout de la demande de retour produit dans PrestaShop
        $orderReturn = new OrderReturn();
        $orderReturn->id_customer = $order->id_customer;
        $orderReturn->id_order = (int) $order->id;
        $orderReturn->question = $message->message
            . "\n\n" . \htmlspecialchars('Informations données par la clinique : ' . $_POST['informations']);
        switch ($_POST['raison']) {
            case 'Erreur de commande client':
            case 'Animal décédé':
            case 'Erreur de livraison centrale':
            case 'Produit défectueux ou non conforme':
                $orderReturn->state = 2;
                break;

            default:
                $orderReturn->state = 1;
        }
        $orderReturn->add();

        $returnIdOrderDetails = [];
        $returnQuantities = [];

        foreach ($returns as $return) {
            $returnIdOrderDetails[] = $return['id_order_detail'];
            $returnQuantities[] = $return['quantity'];
        }

        $orderReturn->addReturnDetail($returnIdOrderDetails, $returnQuantities, null, null);

        // / Message de retour pour l'application mobile
        switch ($_POST['raison']) {
            case 'Erreur de commande client':
            case 'Animal décédé':
                $retMessage
                    = "VetZen et votre centrale ont été informés du retour produit. Remettez le colis avec le ou les produits à retourner au prochain passage centrale. Vous pouvez informer votre client qu'il sera remboursé directement sur sa carte bancaire dès réception des produits.";
                break;

            case 'Erreur de livraison centrale':
            case 'Produit défectueux ou non conforme':
                $retMessage
                    = "VetZen et votre centrale ont été informés. Dans le cas d'un problème de conditionnement (exemple : sac abimé à la livraison), la centrale devra prendre en charge l'échange du produit. Dans le cas d'un problème qualité sur le produit, veuillez prendre contact avec le fournisseur ou le laboratoire responsable.";
                break;

            default:
                $retMessage
                    = "VetZen et votre centrale ont été informés du retour produit. Uniquement si la raison du retour est éligible, remettez le colis avec le ou les produits à retourner au prochain passage centrale. Pour plus d'informations, contactez le SAV MyVetshop (sav@myvetshop.fr).";
        }

        echo \json_encode(
            [
                'success' => true,
                'message' => $retMessage,
            ]
        );
        exit;
    }

    /**
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    protected function processPostContactVetzen(OAuthAccessToken $accessToken): void
    {
        if (!isset($_POST['email']) || empty($_POST['email'])) {
            echo \json_encode(['success' => false, 'message' => 'Le champ email doit être rempli']);
            exit;
        }
        if (!isset($_POST['clinique']) || empty($_POST['clinique'])) {
            echo \json_encode(['success' => false, 'message' => 'Le champ clinique doit être rempli']);
            exit;
        }
        if (!isset($_POST['prenom']) || empty($_POST['prenom'])) {
            echo \json_encode(['success' => false, 'message' => 'Le champ prénom doit être rempli']);
            exit;
        }
        if (!isset($_POST['nom']) || empty($_POST['nom'])) {
            echo \json_encode(['success' => false, 'message' => 'Le champ nom doit être rempli']);
            exit;
        }
        if (!isset($_POST['message']) || empty($_POST['message'])) {
            echo \json_encode(['success' => false, 'message' => 'Le champ message doit être rempli']);
            exit;
        }

        $employee = new Employee($accessToken->id_employee);

        $emails = [$employee->email => $employee->firstname . ' ' . $employee->lastname, 'sav@vetinweb.com' => 'SAV VetInWeb'];
        $emails[$_POST['email']] = $_POST['clinique'];

        foreach ($emails as $email => $name) {
            $templateVars = [
                '{clinique_name}' => $employee->firstname . ' ' . $employee->lastname,
                '{clinique_email}' => $employee->email,
                '{raison}' => $_POST['raison'],
                '{clinique}' => $_POST['clinique'],
                '{nom}' => $_POST['nom'],
                '{prenom}' => $_POST['prenom'],
                '{email}' => $_POST['email'],
                '{message}' => $_POST['message'],
            ];

            $context = Context::getContext();
            \assert(null !== $context);

            Mail::Send(
                $context->language->id,
                'app-contact',
                'Contact VetZen',
                $templateVars, /* @phpstan-ignore-line */
                (string) $email,
                $name,
                null,
                'MyVetShop'
            );
        }

        echo \json_encode([
            'success' => true,
            'message' => 'Votre message a bien été envoyé et votre clinique a été mise en copie.',
        ]);
        exit;
    }

    /**
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    public function init(): void
    {
        $headers = \getallheaders();
        \header('Content-Type: application/json');
        $headerKey = isset($headers['Authorization']) ? 'Authorization' : 'authorization';

        if (!$this->context->employee) {
            throw new Exception();
        }

        if (!isset($headers[$headerKey]) || 0 !== \strpos($headers[$headerKey], 'Bearer ')) {
            $do403 = true;
            if ($this->context->employee->id) {
                $token = OAuthAccessToken::getOneActiveTokenForEmployee($this->context->employee->id);

                if ($token) {
                    $headers[$headerKey] = 'Bearer ' . $token->token;
                    $do403 = false;
                }
            }

            if ($do403) {
                \header('HTTP/1.0 403 Forbidden');
                echo \json_encode(['error' => 'No authorization']);
                exit;
            }
        }

        try {
            $token = \trim(\str_replace('Bearer ', '', $headers[$headerKey]));
            $accessToken = OAuthAccessToken::getByToken($token);
        } catch (PrestaShopDatabaseException $e) {
            $accessToken = null;
        } catch (PrestaShopException $e) {
            $accessToken = null;
        }

        if (!$accessToken) {
            \header('HTTP/1.0 403 Forbidden');
            echo \json_encode(['error' => 'Non-existant token']);
            exit;
        }

        if ($accessToken->expires < \time()) {
            \header('HTTP/1.0 403 Forbidden');
            echo \json_encode(['error' => 'Expired token']);
            exit;
        }

        $accessToken->last_used = \time();
        $accessToken->update();

        switch ($_SERVER['REQUEST_METHOD']) {
            case 'GET':
                $this->processGet($accessToken);
                break;

            case 'POST':
                $this->processPost($accessToken);
                break;
        }

        exit;
    }
}
