<?php

namespace Modules\Evaluation\Repository\Import;

use Helpers\QueryBuilder\AbsRepository;
use PDO;

class ImportInfo extends AbsRepository
{
    /**
     * @var resource $pdoStorage
     */
    private $pdoStorage;

    /**
     * __construct
     *
     * @param  \PDO $pdo
     * @param  resource $pdoStorage
     */
    public function __construct(PDO $pdo, $pdoStorage)
    {
        parent::__construct($pdo);
        $this->pdoStorage = $pdoStorage;
    }
    
    /**
     * importRaters
     *
     * @param  int $campaignId
     * @param  array<mixed> $raters
     * @param  string $type
     * @return array<mixed>
     */
    public function importRaters(int $campaignId, array $raters, string $type): array
    {
        switch ($type) {
            case 'raters':
                return $this->importCampaignRaters($campaignId, $raters);
            
            case 'groups':
                return $this->importGroupsRaters($campaignId, $raters);
            
            case 'suppliers':
                return $this->importSuppliersRaters($campaignId, $raters);
            
            default:
                return [];
        }
    }
    
    
    /**
     * importCampaignRaters
     *
     * @param  int $campaignId
     * @param  array<mixed> $raters
     * @return array<mixed>
     */
    public function importCampaignRaters(int $campaignId, array $raters): array
    {
        // on crée la table temporaire qui nous permettra de faire les contrôles sur l'insert initial
        $query = "SELECT ID_CAMP, NOTEUR, '' AS STATUT
                    INTO #CAMP_LST_NOT_CAMP
                FROM CAMP_LST_NOT_CAMP WITH(NOLOCK)
                WHERE ID_CAMP = 0; ";

        // on réalise un premier insert dans la table temporaire
        $query .= "INSERT INTO #CAMP_LST_NOT_CAMP (ID_CAMP, NOTEUR, STATUT)
        VALUES ";

        foreach ($raters as $rater) {
            $query .= '(' . $campaignId . ', \'' . $rater . '\', \'\'), ';
        }
        $query = \rtrim($query, ', ');

        // on update la table temporaire avec le champ 'statut' pour organiser les résultats
        $query .= "UPDATE T
                SET T.STATUT = 
                    CASE 
                        WHEN ISNULL (F.CODE, '') = ''
                        THEN 'E'
                        WHEN ISNULL (C.NOTEUR, '') = ''
                        THEN 'O'
                        ELSE 'D' 
                    END
                FROM #CAMP_LST_NOT_CAMP T
                    LEFT OUTER JOIN HASTUTIL F ON F.CODE = T.NOTEUR AND F.NOTEUR = 0x54
                    LEFT OUTER JOIN CAMP_LST_NOT_CAMP C ON C.ID_CAMP = $campaignId AND C.NOTEUR = T.NOTEUR;";

        // on insère les fournisseurs vérifiés et non-doublons dans la liste des fournisseurs de la campagne
        $query .= "INSERT INTO CAMP_LST_NOT_CAMP (ID_CAMP, NOTEUR)
                SELECT ID_CAMP, NOTEUR FROM #CAMP_LST_NOT_CAMP T WHERE T.STATUT = 'O';";

        // on exécute la requête en connexion persistante
        $stmt = sqlsrv_query($this->pdoStorage, $query);

        // on récupère le compte de fournisseurs importés et insérés
        $query = "SELECT COUNT(*) AS count FROM #CAMP_LST_NOT_CAMP T WITH(NOLOCK) WHERE T.STATUT = 'O';";

        $stmt = sqlsrv_query($this->pdoStorage, $query);
        /** @phpstan-ignore-next-line */
        while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
            $count = $row['count'];
        }

        // on récupère la liste des fournisseurs inexistants
        $query = "SELECT T.NOTEUR,
                    CASE 
						WHEN F.NOM IS NULL
						THEN 'Code inexistant'
						ELSE F.NOM
					END AS NOM 
                FROM #CAMP_LST_NOT_CAMP T WITH(NOLOCK)
                    LEFT JOIN HASTUTIL F WITH(NOLOCK) ON T.NOTEUR = F.CODE
                WHERE T.STATUT = 'E'";

        $stmt = sqlsrv_query($this->pdoStorage, $query);
        /** @phpstan-ignore-next-line */
        while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
            $missingRaters[$row['NOTEUR']] = $row['NOM'];
        }

        // on récupère la liste des fournisseurs qui étaient déjà enregistrés dans la campagne
        $query = "SELECT T.NOTEUR, F.NOM
                FROM #CAMP_LST_NOT_CAMP T WITH(NOLOCK)
                    LEFT JOIN HASTUTIL F WITH(NOLOCK) ON T.NOTEUR = F.CODE
                WHERE T.STATUT = 'D'";

        $stmt = sqlsrv_query($this->pdoStorage, $query);
        /** @phpstan-ignore-next-line */
        while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
            $alreadyRegisteredRaters[$row['NOTEUR']] = $row['NOM'];
        }

        return [
            'count' => $count ?? 0,
            'missingRaters' => $missingRaters ?? [],
            'alreadyRegisteredRaters' => $alreadyRegisteredRaters ?? [],
        ];
    }
    
    /**
     * importSuppliersRaters
     *
     * @param  int $campaignId
     * @param  array<mixed> $suppliers
     * @return array<mixed>
     */
    public function importSuppliersRaters(int $campaignId, array $suppliers): array
    {
        // on crée la table temporaire qui nous permettra de faire les contrôles sur l'insert initial
        $query = "SELECT ID_CAMP, CODE_FOU, NOTEUR, '' AS STATUT
                    INTO #CAMP_LST_NOT_FOUR
                FROM CAMP_LST_NOT_FOUR WITH(NOLOCK)
                WHERE ID_CAMP = 0; ";

        // on réalise un premier insert dans la table temporaire
        $query .= "INSERT INTO #CAMP_LST_NOT_FOUR (ID_CAMP, CODE_FOU, NOTEUR, STATUT)
        VALUES ";

        foreach ($suppliers as $supplier => $raters) {
            foreach ($raters as $rater) {
                $query .= '(' . $campaignId . ', \'' . $supplier . '\', \'' . $rater . '\', \'\'), ';
            }
        }
        $query = \rtrim($query, ', ');

        // on update la table temporaire avec le champ 'statut' pour organiser les résultats
        $query .= "UPDATE T
                SET T.STATUT = 
                    CASE 
                        WHEN ISNULL (F.CODE, '') = ''
                        THEN 'E'
                        WHEN ISNULL (CLF.CODE_FOU, '') = ''
                        THEN 'F'
                        WHEN ISNULL (C.NOTEUR, '') = ''
                        THEN 'O'
                        ELSE 'D' 
                    END
                FROM #CAMP_LST_NOT_FOUR T
                    LEFT OUTER JOIN HASTUTIL F ON F.CODE = T.NOTEUR AND F.NOTEUR = 0x54
                    LEFT OUTER JOIN CAMP_LST_FOUR CLF ON CLF.ID_CAMP = $campaignId AND CLF.CODE_FOU = T.CODE_FOU
                    LEFT OUTER JOIN CAMP_LST_NOT_FOUR C ON C.ID_CAMP = $campaignId AND C.CODE_FOU = T.CODE_FOU AND C.NOTEUR = T.NOTEUR;";

        // on insère les fournisseurs vérifiés et non-doublons dans la liste des fournisseurs de la campagne
        $query .= "INSERT INTO CAMP_LST_NOT_FOUR (ID_CAMP, CODE_FOU, NOTEUR)
                SELECT ID_CAMP, CODE_FOU, NOTEUR FROM #CAMP_LST_NOT_FOUR T WITH(NOLOCK) WHERE T.STATUT = 'O';";

        // on insère les évaluateurs vérifiés et non-doublons dans la liste des évaluateurs de la campagne
        $query .= "INSERT INTO CAMP_LST_NOT_CAMP (ID_CAMP, NOTEUR)
            SELECT DISTINCT ID_CAMP, NOTEUR 
            FROM CAMP_LST_NOT_FOUR WITH(NOLOCK)
            WHERE ID_CAMP = $campaignId AND NOT EXISTS (
                SELECT NOTEUR FROM CAMP_LST_NOT_CAMP WITH(NOLOCK) where ID_CAMP = $campaignId AND NOTEUR = CAMP_LST_NOT_FOUR.NOTEUR
            );";

        // on exécute la requête en connexion persistante
        $stmt = sqlsrv_query($this->pdoStorage, $query);

        // on récupère le compte de fournisseurs importés et insérés
        $query = "SELECT COUNT(*) AS count FROM #CAMP_LST_NOT_FOUR T WHERE T.STATUT = 'O';";

        $stmt = sqlsrv_query($this->pdoStorage, $query);

        /** @phpstan-ignore-next-line */
        while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
            $count = $row['count'];
        }

        // on récupère la liste des noteurs inexistants
        $query = "SELECT T.NOTEUR,
                    CASE 
						WHEN F.NOM IS NULL
						THEN 'Code inexistant'
						ELSE F.NOM
					END AS NOM 
                FROM #CAMP_LST_NOT_FOUR T WITH(NOLOCK)
                    LEFT JOIN HASTUTIL F WITH(NOLOCK) ON T.NOTEUR = F.CODE
                WHERE T.STATUT = 'E'";

        $stmt = sqlsrv_query($this->pdoStorage, $query);
        /** @phpstan-ignore-next-line */
        while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
            $missingRaters[$row['NOTEUR']] = $row['NOTEUR'];
        }

        // on récupère la liste des fournisseurs inexistants
        $query = "SELECT T.CODE_FOU,
                    CASE 
						WHEN CLF.CODE_FOU IS NULL
						THEN 'Code inexistant'
						ELSE CLF.CODE_FOU
					END AS NOM 
                FROM #CAMP_LST_NOT_FOUR T WITH(NOLOCK)
                    LEFT OUTER JOIN CAMP_LST_FOUR CLF WITH(NOLOCK) ON CLF.ID_CAMP = $campaignId AND CLF.CODE_FOU = T.CODE_FOU
                WHERE T.STATUT = 'F'";

        $stmt = sqlsrv_query($this->pdoStorage, $query);

        /** @phpstan-ignore-next-line */
        while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
            $missingSuppliers[$row['CODE_FOU']] = $row['CODE_FOU'];
        }

        // on récupère la liste des noteurs qui étaient déjà enregistrés dans la campagne
        $query = "SELECT T.NOTEUR, F.NOM
                FROM #CAMP_LST_NOT_FOUR T WITH(NOLOCK)
                    LEFT JOIN HASTUTIL F WITH(NOLOCK) ON T.NOTEUR = F.CODE
                WHERE T.STATUT = 'D'";

        $stmt = sqlsrv_query($this->pdoStorage, $query);
        /** @phpstan-ignore-next-line */
        while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
            $alreadyRegisteredRaters[$row['NOTEUR']] = $row['NOTEUR'];
        }

        return [
            'count' => $count ?? 0,
            'missingRaters' => $missingRaters ?? [],
            'missingSuppliers' => $missingSuppliers ?? [],
            'alreadyRegisteredRaters' => $alreadyRegisteredRaters ?? [],
        ];
    }
    
    /**
     * importGroupsRaters
     *
     * @param  int $campaignId
     * @param  array<mixed> $groups
     * @return array<mixed>
     */
    public function importGroupsRaters(int $campaignId, array $groups): array
    {
        // on crée la table temporaire qui nous permettra de faire les contrôles sur l'insert initial
        $query = "SELECT ID_CAMP, GROUPE, NOTEUR, '' AS STATUT
                    INTO #CAMP_LST_NOT_GRP
                FROM CAMP_LST_NOT_GRP
                WHERE ID_CAMP = 0; ";

        // on réalise un premier insert dans la table temporaire
        $query .= "INSERT INTO #CAMP_LST_NOT_GRP (ID_CAMP, GROUPE, NOTEUR, STATUT)
        VALUES ";

        foreach ($groups as $group => $raters) {
            foreach ($raters as $rater) {
                $query .= '(' . $campaignId . ', \'' . $group . '\', \'' . $rater . '\', \'\'), ';
            }
        }
        $query = \rtrim($query, ', ');

        // on update la table temporaire avec le champ 'statut' pour organiser les résultats
        $query .= "UPDATE T
                SET T.STATUT = 
                    CASE 
                        WHEN ISNULL (F.CODE, '') = ''
                        THEN 'E'
                        WHEN ISNULL (CGN.GROUPE, '') = ''
                        THEN 'F'
                        WHEN ISNULL (C.NOTEUR, '') = ''
                        THEN 'O'
                        ELSE 'D' 
                    END
                FROM #CAMP_LST_NOT_GRP T
                    LEFT OUTER JOIN HASTUTIL F ON F.CODE = T.NOTEUR AND F.NOTEUR = 0x54
                    LEFT OUTER JOIN CAMP_GRP_NOT CGN ON CGN.ID_CAMP = $campaignId AND CGN.GROUPE = T.GROUPE
                    LEFT OUTER JOIN CAMP_LST_NOT_GRP C ON C.ID_CAMP = $campaignId AND C.GROUPE = T.GROUPE AND C.NOTEUR = T.NOTEUR;";

        // on insère les fournisseurs vérifiés et non-doublons dans la liste des fournisseurs de la campagne
        $query .= "INSERT INTO CAMP_LST_NOT_GRP (ID_CAMP, GROUPE, NOTEUR)
                SELECT ID_CAMP, GROUPE, NOTEUR FROM #CAMP_LST_NOT_GRP T WHERE T.STATUT = 'O';";

        // on insère les évaluateurs vérifiés et non-doublons dans la liste des évaluateurs de la campagne
        $query .= "INSERT INTO CAMP_LST_NOT_CAMP (ID_CAMP, NOTEUR)
            SELECT DISTINCT ID_CAMP, NOTEUR 
            FROM CAMP_LST_NOT_GRP 
            WHERE ID_CAMP = $campaignId AND NOT EXISTS (
                SELECT NOTEUR FROM CAMP_LST_NOT_CAMP where ID_CAMP = $campaignId AND NOTEUR = CAMP_LST_NOT_GRP.NOTEUR
            );";

        // on exécute la requête en connexion persistante
        $stmt = sqlsrv_query($this->pdoStorage, $query);

        // on récupère le compte de fournisseurs importés et insérés
        $query = "SELECT COUNT(*) AS count FROM #CAMP_LST_NOT_GRP T WHERE T.STATUT = 'O';";

        $stmt = sqlsrv_query($this->pdoStorage, $query);

        /** @phpstan-ignore-next-line */
        while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
            $count = $row['count'];
        }

        // on récupère la liste des noteurs inexistants
        $query = "SELECT T.NOTEUR,
                    CASE 
						WHEN F.NOM IS NULL
						THEN 'Code inexistant'
						ELSE F.NOM
					END AS NOM 
                FROM #CAMP_LST_NOT_GRP T 
                    LEFT JOIN HASTUTIL F ON T.NOTEUR = F.CODE
                WHERE T.STATUT = 'E'";

        $stmt = sqlsrv_query($this->pdoStorage, $query);
        /** @phpstan-ignore-next-line */
        while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
            $missingRaters[$row['NOTEUR']] = $row['NOTEUR'];
        }

        // on récupère la liste des fournisseurs inexistants
        $query = "SELECT T.GROUPE,
                    CASE 
						WHEN CGN.GROUPE IS NULL
						THEN 'Code inexistant'
						ELSE CGN.GROUPE
					END AS NOM 
                FROM #CAMP_LST_NOT_GRP T 
                    LEFT OUTER JOIN CAMP_GRP_NOT CGN ON CGN.ID_CAMP = $campaignId AND CGN.GROUPE = T.GROUPE
                WHERE T.STATUT = 'F'";

        $stmt = sqlsrv_query($this->pdoStorage, $query);

        /** @phpstan-ignore-next-line */
        while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
            $missingGroups[$row['GROUPE']] = $row['GROUPE'];
        }

        // on récupère la liste des noteurs qui étaient déjà enregistrés dans la campagne
        $query = "SELECT T.NOTEUR, F.NOM
                FROM #CAMP_LST_NOT_GRP T 
                    LEFT JOIN HASTUTIL F ON T.NOTEUR = F.CODE
                WHERE T.STATUT = 'D'";

        $stmt = sqlsrv_query($this->pdoStorage, $query);
        /** @phpstan-ignore-next-line */
        while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
            $alreadyRegisteredRaters[$row['NOTEUR']] = $row['NOTEUR'];
        }

        return [
            'count' => $count ?? 0,
            'missingRaters' => $missingRaters ?? [],
            'missingGroups' => $missingGroups ?? [],
            'alreadyRegisteredRaters' => $alreadyRegisteredRaters ?? [],
        ];
    }
}
