<?php
namespace API\Altares;

use API\Partenaire\IBatch;
use API\Partenaire\IFournissLink;
use API\Partenaire\IPartenaire;
use API\Partenaire\Repository\PartenaireRepo;
use Entity\Model\Docatt;
use Entity\Model\Fourniss;
use Entity\Model\FournScoring;
use Entity\Model\FourPartenaireData;
use Entity\Model\ParamDico;
use Modules\API\APIExterne\Repository\Partenaire;
use Modules\Fournisseur\Repository\DocAtt as DocAttRepo;
use Psr\Container\ContainerInterface;
use Psr\SimpleCache\CacheInterface;

/**
 * Require phpStan 1.10.12
 * phpstan-type ProvigisDoc object{name:string,status:string,validity:string}
 */
class AltaresPartenaire implements IPartenaire, IFournissLink, IBatch
{

    private \PDO $pdo;
    private IntuizWs $webservice;

    public function __construct(ContainerInterface $container)
    {
        $this->webservice = IntuizWs::createFromConfig($container);
        $this->pdo = $container->get('PDO.oxasql');
    }

//_____________________________________________________________________________
// Accessor

    public function getCode() :string
    {
        return 'ALTARES';
    }

    public function getLabel() :string
    {
        return 'Altares';
    }

    public function getRouteLink() :string
    {
        return 'API.Altares.rattacher';
    }

    public function getRouteUnlink() :string
    {
        return 'API.Altares.detacher';
    }

//_____________________________________________________________________________
// IFournissLink

    public function getRouteDetail() :?string
    {
        return 'API.Altares.detail';
    }

    public function isLinkable(array $fourniss) :bool
    {
        return !empty($fourniss['NO_SIRET']);
    }

    public function linkFourniss(array $fourniss) :void
    {
        
        $siret = $this->webservice->match($fourniss);

        if (empty($siret)) {
            // TODO
            throw new \Exception('cannot find it');
        }
        // if (count($listResult) > 1) {
        //     // TODO : popup choice
        //     throw new \Exception('too many choice');
        // }
        // $result = reset($listResult);

        $isIntransac = $this->pdo->inTransaction();
        if (! $isIntransac) {
            $this->pdo->beginTransaction();
        }

        $fournissCode = $fourniss['CODE'];
        
        (new ParamDico($this->pdo))->insert([
            'TYPEDICO' => $this->getCode() . '_KEY',
            'ID1' => $this->getCode(),
            'ID3' => $fournissCode,
            'ID4' => $siret,
        ]);

        (new FourPartenaireData($this->pdo))->insertEntity(
            $fournissCode,
            $this->getCode(),
            false,
            false
        );

        if (! $isIntransac) {
            $this->pdo->commit();
        }
    }

    public function unlinkFourniss(string $fournissCode) :void
    {
        $this->pdo->beginTransaction();
        (new ParamDico($this->pdo))->delete([
            'TYPEDICO' => $this->getCode(). '_KEY',
            'ID1' => $this->getCode(),
            'ID3' => $fournissCode,
        ]);
        (new FourPartenaireData($this->pdo))->deleteEntity(
            $fournissCode,
            $this->getCode()
        );
        $this->pdo->commit();
    }

    /**
     * @return array<mixed>
     */
    public function getFullDetail(string $fournissId) :array
    {
        $fournissData = (new ParamDico($this->pdo))->find([
            'TYPEDICO' => $this->getCode() . '_KEY',
            'ID1' => $this->getCode(),
            'ID3' => $fournissId,
        ]);
        if ($fournissData == null) {
            throw new \Exception('Invalid code "'.$fournissId.'"');
        }
        $siret = $fournissData['ID4']/* SIRET */;
        $listBilan = $this->webservice->getListeBilans($siret);

        return [
            'Entreprise' => $this->webservice->getIdentiteEntreprise($siret),
            'Etablissement' => $this->webservice->getIdentiteEtablissement($siret),
            'ListEtablissement' => $this->webservice->getListeEtablissements($siret),
            'Score' => $this->webservice->getScore($siret),
            'HistoriqueScore' => $this->webservice->getHistoriqueScore($siret),
            'ScoreComment' => $this->webservice->getCommentairesScore($siret),
            'SyntheseFinanciere' => $this->webservice->getSyntheseFinanciere(
                $siret,
                reset($listBilan) // Assume first one is the most recent
            ),
        ];
    }

//_____________________________________________________________________________
// Batch

    public function batch(string $numeroTraitement) :string
    {
        $log = new \Helpers\Log\OxaEventDet($this->pdo, $numeroTraitement);

        $listFourniss =
            (new PartenaireRepo($this->pdo))
                ->listFournissByPartn($this->getCode());

        $fourScoringId = (new \Entity\Model\Dilispec($this->pdo))
            ->find([
                'TYPEDICO' => $this->getCode(),
                'CODEDICO'=>'ID_SCORE'
            ])['LIB01DICO'] ?? null;

        if (empty($fourScoringId)) {
            $log->setLog(
                $numeroTraitement,
                'O',
                'Warning : Aucun score id défini'
            );
            return 'O';
        }

        foreach ($listFourniss as $fourniss) {
            try {
                $score = $this->webservice->getScore($fourniss['ExternalId']);
                $hito = $this->webservice->getHistoriqueScore($fourniss['ExternalId']);
            } catch (\Throwable $e) {
                $log->setLog(
                    $numeroTraitement,
                    'E',
                    'ALTARES (INTUIZ) : Error : '
                    . 'Fourniss #'.$fourniss['CODE'] .' : '
                    . $e->__tostring()
                );
                continue;
            }
            $currentScore = intval($score['scoreVingt']);
            $scoreMoyen = array_sum(
                array_column(
                    $hito['listScore'],
                    'scoreVingt'
                )
            ) / count($hito['listScore']);

            $FournScoring = new FournScoring($this->pdo);
            $FournScoring->merge([
                'CODE_FOU' => $fourniss['CODE'],
                'ID_TYPESCORE' => $fourScoringId,
                'DATE_MAJ' => date('Ymd'),
                'VAL_SCORE' => $currentScore,
                'VAL_RISQUE' => $score['niveauRisque'],
                'TENDANCE' => [
                    1 => 'UP',
                    0 => 'EQ',
                    -1 => 'DO',
                ][ $currentScore <=> $scoreMoyen ],
            ]);
        
            $log->setLog(
                $numeroTraitement,
                'O',
                'ALTARES (INTUIZ) : Mise à jour du fournisseur '
                . $fourniss['RS'] . ' ('.$fourniss['NO_SIRET'].')'
            );
        }
        
        return 'O';
    }

//_____________________________________________________________________________
// Sub-routine
}
