<?php 

namespace PrestaShop\Module\PolarisPrestaConnector\Controller;

use PolarisPrestaConnector;
use Symfony\Component\HttpFoundation\Request;
use PrestaShop\Module\PolarisPrestaConnector\SyncConfiguration;
use Symfony\Component\HttpFoundation\JsonResponse;

class VatReportAdminController extends ConfigurationAdminController
{
    /**
     * Limite de CA pour le mode TVA simplifié de l'UE
     */
    const EU_VAT_LIMIT = 10000;

    /**
     * On enrechit la configuration de la barre d'outils
     * 
     * @return array
     */
    protected function getAdminLayoutToolBar() : array 
    {
        return [];
    }

    /**
     * Obtient l'id_tax_rules_group principalement utilisé sur ce shop
     * 
     * @return int
     */
    public static function getMainTaxRulesGroupId() : int
    {
        $db = \Db::getInstance();
        $query = @"SELECT id_tax_rules_group
                    FROM `" . _DB_PREFIX_ . "product` 
                    WHERE active = 1
                    GROUP BY id_tax_rules_group
                    ORDER BY COUNT(*) DESC";
        $result = $db->getRow($query);
        if ($result === FALSE && $db->getMsgError())
            throw new \Exception('Erreur à la détermination de la règle de taxes utilisée : '. $db->getMsgError());

        return (int) $result["id_tax_rules_group"];
    }


    /**
     * Contrôle de la TVA.
     * Si le chiffre d'affaires des 12 derniers mois est > 10000€ et que les taux sont de 20% partout dans la TVA 20%, 
     * alors on passe la boutique en mode alerte !
     */
    public static function ControlVat()
    {
        // On demande le rapport pour les 12 derniers mois
        $begin = new \DateTime('-12 months');
        $end = new \DateTime();
        $report = self::ComputeVatReport($begin, $end);

        $alert = false;

        $total = 0;
        $countries = [];
        foreach ($report as $vat)
            foreach ($vat as $values)                
            {
                $countries[$values["country"]] = true;
                $total += $values["volume"];
            }

        if (count($countries) > 1 && $total > self::EU_VAT_LIMIT)
        {
            // Potentiellement !
            // On regarde le groupe de taxes (id_tax_rules_group) le plus utilisé sur les produits (ps_product)
            $id_tax_rules_group = self::getMainTaxRulesGroupId();
            if ($id_tax_rules_group)
            {
                // Chargement du groupe de taxe $id_tax_rules_group
                $taxes = \TaxRule::getTaxRulesByGroupId((int)  \Context::getContext()->language->id, $id_tax_rules_group);
                $same = true;
                $last = -1;
                foreach ($taxes as $tax)
                {                    
                    if ($last === -1)
                        $last = $tax["rate"];
                    else if ($last !== $tax["rate"])
                    {
                        // On a trouvé un taux différent, on sort
                        $same = false;
                        break;
                    }
                }

                $alert = $same;                
            }
        }

        \Configuration::updateValue('EU_VAT_ALERT', $alert);
    }

    /**
     * Calcul et retourne le rapport de TVA au format :
     * [ 
     *  "country" => "France", 
     *  "rate" => "20.00",
     *  "orders" => 100,
     *  "volume" => 10000,
     *  "amount" => 1234,
     * ] pour chaque marketplace
     * 
     */
    public static function ComputeVatReport(\DateTime $begin, \DateTime $end) : array 
    {
        /** @var PolarisPrestaConnector $module */
        $module = \Module::getInstanceByName(strtolower('PolarisPrestaConnector'));

        $id_lang = (int)  \Context::getContext()->language->id;
        $db = \Db::getInstance();
        $query = @"SELECT 
                    cu.email AS email,
                    c.name AS country,
                    od.tax_rate AS rate,
                    od.total_price_tax_incl / o.conversion_rate AS volume_t_incl, 
                    od.total_price_tax_excl / o.conversion_rate AS volume_t_excl, 
                    ((od.total_price_tax_incl - od.total_price_tax_excl) - (od.total_refunded_tax_incl - od.total_refunded_tax_incl)) / o.conversion_rate AS vat
                FROM `" . _DB_PREFIX_ . "order_detail` AS od 
                LEFT JOIN `" . _DB_PREFIX_ . "orders` AS o ON (o.id_order = od.id_order)
                LEFT JOIN `" . _DB_PREFIX_ . "address` AS a ON (a.id_address = o.id_address_delivery)
                LEFT JOIN `" . _DB_PREFIX_ . "customer` AS cu ON (cu.id_customer = o.id_customer)
                LEFT JOIN `" . _DB_PREFIX_ . "country_lang` AS c ON (c.id_country = a.id_country AND c.id_lang = ".$id_lang.")
                WHERE   
                    o.date_add BETWEEN '".$begin->format("Y-m-d H:i:s")."' AND '".$end->format("Y-m-d H:i:s")."' AND 
                    (o.invoice_number != 0 OR o.valid) AND 
                    od.total_price_tax_incl > 0 AND 
                    od.total_price_tax_excl > 0
                    ";
        
        $rows = $db->executeS($query);
        if ($rows === FALSE)
            throw new \Exception('Erreur à la lecture de la bdd : '. $db->getMsgError());        

        $result = [];
        foreach ($rows as $row)
        {
            $marketplace = $module->getBridge()->detectMarketplace($row["email"] ?? "") ?? "directes";

            if (!isset($result[$marketplace]))
                $result[$marketplace] = [];

            $rate = (float) $row["rate"] ?? 0;
            if (!$rate) // Humm, suspect, on recalcul le ratio
                $rate = round(($row["volume_t_incl"] - $row["volume_t_excl"]) / $row["volume_t_excl"], 3) * 100;

            $key = $row["country"].$rate;

            if (!isset($result[$marketplace][$key]))
                $result[$marketplace][$key] = [
                    "country" => $row["country"],
                    "rate" => $rate,
                    "orders" => 0,
                    "volume" => 0,
                    "amount" => 0,
                ];

            $result[$marketplace][$key]["orders"] += 1;
            $result[$marketplace][$key]["volume"] += $row["volume_t_incl"];
            $result[$marketplace][$key]["amount"] += $row["vat"];
        }

        // Construisons le résultat ...
        $report = [];

        foreach ($result as $marketplace => $data) {
            $report[$marketplace] = [];

            foreach ($data as $values)
                $report[$marketplace][] = $values;
        }

        return $report;
    }

    /**
     * Mappings produits
     */
    public function indexAction(Request $request)
    {
        if (isset($_REQUEST["settax"]) && $_REQUEST["settax"] == 1)
        {
            // On réinitialise les contrôles
            \Configuration::updateValue('EU_VAT_ALERT', false);            
            \Configuration::updateValue('EU_VAT_LAST_CHECKS', '2020-01-01');
            
            // On détermine l'id_tax_rules_group
            $id_tax_rules_group = self::getMainTaxRulesGroupId();

            // Et on redirige vers la configuration des taxes
            // Génération de l’URL Symfony
            $link = \Context::getContext()->link->getAdminLink(
                'AdminTaxRulesGroup',
                true, // with token
                [],   // pas de paramètres Symfony ici
                [ 'updatetax_rules_group' => '', 'id_tax_rules_group' => $id_tax_rules_group]
            );

            // Redirection HTTP
            \Tools::redirectAdmin($link);
            return;
        }

        // Par défaut, on prend le mois dernier, du premier au dernier jour
        $begin = new \DateTime(((isset($_REQUEST["begin"]) && !empty($_REQUEST["begin"])) ? $_REQUEST["begin"] : 'first day of last month') . ", 00:00");
        $end = new \DateTime(((isset($_REQUEST["end"]) && !empty($_REQUEST["end"])) ? $_REQUEST["end"] : 'last day of last month') . ", 23:59");        

        // Symbole de la monnaie principale. 
        // Récupération de l'ID de la devise par défaut
        $id_currency = (int) \Configuration::get('PS_CURRENCY_DEFAULT');

        // Chargement de l'objet Currency        
        $currency = new \Currency($id_currency);

        // Do ...        
        $report = [
            "begin" => $begin->format('Y-m-d'),
            "end" => $end->format('Y-m-d'),
            "money" => $currency->symbol,
            "vats" => self::ComputeVatReport($begin, $end)
        ];
        
        // Mode download ?
        if (isset($_REQUEST["download"]) && 
            isset($_REQUEST["marketplace"]) && 
            $_REQUEST["download"] === "yes")
        {            
            // Génération du fichier CSV
            $csv = "Country,Rate,Orders,Volume,Amount\n";
            if (isset($report["vats"][$_REQUEST["marketplace"]]))            
                foreach ($report["vats"][$_REQUEST["marketplace"]] as $vat) {
                    $csv .= sprintf("%s,%.2f,%d,%.2f,%.2f\n",
                        $vat["country"],
                        $vat["rate"],
                        $vat["orders"],
                        $vat["volume"],
                        $vat["amount"]
                    );
                }

            // Envoi du fichier CSV
            header('Content-Type: text/csv');
            header('Content-Disposition: attachment; filename="vat_report_' . 
                        preg_replace('/[^a-z0-9_]/', '', strtolower($_REQUEST["marketplace"])) . '_'.
                        $report["begin"] . '_' . $report["end"] . '.csv"');
            echo $csv;
            exit;
        }

        // On modifie le rapport pour le rendre plus présentable en supprimant la référence pays quand elle se répète
        $last = '';
        foreach (array_keys($report['vats']) as $marketplace)
        {
            for ($i = 0; $i < count($report['vats'][$marketplace]); $i++)
            {
                $country = $report['vats'][$marketplace][$i]['country'];
                if ($country === $last)
                {
                    // On supprime la référence pays
                    $report['vats'][$marketplace][$i]['country'] = '';
                }
                else
                {
                    // On garde la référence pays
                    $last = $country;
                }
            }
        }
        
        return $this->render('@Modules/' . $this->module->name . '/views/templates/admin/vat_report.html.twig', $this->addDefaultVars([
            'report' => $report,
            'backoffice' => $this->module->getBridge()->getId(),
        ]));
    }    
}