<?php

namespace Modules\Facture\Repository;

use Entity\Model\Alias\ParamFourniss;
use Entity\Model\ParamDico;
use Entity\Model\Paravrac;
use Helpers\Outil\ArrayHelper;
use Helpers\Outil\Date;
use Helpers\Outil\Sql;
use Helpers\QueryBuilder\AbsRepository;

class PartnDematRepo extends AbsRepository
{

    public function __construct(\PDO $pdo)
    {
        parent::__construct($pdo);
    }

//_____________________________________________________________________________
// Partenaire Agréé

    /**
     * @param array<mixed> $post
     * @return array<array<mixed>>
     */
    public function listPartenaire(array $post = []) :array
    {
        $list = array_map(
            fn($listItem) => $this->hydratePartn($listItem),
            ArrayHelper::indexBy(
                (new ParamDico($this->pdo))->findAll([
                    'TYPEDICO' => 'FACT_DEMAT_PARTN',
                ]),
                'ID1'
            )
        );
        if (!empty($post['filter_isActive'])) {
            $list = array_filter(
                $list,
                fn($partn) => $partn['isActive'] == Sql::toBool($post['filter_isActive'])
            );
        }
        return $list;
    }

    /**
     * @return array<mixed>
     */
    public function getPartenaire(string $id) :array
    {
        return $this->hydratePartn(
            (new ParamDico($this->pdo))->findAll([
                'TYPEDICO' => 'FACT_DEMAT_PARTN',
                'ID1' => $id,
            ])
        );
    }

    /**
     * @param array<mixed> $listParamDico list of ParamDico 'TYPEDICO' = 'FACT_DEMAT_PARTN' with the same ID1 (Code PDP)
     * @return array<mixed>
     */
    private function hydratePartn(array $listParamDico)
    {
        // ID1 => partn id
        // ID2 => field name (see below)
        // COMMENTAIRE => field value
        $map = array_column($listParamDico, 'COMMENTAIRE', 'ID2');
        $now = date('Ymd');
        
        return [
            'ID' => $listParamDico[0]['ID1'],
            'isActive' => Date::isSqlDateBetween(
                $now,
                $map['DATE_DEBUT'] ?? '00000000',
                $map['DATE_FIN'] ?? '00000000'
            ),
            /*
            Possible fields :
            - LABEL: libellé du Flow
            - PARTN: enum ('OTHER'|'AGN3')
            - DATE_DEBUT: date Ymd
            - DATE_FIN: date Ymd

            Pour AGN3:
            - COMPANY_ID: id de company Agena (dans le cas ou PATN = 'AGN3')

            Pour OTHER:
            - URL:
            - URL_AUTH:
            - CLIENT_ID:
            - CLIENT_SECRET:
            */
        ] + $map;
    }
    
    

    /**
     * @param array<mixed> $pdpConfig
     */
    public function merge(array $pdpConfig) :void
    {
        
        $this->pdo->beginTransaction();

        $paramdico = new ParamDico($this->pdo);

        $id = [
            'TYPEDICO' => 'FACT_DEMAT_PARTN',
            'ID1' =>
                $pdpConfig['ID']
                ?? $this->fetchAssocOne( // 'Autoincrement'
                    "SELECT COALESCE( MAX(ID1) + 1, 1) as nextId
                    FROM PARAMDICO
                    WHERE TYPEDICO = 'FACT_DEMAT_PARTN'",
                    []
                )['nextId'] ?? 1,
        ];
        foreach ($pdpConfig as $field => $value) {
            if ($field == 'ID') {
                continue;
            }
            $paramdico->merge($id + [
                'ID2' => $field,
                'ID3' => '',
                'ID4' => '',
                'COMMENTAIRE' => $value,
            ]);
        }
        
        $this->pdo->commit();
    }
//_____________________________________________________________________________
// Taxe field marker

    /**
     * Issue #1400 automatically setup SIREN
     */
    public function updateTaxeField() :void
    {
        $paravrac = new ParamFourniss($this->pdo);
        $mapFr = $paravrac->getTaxeFieldMap()['FR'] ?? [];
        
        // Check if SIREN already exist
        if (! empty(ArrayHelper::findFirst(
            $mapFr,
            fn($item) => $item->type == 'SIREN'
        ))) {
            return;
        }

        // Deduce SIREN from label
        $itemSiren = ArrayHelper::findFirst(
            $mapFr,
            fn($item) => str_contains(strtolower($item->label), 'siren')
        );
        if ($itemSiren == null) {
            return;
        }
        
        $paravrac->set(ParamFourniss::$FouTaxeType, 'FR_' . $itemSiren->name, 'SIREN');
    }

//_____________________________________________________________________________
// Adr elec

    /**
     * List uniq AdrElec with any Centre
     * @return array<array<string>>
     */
    public function listAdrElec() :array
    {
        return $this->fetchAssocAll(
            "SELECT 
                FAC_DEMAT_ADRELEC.*,
                tCentre.RAIS_SOC as Centre_RAIS_SOC 
            FROM FAC_DEMAT_ADRELEC with(nolock)
            CROSS APPLY ( /* JOIN TOP 1 */
                SELECT TOP 1 * FROM (
                    SELECT CENTRE.*
                    FROM CENTRE with(nolock)
                    WHERE CENTRE.ID_ADR_FACELEC = FAC_DEMAT_ADRELEC.ID
                ) as tmp
            ) as tCentre",
            []
        );
    }
}
