<?php

namespace Modules\Stock\Service\Export;

use Entity\Model\CsDon;
use Exception;
use Helpers\ChampsSupplementaire\ChampSupp;
use Helpers\Outil\Date;
use Helpers\Outil\Roles;
use Helpers\Outil\Sql;
use Helpers\Trad\ITrad;
use Modules\Stock\Service\ParametrageService;
use PDO;

abstract class AbstractExportService
{
    protected readonly ParametrageService $parametrageService;
    public function __construct(protected readonly PDO $pdo, protected readonly ITrad $trad)
    {
        $this->parametrageService = new ParametrageService($this->pdo);
    }


    /**
     * @return array<string,array<string,string>>
     */
    abstract public function getArchitecture(): array;


    /**
     * @param array<string,mixed> $post
     * @return array<string,string>
     */
    public function getArrayMultiSelect(array $post): array
    {
        return array_filter($post, function ($k) {
            return (bool) stristr($k, 'multiSelect');
        }, ARRAY_FILTER_USE_KEY);
    }


    /**
     * @param array<string,string> $arrayMultiSelect
     * @return array<int,string>
     */
    public function getListeCS(array &$arrayMultiSelect): array
    {
        $listeCS = [];
        foreach ($arrayMultiSelect as $key => &$multiSelect) {
            if (str_starts_with($multiSelect, 'CS_EXTENSION')) {
                $listeCS[] = substr($multiSelect, 12);
                unset($arrayMultiSelect[$key]);
            }
        }

        return $listeCS;
    }


    /**
     * @param array<string,string> $arrayMultiSelect
     * @param array<string,string> $listeCS
     * @return array<string,string>
     */
    public function getTableEntete(
        array $arrayMultiSelect,
        array &$listeCS,
        string $tableEntete,
        ?string $tableLign = null
    ): array {
        $entete = [];
        $architecture = $this->getArchitecture();
        foreach ($arrayMultiSelect as $colonne) {
            $entete[$colonne] = $architecture[$colonne]['nomChamp'];
        }

        $champSupp = new ChampSupp($this->pdo);
        foreach ($listeCS as &$cs) {
            $codeTab = str_contains($cs, $tableEntete) ? $tableEntete: $tableLign;
            $cs = $champSupp->getinfoOneCs($codeTab, str_replace($codeTab, '', $cs));
            $entete['CS_EXTENSION'.$codeTab.$cs['NUM_FIX']] = $this->trad->t($cs['NOM']);
        }

        return $entete;
    }


    /**
     * @param string $type
     * @return array<int,string>
     */
    public function getChampsParType(string $type): array
    {
        $champsDate = [];
        $architecture = $this->getArchitecture();
        foreach ($architecture as $champs => $data) {
            if ($data['type'] === $type) {
                $champsDate[] = $champs;
            }
        }

        return $champsDate;
    }


    /**
     * @param array<string,string> $tables
     * @return array<string,array<string,string>>
     */
    public function getTab(array $tables): array
    {
        $tab = [];
        $listeChps = $this->getArchitecture();
        foreach ($listeChps as $key => $value) {
            $tab[$key] = $value['nomChamp'];
        }

        foreach ($tables as $libelle => $table) {
            $this->ajouterCs($libelle, $table, $tab);
        }

        return $tab;
    }


    /**
     * @param array<int,array<string,string>> $listeCS
     * @param array<string,mixed> $entity
     * @throws Exception
     */
    public function addChampsSupplementaireValeur(
        array $listeCS,
        array &$entity,
        string $numTableEntete,
        ?string $numTableLign = null,
        ?string $tableLign = null
    ): void {
        $csDon = new CsDon($this->pdo);
        foreach ($listeCS as $champSupplementaire) {
            $noLig = $champSupplementaire['COD_TAB'] === $tableLign ? $entity[$numTableLign]: null;
            $codeEnr = ChampSupp::autoCompletCodeEnr($entity[$numTableEntete], $noLig, $champSupplementaire['COD_TAB']);
            $csDonEntity = $csDon->find(['COD_TAB' => $champSupplementaire['COD_TAB'], 'COD_ENR' => $codeEnr, 'NUM_FIX' => $champSupplementaire['NUM_FIX']]);

            if ($champSupplementaire['TYPE'] === 'LOGIQUE') {
                $csDonEntity['VALEUR'] = Sql::toBool($csDonEntity['VALEUR']) ? $this->trad->t('Oui'): $this->trad->t('Non');
            }
            if ($champSupplementaire['TYPE'] === 'DATE') {
                $csDonEntity['VALEUR'] = Date::dateConverte($csDonEntity['VALEUR']);
            }

            $entity['CS_EXTENSION'.$champSupplementaire['COD_TAB'].$champSupplementaire['NUM_FIX']] = $csDonEntity['VALEUR'];
        }
    }


    /**
     * @param string[] $champsDate
     * @param array<string,string> $entity
     * @return void
     */
    public function convertirDates(array $champsDate, array &$entity): void
    {
        $colonnes = array_keys($entity);
        foreach ($champsDate as $champ) {
            foreach ($colonnes as $colonne) {
                if (str_contains($champ, $colonne)) {
                    $entity[$colonne] = Date::dateConverte($entity[$colonne]);
                }
            }
        }
    }


    /**
     * @param string[] $champsDate
     * @param array<string,string> $entity
     * @return void
     */
    public function convertirBool(array $champsDate, array &$entity): void
    {
        $colonnes = array_keys($entity);
        foreach ($champsDate as $champ) {
            foreach ($colonnes as $colonne) {
                if (str_contains($champ, $colonne)) {
                    $entity[$colonne] = Sql::toBool($entity[$colonne]);
                }
            }
        }
    }

    protected function isPrixVisible(): bool
    {
        return !$this->parametrageService->isVisibilitePrixActif() || Roles::droitsUtilisateur($this->pdo, 'ST_PRX_ACC');
    }


    /**
     * @param string $libelle
     * @param string $codeTab
     * @param array<string,string> $listeChps
     * @return void
     */
    private function ajouterCs(string $libelle, string $codeTab, array &$listeChps): void
    {
        $listeCs = (new ChampSupp($this->pdo))->getInfoCS($codeTab);
        foreach ($listeCs as $cs) {
            $listeChps['CS_EXTENSION'.$codeTab.$cs['NUM_FIX']] = 'CS - '.$libelle.' - '.$cs['NOM'];
        }
    }
}
