<?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);

        $clinique_id = Clinique::getCliniqueByEmployee($employee->id);

        return new Clinique($clinique_id);
    }

    /**
     * @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://' . Configuration::get('PS_SHOP_DOMAIN_SSL') . '/img/tmp/employee_' . (int) $employee->id . '.' . $this->imageType,
            'photo' => '',
            'theme' => '',
            'code_privilege' => '',
            'centrale' => 'centrale',
        ];

        /** @var int $clinique_id */
        $clinique_id = Clinique::getCliniqueByEmployee($employee->id);

        if ($clinique_id) {
            $clinique = new Clinique($clinique_id);
            // 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);

            $ret['photo'] = 'https://' . Configuration::get('PS_SHOP_DOMAIN_SSL') . '/img/tmp/store_' . (int) $clinique->id_store . '.' . $this->imageType;
            $ret['theme'] = $clinique->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':
                // TODO : Sera à supprimer dans une mise à jour future (le temps que tout le monde mette à jour son application)
                $this->processPostRetourProduit($accessToken);
                break;

            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 processPostRetourProduit(OAuthAccessToken $accessToken): void
    {
        if (!isset($_POST['commande']) || empty($_POST['commande'])) {
            echo json_encode(['success' => false, 'message' => 'Le numéro de commande doit être rempli']);
            exit();
        }
        if (!isset($_POST['references']) || empty($_POST['references'])) {
            echo json_encode(['success' => false, 'message' => 'La références des produits doit être indiquée']);
            exit();
        }

        $order = new Order($_POST['commande']);
        if (!$order->date_add) {
            echo json_encode(['success' => false, 'message' => "Le numéro de commande n'est pas valide"]);
            exit();
        }

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

        $emails = [
            $employee->email => $employee->firstname . ' ' . $employee->lastname,
            'cabayot@vetzen.fr' => 'Virginie Cabayot',
            'pieron@vetzen.fr' => 'David PIERON',
            'paulin@vetzen.fr' => 'Sandrine PAULIN',
        ];
        $centrale_email = '';

        switch ($clinique->centrale) {
            case 'alcyon':
                $centrale_email = 'm.nowe@alcyon.com';
                $emails['m.nowe@alcyon.com'] = 'Maïté NOWE';
                break;

            case 'centravet':
                $centrale_email = 'mjromanoni@centravet.fr';
                $emails['mjromanoni@centravet.fr'] = 'Marie-José ROMANONI';
                break;

            case 'coveto':
                $centrale_email = 'commandecolisage@coveto.fr';
                $emails['commandecolisage@coveto.fr'] = 'Retour CoVeto';
                break;

            case 'hippocampe':
                $centrale_email = 'conseilleres@hippocampe-sa.com';
                $emails['conseilleres@hippocampe-sa.com'] = 'Retour Hippocampe';
                break;
        }

        // Ajoute l'e-mail en copie
        $emails[$centrale_email] = ucfirst($clinique->centrale);

        foreach ($emails as $email => $name) {
            $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],
                '{commande}' => $_POST['commande'],
                '{references}' => $_POST['references'],
                '{raison}' => $_POST['raison'],
                '{remboursement}' => $_POST['remboursement'],
                '{informations}' => $_POST['informations'],
            ];

            Mail::Send(
                Context::getContext()->language->id,
                'app-retour-produit',
                'Demande de retour produit',
               $templateVars, /* @phpstan-ignore-line Erreur typage code source prestashop */
                $email,
                $name,
                null,
                'MyVetShop'
            );
        }

        echo json_encode(
            ['success' => true,
                'message' => 'VetZen et votre centrale ont été informés du retour produit. Votre centrale émettra un bon de retour sous 48h et vous pourrez remettre le colis avec le ou les produits à retourner au passage du livreur.', ]
        );
        exit();
    }

    /**
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    protected function processPostRetourProduitNew(OAuthAccessToken $accessToken): void
    {
        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(intval($_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 : Vérifier le droit d'accès pour le retour commande. L'employé peut-il effectuer un retour sur cette commande ?
        // TODO : Vérifier qu'un retour n'est pas déjà en cours pour cette commande

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

            case 'alcyon':
                $supplier = new Supplier(2);
                break;

            case 'coveto':
                $supplier = new Supplier(3);
                break;

            case 'hippocampe':
                $supplier = new Supplier(4);
                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'],
            'cabayot@vetzen.fr' => ['name' => 'Virginie Cabayot', 'titre' => 'Demande de retour produit'],
            'pieron@vetzen.fr' => ['name' => 'David PIERON', 'titre' => 'Demande de retour produit'],
            'paulin@vetzen.fr' => ['name' => 'Sandrine PAULIN', 'titre' => 'Demande de retour produit'],
        ];
        $centrale_email = '';

        switch ($clinique->centrale) {
            case 'alcyon':
                $centrale_email = 'm.nowe@alcyon.com';
                $emails['m.nowe@alcyon.com'] = ['name' => 'Maïté NOWE', 'titre' => $titre];
                break;

            case 'centravet':
                $centrale_email = 'mjromanoni@centravet.fr';
                $emails['mjromanoni@centravet.fr'] = ['name' => 'Marie-José ROMANONI', '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],
                '{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::getContext()->language->id,
                'app-retour-produit',
                $titre,
                $templateVars, /* @phpstan-ignore-line */
                $email,
                $name,
                null,
                'MyVetShop',
                null,
                null,
                _PS_MAIL_DIR_,
                false,
                null,
                null,
                'cabayot@vetzen.fr'
            );
        }

        $contacts = array_filter(
            Contact::getContacts(1),
            function ($contact) {
                return false !== strpos($contact['email'], 'sav@myvetshop.fr');
            }
        );

        $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 = $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 = (int) ip2long(Tools::getRemoteAddr());
        $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 = $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, 'contact@vetzen.fr' => 'VetZen', 'pieron@vetzen.fr' => 'David PIERON'];
        $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'],
            ];

            Mail::Send(
                Context::getContext()->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 (!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();
    }
}
