<?php

namespace Entity\Model\Alias;

use Entity\Model\ParamDico;
use Helpers\Securite\Securite;
use Helpers\Session\ParseBase1;

class ParamImap extends ParamDico
{
   
    /**
     * @return array<\StdClass>
     */
    public function listImapConfig() :array
    {
        $listRow = $this->findAll([
            'TYPEDICO' => 'OXAFLEXI',
            'ID1' => $_SESSION['Session_NumClient'],
            'ID2' => (new ParseBase1())->getBroker(),
            'ID3' => 'IMAP',
        ]);
        
        return array_map([$this,'parseRow'], $listRow);
    }

    /**
     * @return \StdClass
     */
    public function getImapConfig(string $id) :object
    {
        $row = $this->find([
            'TYPEDICO' => 'OXAFLEXI',
            'ID1' => $_SESSION['Session_NumClient'],
            'ID2' => (new ParseBase1())->getBroker(),
            'ID3' => 'IMAP',
            'ID4' => str_pad($id, 10, '0', STR_PAD_LEFT),
        ]);
        
        return $this->parseRow($row);
    }

    /**
     * @param array<mixed> $entity
     */
    public function updateAccessToken(array $entity, ?string $refreshToken) :void
    {
        $com = $this->parseCommentaire($entity['COMMENTAIRE']);

        $this->updateEntity(
            array_intersect_key($entity, array_flip($this->primKey))
            + [
                'COMMENTAIRE' => $this->encodeCommentaire(
                    $com['type'],
                    $com['oauth2']['client_id'] ?? null,
                    $com['oauth2']['secret'] ?? null,
                    $com['oauth2']['url_auth'] ?? null,
                    $com['oauth2']['url_token'] ?? null,
                    $com['oauth2']['scope'] ?? null,
                    $refreshToken,
                ),
            ],
        );
    }


//_____________________________________________________________________________
// Sub-routine

    /**
     * @param array<string> $row
     * @_return object{
     *     source_entity:array<mixed>,
     *     id:string,
     *     label:string,
     *     type:int,
     *     societe:string,
     *     serveur:string,
     *     port:string,
     *     ssl:string,
     *     login:string,
     *     password:string,
     *     imap_config:array{
     *         host:string
     *     },
     *     oauth2?:array{
     *         client_id: string,
     *         secret: string,
     *         url_auth: string,
     *         url_token: string,
     *         scope: string,
     *         refresh_token: string
     *     }
     * }|null
     * @return \stdClass|null
     */
    private function parseRow(array $row)
    {
        if (empty($row)) {
            return null;
        }

        $com = $this->parseCommentaire($row['COMMENTAIRE']);
        return (object) ([
            'source_entity' => $row,
            'id' => $row['ID4'],
            'label' => $row['LIBELLE'],
            'type' => $com['type'],
            'client' => intval($row['ID1']),
            'societe' => $row['ALPHA1'],
            'port' => $row['ALPHA3'],
            'ssl' => $row['ALPHA4'], // type SSL
            'imap_config' => [
                'host'          => $row['ALPHA2'],
                'encryption'    => !empty($row['ALPHA4']) ? strtolower($row['ALPHA4']) : 'ssl',
                'validate_cert' => false, // TODO : true ?
                'username'      => $row['ALPHA8'],
                'password'      => $row['ALPHA9'],
                'protocol'      => 'imap'
            ]
            + (empty($row['ALPHA3']) ? [] : [
                'port' => intval($row['ALPHA3']),
            ])
            + (isset($com['oauth2']) ? [
                'authentication' => 'oauth',
            ] : []),
        ]
        + (isset($com['oauth2']) ? [
            'oauth2' => $com['oauth2'],
        ] : []));
    }

    /**
     * @return array{
     *    type:int,
     *    oauth2?:array{
     *        client_id:string,
     *        secret:string,
     *        url_auth:string,
     *        url_token:string,
     *        scope:string,
     *        refresh_token:?string,
     *    }
     * }
     */
    private function parseCommentaire(string $s) :array
    {
        if (empty($s)) {
            return ['type' => intval(0)];
        }
        
        $a = array_map('trim', explode(';', $s));
        try {
            return [
                'type' => intval($a[0]),
                'oauth2' => [
                    'client_id' => trim(Securite::decodeChiffrageFromMagic($a[1])),
                    'secret' => trim(Securite::decodeChiffrageFromMagic($a[2])),
                    'url_auth' => trim($a[3]),
                    'url_token' => trim($a[4]),
                    'scope' => trim($a[5]),
                    'refresh_token' => !empty($a[6]) ?
                        trim(Securite::decodeChiffrageFromMagic($a[6])):
                        null,
                ],
            ];
        } catch (\Exception $e) {
            // Magic may input ';;;;;'
            return ['type' => intval(0)];
        }
    }

    private function encodeCommentaire(
        int $type,
        ?string $client_id = null,
        ?string $secret = null,
        ?string $url_auth = null,
        ?string $url_token = null,
        ?string $scope = null,
        ?string $refresh_token = null
    ) :string {
        // TODO : handle case client_id null
        return join(';', [
            $type,
            Securite::encodeChiffrageFormMagic($client_id),
            Securite::encodeChiffrageFormMagic($secret),
            $url_auth,
            $url_token,
            $scope,
            $refresh_token != null ?
                Securite::encodeChiffrageFormMagic($refresh_token) :
                '',
        ]);
    }
}
