<?php
namespace API\Edicom;

use API\Partenaire\IFactDematReceiver;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\StreamInterface;
use Psr\SimpleCache\CacheInterface;
use Skeleton\Renderer\RendererInterface;

/**
 * @phpstan-import-type SubcripItem from \API\Edicom\EdicomWs
 */
class EdicomPartenaire implements IFactDematReceiver
{
    private int $id;

    private string $schemaUbl;
    private string $schemaStatusIn;
    private string $schemaStatusOut;

    private EdicomWs $ws;

    public function __construct(
        private ContainerInterface $container,
        int $id,
        string $username,
        string $password,
        string $login,
        string $secret,
        string $group,
        string $domain,
        string $application,
        string $schemaUbl,
        string $schemaStatusIn,
        string $schemaStatusOut,
        CacheInterface $cache
    ) {
        $this->id = $id;
        $this->schemaUbl = $schemaUbl;
        $this->schemaStatusIn = $schemaStatusIn;
        $this->schemaStatusOut = $schemaStatusOut;
        $this->ws = new EdicomWs(
            $username,
            $password,
            $login,
            $secret,
            $group,
            $domain,
            $application,
            $cache
        );
    }

    /**
     * @param array<mixed> $config As given by FactureDematRepo
     */
    public static function getFromConfig(ContainerInterface $container, array $config) :self
    {
        return new EdicomPartenaire(
            $container,
            $config['ID'],
            $config['USERNAME'],
            $config['PASSWORD'],
            $config['LOGIN'],
            $config['SECRET'],
            $config['GROUP'],
            $config['DOMAIN'],
            $config['APPLICATION'],
            $config['SCHEMA_UBL'],
            $config['SCHEMA_STATUS_IN'],
            $config['SCHEMA_STATUS_OUT'],
            $container->get(CacheInterface::class)
        );
    }


    public function getId() :int
    {
        return $this->id;
    }
    public function getCode() :string
    {
        return 'EDICOM';
    }
    public function getLabel(bool $short = false) :string
    {
        return 'Edicom';
    }

    public function getWs() :EdicomWs
    {
        return $this->ws;
    }

    public function getSchemaUbl() :string
    {
        return $this->schemaUbl;
    }

    public function getSchemaStatusIn() :string
    {
        return $this->schemaStatusIn;
    }

    public function getPPFId(): string
    {
        return 'NOT_USED';
    }
    
    public function listNext(array &$context) :array
    {
        // Note : Since edicom ubl retrieval is not compatible
        // with IFactDematReceiver::listFlow we use EdicomFactureBatch
        // TODO : adapt it to use $context
        throw new \Exception('Not implemented');
    }

    /**
     * @return SubcripItem[]
     */
    public function listUblItem()
    {
        return array_map(
            function ($item) {
                $item->fullId = 'U'.$item->id; // Add schema indicator inside the id
                return $item;
            },
            $this->ws->listSubcription($this->schemaUbl)
        );
    }

    /**
     * @return SubcripItem[]
     */
    public function listDocStatusItem()
    {
        return array_map(
            function ($item) {
                $item->id = 'S'.$item->id; // Add schema indicator inside the id
                return $item;
            },
            $this->ws->listSubcription($this->schemaStatusIn)
        );
    }

    /**
     * expect $id to start with schema indicator
     */
    public function getFlowFile(string $id) :StreamInterface
    {
        return $this->ws->getFile(
            match (substr($id, 0, 1)) {
                'U' => $this->schemaUbl,
                'S' => $this->schemaStatusIn,
                default => (function () {
                    throw new \Exception('Invalid code');
                })()
            },
            substr($id, 1)
        );
    }

    /**
     * expect $id to start with schema indicator
     */
    public function getCdarFile(string $id) :StreamInterface
    {
        return $this->ws->getFile(
            match (substr($id, 0, 1)) {
                'U' => $this->schemaUbl,
                'S' => $this->schemaStatusIn,
                default => (function () {
                    throw new \Exception('Invalid code');
                })()
            },
            substr($id, 1)
        );
    }


    public function getReadableViewFile(object $flow) :?StreamInterface
    {
        // Reable is given inside the UBL (see EdicomFactureBatch::createFlowEntityFromUBL)
        return null;
    }

    public function updateStatus(string $id, array $cdar) :void
    {
        $this->ws->postDoc(
            $this->schemaStatusOut,
            $this->container->get(RendererInterface::class)->render(
                '@API/Edicom/_StatusUpdate',
                $cdar
            ),
            'invoice_'.$cdar['FAC_ENT']['FACT_FOU']
            .'_status_'.$cdar['status']['code'].'_update.xml'
        );
    }
}
