<?php
namespace API\Altares;

use API\Partenaire\IBatch;
use API\Partenaire\IFournissLink;
use API\Partenaire\IPartenaire;
use API\Partenaire\Repository\PartenaireRepo;
use API\Partenaire\Service\PartenaireService;
use Entity\Model\FournScoring;
use Entity\Model\FourPartenaireData;
use Entity\Model\ParamDico;
use Psr\Container\ContainerInterface;

class IntuizPartenaire implements IPartenaire, IFournissLink, IBatch
{
    private ContainerInterface $container;
    private IntuizWs $webservice;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

//_____________________________________________________________________________
// Accessor

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

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

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

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

    protected function getIntuizWs() :IntuizWs
    {
        if (! isset($this->webservice)) {
            $this->webservice = IntuizWs::createFromConfig($this->container);
        }
        return $this->webservice;
    }

    protected function getService() :PartenaireService
    {
        return $this->container->get(PartenaireService::class);
    }
    protected function getPdo() :\PDO
    {
        return $this->container->get('PDO.oxasql');
    }

//_____________________________________________________________________________
// IFournissLink

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

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

    public function linkFourniss(array $fourniss) :void
    {
        
        $siret = $this->getIntuizWs()->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);

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

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

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

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

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

    /**
     * @return array<mixed>
     */
    public function getFullDetail(string $fournissId) :array
    {
        $fournissData = (new ParamDico($this->getPdo()))->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->getIntuizWs()->getListeBilans($siret);

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

//_____________________________________________________________________________
// Batch

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

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

        $fourScoringId = (new \Entity\Model\Dilispec($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';
        }

        // Update FournScoring
        $ws = $this->getIntuizWs();
        foreach ($listFourniss as $fourniss) {
            try {
                $score = $ws->getScore($fourniss['ExternalId']);
                $hito = $ws->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($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'].')'
            );
        }

        // Monitoring Direct+
        // TODO : get all followed fourniss with duns
        // TODO : compare with registered duns
        // TODO : add missing registered

        // TODO : pull notif
        // TODO : store notif

        // TODO : during fourniss modif, reset notif
        
        return 'O';
    }

//_____________________________________________________________________________
// Sub-routine
}
