<?php

namespace Modules\API\APIInterne\OxaMobility\Outil;

class StockInventaire
{
    const COLUMN_BY_LIST_TYPE = [
        'BE' => [
            'NUM_DOC',
            'DTE_CREAT',
            'DTE_VALID',
            'MAG',
            'NOM_MAG',
            'SITE',
            'NOM_SITE',
            'ORIGINE',
            'TIERS',
            'TYPE_BE'
        ],
        'BS' => [
            'NUM_DOC',
            'DTE_CREAT',
            'DTE_VALID',
            'MAG',
            'NOM_MAG',
            'SITE',
            'NOM_SITE',
            'ORIGINE',
            'TIERS',
        ],
        'BT' => [
            'NUM_DOC',
            'DTE_CREAT',
            'DTE_VALID',
            'MAG',
            'NOM_MAG',
            'SITE',
            'NOM_SITE',
            'SITE_DEST',
            'NOM_SITE_DEST',
        ],
    ];

    /** @var \PDO $pdo */
    private \PDO $pdo;

    /**
     * @param \PDO $pdo
     */
    public function __construct($pdo)
    {
        $this->pdo = $pdo;
    }

    /**
     * Liste des Inventaires à réaliser,
     * pour l'utilisateur et la société précisés :
     * - les critères d'inventaires sont validés (DTE_PRET)
     * - les mouvements sont arrêtés (MVT_BLOQ)
     * - l'inventaire concerne le site de stock précisé (mais il peut être multi-sites)
     *
     * @param string $codeUser
     * @param string $codeSoc
     * @param string $codeSite
     * @param int $page
     * @return array<mixed>|false
     */
    public function getInventory($codeUser, $codeSoc, $codeSite, $page)
    {
        $stmt = "
            DECLARE
                @v_Utilisateur				varchar(30)		= :codeUser,
                @v_CodeSoc					varchar(7)		= :codeSoc,
                @v_CodeSite					varchar(7)		= :codeSite
            ;
            
            SELECT
                inv.NO_INV, inv.DESIGN, inv.DTE_CREAT, inv.DTE_PRET,
                ISNULL(rtrim(m.CONTMEMO),'') AS DESCR,
                ISNULL((SELECT count(*) FROM SCIINVLI lig WITH(nolock) WHERE lig.NO_INV = inv.NO_INV AND lig.SITE = site.SITE),0) AS NB_ART
            FROM
                SINVENTA inv WITH(nolock)
            INNER JOIN
                SCINVENT site WITH(nolock) ON site.NO_INV = inv.NO_INV AND site.SITE = @v_CodeSite
            LEFT OUTER JOIN
                MEMOS m WITH(nolock) ON m.NODEMEMO = inv.NM_DESCR
            WHERE
                inv.MAG = @v_Utilisateur
                AND inv.CODE_STE = @v_CodeSoc
                AND inv.DTE_PRET > '00000000'
                AND inv.MVT_BLOQ = 'O'
        ";

        $params = [
            'codeUser'  => $codeUser,
            'codeSoc'   => $codeSoc,
            'codeSite'  => $codeSite,
        ];

        $paginatorGestion = new \Helpers\Pagination\PaginatorGestion();
        $paginatorGestion->injecterSqlCount($stmt, [], $params, $this->pdo, true);

        $stmt .= " ORDER BY {$_SESSION['PaginatorGestion']['nomAttributOrder']}";
        $stmt .= " OFFSET (( {$page} - 1 ) * {$_SESSION['PaginatorGestion']['nbrArticleParPage']} ) ROWS
                   FETCH NEXT {$_SESSION['PaginatorGestion']['nbrArticleParPage']} ROWS ONLY";


        $query = $this->pdo->prepare($stmt);
        $query->execute($params);

        return $query->fetchAll($this->pdo::FETCH_ASSOC);
    }

    /**
     * Liste des Articles d'un inventaire
     * @param int $numInventory
     * @param string $codeSite
     * @return array<mixed>|false
     */
    public function getArticles($numInventory, $codeSite)
    {
        $stmtCheckInventory = "
            DECLARE
                @v_NumInv		int			= :numInventory
            ;
            
            SELECT
                1 as inventoryExist
            FROM
                SINVENTA WITH(nolock)
            WHERE
                NO_INV = @v_NumInv
        ";

        $paramsCheck = [
            'numInventory'  => $numInventory,
        ];
        $queryCheck = $this->pdo->prepare($stmtCheckInventory);
        $queryCheck->execute($paramsCheck);
        $checkInventory = $queryCheck->fetch($this->pdo::FETCH_ASSOC);

        if (!isset($checkInventory['inventoryExist'])) {
            return false;
        }

        $stmt = "
            DECLARE
                @v_NumInv		int			= :numInventory,
                @v_CodeSite		varchar(7)	= :codeSite
            ;

            SELECT
                CODE_ART AS CodeArt, QTE_THEO AS QteTheo, QTE_REEL AS QteReel, PU_EXECED as Prix
            FROM
                SCIINVLI WITH(nolock)
            WHERE
                NO_INV = @v_NumInv
                AND SITE = @v_CodeSite
        ";

        $params = [
            'numInventory'  => $numInventory,
            'codeSite'      => $codeSite
        ];

        $query = $this->pdo->prepare($stmt);
        $query->execute($params);

        return $query->fetchAll($this->pdo::FETCH_ASSOC);
    }

    /**
     * @param array<mixed> $return
     * @param array<mixed> $list
     * @param mixed $key
     * @return array<mixed>
     */
    public function buildListStocksDocs($return, $list, $key)
    {
        foreach ($list as $item) {
            $listName = str_replace('Liste', '', $item['LIST_TYPE'] ?? $key);

            $array = [];
            foreach (self::COLUMN_BY_LIST_TYPE[$listName] as $column) { //@phpstan-ignore-line
                $data = $item[$column];
                if ($column === 'NUM_DOC') {
                    $data = (int) $item[$column];
                }

                $array[$column] = $data;
            }
            $return[$item['LIST_TYPE'] ?? $key][] = $array;
        }

        return $return;
    }
}
