<?php

namespace Modules\Fournisseur\Service;

use Entity\Model\Alias\ParamFourniss;
use Entity\Model\Devise;
use Entity\Model\Fourniss;
use Entity\Model\Langues;
use Entity\Model\ParamDico;
use Entity\Model\Paravrac;
use Entity\Model\Pays;
use Entity\Model\Periodes;
use Entity\Model\TypeTVA;
use Helpers\ChampsSupplementaire\ChampSupp;
use Helpers\Form\AbsFormService;
use Helpers\Form\FormBuilder;
use Helpers\Outil\ArrayHelper;
use Helpers\Trad\ITrad;
use Helpers\Trad\Trad;
use Helpers\Validator\Validator;
use Modules\Fournisseur\Repository\FircheFournissRepo;
use Psr\Container\ContainerInterface;

class FormFounisseur extends AbsFormService
{
    private ContainerInterface $container;

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

    private function getPdo() :\PDO
    {
        return $this->container->get(\PDO::class);
    }

    /**
     * @return array<\stdClass>
     */
    public function getBaseForm(string $taxePays)
    {
        return array_column(array_merge(
            $this->getBaseFormIdentite($taxePays),
            $this->getBaseFormDetail(),
            $this->getBaseFormRegl(),
            $this->getBaseFormCondPaie(),
            $this->getBaseFormBDD(),
            $this->getChampSup(),
        ), null, 'name');
    }

    /**
     * @return array<\stdClass>
     */
    public function getBaseFormIdentite(string $taxePays)
    {
        $pdo = $this->getPdo();
        $config = (new Paravrac($pdo))->getMap('PARAMFOU');
        $listTaxeInput = (new ParamFourniss($pdo))
            ->getTaxeField($taxePays);
        return array_column(array_merge(
            [
                // (object) [
                //     'name' => 'CODE_STE',
                //     'type' => 'ZOOM',
                //     'entity' => Societe::class,
                //     'validator' => ['mandatory' => true],
                // ],

                // Raison sociale
                $this->simpleText('RS', 45, ['validator' => [
                    'mandatory' => true,
                ]]),
                // Enseigne commerciale
                $this->simpleText('ENSCOMM', 45),

                //_______________________
                // Identité - Addresse
                
                $this->simpleSelect('CODE_PAYS', array_column( // Pays
                    (new Pays($pdo))->fetchAll(),
                    'LIBELLE',
                    'CODE_PAYS'
                )),
                $this->simpleText('VILLE1', 35, ['validator' => [ // Ville
                    'mandatory' => ($config['CTLVILLE'] == 'B'),
                ]]),
                $this->cpostal('CPOSTAL', 'CODE_PAYS', ['validator' => [
                    'mandatory' => ($config['CTLCDP'] == 'B'),
                ]]),
                (object) [
                    'name' => 'ADR', // 'Adresse'
                    'type' => 'TEXTAREA',
                    'validator' => [
                        'max' => 90,
                        'mandatory' => ($config['CTLADR'] == 'B'),
                    ],
                ],

                //_______________________
                // Identité - Contact

                $this->simpleText('TEL', 16), // Téléphone
                $this->simpleText('FAX', 16), // Fax
                $this->simpleText('EMAIL', 100, ['validator' => [ // Email
                    'email' => true,
                ]]),
                $this->simpleText('SITEWEB', 100, ['validator' => [ // Site Web
                    'url' => true,
                ]]),

                //_______________________
                // Register number

                $this->simpleText('NO_DUNS', 15), // DUNS Number
                $this->simpleText('ID_EXT', 30), // 'Identifiant externe'
                
                (object) [
                    'name' => 'TYP_TVA', // 'Type de TVA'
                    'type' => 'SELECT',
                    'choices' => array_column(
                        (new TypeTVA($pdo))->fetchAll(),
                        'LIBELLE',
                        'CODE_TTV'
                    ),
                    'validator' => [],
                ],

                $this->simpleText('NO_TVA_IC', 15),

                $this->simpleDate('DTEVALMIN'), // 'Date de début de validité'
                $this->simpleDate('DTEVALMAX'), // 'Date val max'
            ],
            // Champs Taxes
            array_map(function ($item) {
                return  (object) [
                    'label' => $item->label,
                    'name' => $item->name,
                    'type' => 'TEXT',
                    'validator' => $item->validator,
                ];
            }, $listTaxeInput), // TODO : filter input with empty label
            [
                //_______________________
                // Identité - misc

                $this->switch('ADR_COMMANDE'), // 'Adresse de Cde'
                $this->switch('DISPO_MOBILITY'), // 'Disponible sur mobile ?'


                (object) [ // 'Groupement'
                    'name' => 'FOURPRIN',
                    'type' => 'ZOOM',
                    'zoom_path' => 'Ajax.liste.grpfou',
                    'validator' => [],
                ],
                
                $this->simpleSelect('COD_LNG', (new Langues($pdo))->listChoice()),  // Langue

            ],
        ), null, 'name');
    }

    /**
     * @param array<\stdClass> $form
     * @return array<\stdClass>
     */
    public function applyOxaSimpliControl(array $form)
    {
        $configOxa = (new ParamDico($this->getPdo()))->getFournFieldConfig()['FOURNISS'];
        return array_map(function ($input) use ($configOxa) {
            if ($configOxa[ $input->name ]['isMandatory'] ?? false) {
                $input->validator['mandatory'] = true;
            }
            return $input;
        }, $form);
    }
    
    /**
     * @return array<\stdClass>
     */
    public function getBaseFormRegl()
    {
        $pdo = $this->getPdo();
        $config = (new Paravrac($pdo))->getMap('PARAMFOU');
        return array_column(array_merge(
            [
                $this->simpleText('RS_REGL', 45), // Raison sociale
                $this->simpleText('ADR_REGL', 90, ['type' => 'TEXTAREA']), // Adresse
                $this->simpleSelect('PAYSREGL', array_column( // Pays
                    (new Pays($pdo))->fetchAll(),
                    'LIBELLE',
                    'CODE_PAYS'
                )),
                $this->cpostal('CPREGL', 'PAYSREGL'), // Code postal
                $this->simpleText('VILREGL', 35), // Ville
                $this->simpleZoom('RESP_FAC', 'Ajax.liste.utilisateur'),
                $this->simpleText('DOM_BK', 26), // Domiciliation bancaire
                $this->simpleText('CODE_BK', 5), // Banque
                $this->simpleText('CODE_GUIC', 5), // Guichet
                $this->simpleText('NO_CPTE', 11), // N° Compte
                $this->simpleText('CLE_RIB', 2), // Clé RIB

                $this->simpleSelect('IBANPAYS', array_column(// Iban - Pays
                    (new Pays($pdo))->fetchAll(),
                    'CODE_PAYS',
                    'CODE_PAYS'
                ) + ['' => ''/* Empty option */]),
                $this->simpleText('IBANCLE', 2, [ // Iban - clé
                    'validator' => ['format' => 'integer']
                ]),
                $this->simpleText('IBANCPT', 30, [ // Iban - compte
                    'validator' => ['format' => 'code']
                ]),

                $this->simpleText('CODEBIC', 11, [ // Iban - bic
                    'validator' => [
                        'mandatory' => ($config['CTLCODEBIC'] == 'B'),
                    ]
                ]),
            ]
        ), null, 'name');
    }

    /**
     * @return array<\stdClass>
     */
    public function getBaseFormCondPaie()
    {
        $pdo = $this->getPdo();
        $config = (new Paravrac($pdo))->getMap('PARAMFOU');

        return array_column(array_merge(
            [
                // Condition de paiement
                $this->simpleZoom('COND_PAIE', 'Ajax.liste.conditionPaiement', [
                    'validator' => ['mandatory' => $config['CTLCDP']],
                ]),
                // Mode de paiement
                $this->simpleZoom('MODE_PAIE', 'Ajax.liste.modePaiement', [
                    'validator' => ['mandatory' => $config['CTLMDP']],
                ]),
                // Mode de livraison
                $this->simpleZoom('LIV', 'Ajax.liste.modelivraison', [
                    'validator' => ['mandatory' => $config['CTLMDL']],
                ]),
                $this->switch('AUTOCC'),
                $this->switch('NOCCGEN'),
                $this->switch('SEUILEPDIF'), // Seuils Cde e-proc différents Catalogue/hors catalogue

                (object) [
                    'name' => 'MTMAXCC', // Montant Max (catalogue)
                    'type' => 'DEVISE',
                    'devise' => 'EUR',
                ],
                (object) [
                    'name' => 'MTMAXCCHCT', // Montant Max (Hors catalogue)
                    'type' => 'DEVISE',
                    'devise' => 'EUR',
                    // Note : disabled if SEUILEPDIF == false
                ],

                $this->switch('FOURPREF'), // Fournisseur préférentiel

                $this->simpleZoom('DEFTYPDOC', 'Ajax.liste.typeDoc'), // Type de document
                $this->simpleText('ZONE_LIB1', 15), // Zone libre 1
                $this->simpleText('ZONE_LIB2', 15), // Zone libre 2

                $this->switch('RMINCPXN'), // Remise incluse en prix net ?
                $this->simpleFloat('REMISE', '3.2'), // Remise (%)
                $this->simpleZoom('DEVISE', 'Ajax.liste.devise'),
                $this->simpleSelect('TYP_TVA', array_column( // Type de TVA
                    (new TypeTVA($pdo))->fetchAll(),
                    'LIBELLE',
                    'CODE_TTV'
                )),
                (object) [
                    'name' => 'MNTMINFAC', // Minimum de facturation
                    'type' => 'DEVISE',
                    'devise' => 'EUR',
                ],
                (object) [
                    'name' => 'CA_MIN_ST', // CA Minimum Sous-traitant
                    'type' => 'DEVISE',
                    'devise' => 'EUR',
                ],
                (object) [// TOOD : Fournisseur.Conditions.CA_MIN_ST.attributes.Modifiable==0 and modifFourniss)
                    'name' => 'CA_MAX_ST', // CA Maximum Sous-traitant
                    'type' => 'DEVISE',
                    'devise' => 'EUR',
                ],
                $this->switch('RFRACT'), // Règle franco active ?
                (object) [
                    'name' => 'MNTMINFRA', // Minimum de franco
                    'type' => 'DEVISE',
                    'devise' => 'EUR',
                ],
                // TODO : FF.Fournisseur.Conditions.Franco.RFRACT |number_format
                // TODO : $('#input_ARTFRPORT').change(function(){
                $this->simpleZoom( // Article frais de port
                    'ARTFRPORT',
                    'Ajax.liste.articlesFraisPort',
                    ['zoom_filter' => ['filter_ARTFRAISPORT' => 'T']]
                    // Note : is disabled if RFRACT == false
                    // Note : On change a popup suggesting to create a assotiation
                    // Note : mandatory if FRPOBLIG == true
                ),
                $this->switch('FRPOBLIG'), // Frais de port obligatoire ?
                // Note : is disabled if RFRACT == false

            ]
        ), null, 'name');
    }

    /**
     * @return array<\stdClass>
     */
    public function getBaseFormBDD()
    {
        $pdo = $this->getPdo();
        return array_column(array_merge(
            [
                (object) [
                    // Tableau BDD
                    'type' => 'TABLE',
                    'name' => 'listBdd',
                    'validator' => [
                        'callback' =>
                            function (
                                Validator $validator,
                                object $input,
                                array $post,
                                ITrad $trad
                            ) {
                                // Validate unique NO_PAGE
                                $listCode = array_column(
                                    // Filter deleted
                                    array_filter($post['listBdd'] ?? [], function ($bdd) {
                                        return $bdd['Etat'] != 'S' /* Supprimer */;
                                    }),
                                    'NO_PAGE'
                                );

                                $validator->isTrue(
                                    count($listCode) != count(array_unique($listCode)),
                                    '<br />'. Trad::strBuild(
                                        $trad->t('Le numéro @1@ existe déjà pour ce fournisseur.'),
                                        $post['NO_PAGE']
                                    )
                                );
                            }
                    ],
                    'listChild' => [
                        $this->simpleText('NO_PAGE', 2, [ // Numéro
                            'label' => 'Numéro',
                            'validator' => ['mandatory' => true],
                        ]),
                        $this->simpleText('TITRE', 60, [ // Sommaire
                            'label' => 'Sommaire',
                            'validator' => ['mandatory' => true],
                        ]),
                        (object) [ // Numéro d'ordre
                            'name' => 'NUMORDRE',
                            'label' => 'Numéro d’ordre',
                            'type' => 'TEXT',
                            'validator' => ['format' => 'integer'],
                        ],
                        $this->switch('VEPROC', [ // Visible eProc
                            'label' => 'Visible eProc',
                        ]),
                        (object) [ // Onglet
                            'name' => 'ONGLET',
                            'label' => 'Onglet',
                            'type' => 'SELECT',
                            'choices' => function (ITrad $trad) {
                                return [
                                    'F' => $trad->t('Fournisseur'),
                                    'D' => $trad->t('Détail panier')
                                ];
                            },
                        ],
                        $this->simpleSelect(  // Langue
                            'LANGUE',
                            (new Langues($pdo))->listChoice(),
                        ),
                        $this->simpleText('TEXTEBDD', 3000, [ // Commentaires
                            'type' => 'TEXTAREA',
                            'validator' => [
                                'mandatory' => true,
                                // TODO : Regle de gestion obsolete ?
                                // 'callback' =>
                                //     function(
                                //         Validator $validator,
                                //         object $input,
                                //         array $post,
                                //         ITrad $trad
                                //     ) use($pdo) {
                                //         $id = $post['NO_PAGE'];
                                //         $config =
                                //             (new ParamDico($pdo))
                                //             ->getBddConfig()
                                //             [ str_pad($id,2,'0',STR_PAD_LEFT) ]
                                //             ?? null;
                                //         $validator->isStringAvecEspace(
                                //             Trad::strBuild(
                                //                 $trad->t('BDD - @1@ : @2@'),
                                //                 $post['NO_PAGE'],
                                //                 $post['TITRE']
                                //             ),
                                //             $post['TEXTEBDD'],
                                //             ($config['ctrlComment'] ?? 'B') == 'B'
                                //                 ? 1 : 0,
                                //             3000
                                //         );
                                //     }
                            ],
                            'label' => 'Commentaires',
                        ]),
                    ],
                ],
            ]
        ), null, 'name');
    }

    /**
     * @return array<\stdClass>
     */
    public function getBaseFormDetail()
    {
        $pdo = $this->getPdo();
        return array_column(array_merge(
            [
                $this->simpleDate('DTE_AGREM'), // Date d'agrément
                $this->switch('FRANCTVA'), // Achat systématique en franchise de TVA ?
                $this->switch('NOT_MANU'), // Notation manuelle systématique ?
                $this->simpleText('CERTIF', 20), // Certification
                $this->switch('GEREPORTAIL'), // Accès au portail OXALINK ?
                $this->simpleZoom('CODE_REGR', 'Ajax.liste.regroup'), // Regroupement
                $this->simpleText('MOTCLE', 30), // Zone libre 3
                $this->simpleText('IND_QUALI', 5), // Indice qualité
                $this->switch('RECEP_AUTO'), // Réception automatique des Cdes
                (object) [ // Périodicité du contrat
                    'name' => 'PER_REC_AUTO',
                    'type' => 'SELECT',
                    'choices' => function (ITrad $trad) {
                        return [
                            '' => '',
                            'M' => $trad->t('Mensuelle'),
                            'T' => $trad->t('Trimestrielle'),
                            'S' => $trad->t('Semestrielle'),
                            'A' => $trad->t('Annuelle'),
                        ];
                    },
                    'choices_value' => function () {
                        return ['', 'M', 'T', 'S', 'A'];
                    }
                ],
                $this->switch('NAUTOSFA'), // Pas d\'alimentation automatique des Sous-familles

                //_______________________

                (object) [
                    // Chiffre d'affaire
                    'type' => 'TABLE',
                    'name' => 'ListChiffreAffaire',
                    'listChild' => [
                        (object) [
                            'name' => 'ANNEE',
                            'type' => 'SELECT',
                            'choices' => array_column(
                                (new Periodes($pdo))
                                    ->fetchAll([], ['tri_DATE_DEB' => 'desc']),
                                'LIBELLE',
                                'CODE_PER'
                            ),
                            'validator' => ['mandatory' => true],
                        ],
                        (object) [
                            'name' => 'CHIFF_AFF', // 'Chiffre d\'affaire'
                            'type' => 'MONTANT',
                            'format' => '13.2',
                            'validator' => ['mandatory' => true],
                        ],
                        $this->simpleZoom(
                            'DEVISE_CA',
                            'Ajax.liste.devise',
                            ['validator' => ['mandatory' => true]]
                        ),
                    ],
                    'sort' => function ($a, $b) {
                        return $b['ANNEE'] <=> $a['ANNEE'];
                    }
                ],
            ]
        ), null, 'name');
    }

    // TODO : factorize
    /**
     * @return array<\stdClass>
     */
    public function getChampSup()
    {
        $builder = new FormBuilder();
        $schema = (new ChampSupp($this->getPdo()))->getSchema('FOURNISS');
        foreach ($schema as $cs) {
            switch ($cs['TYPE']) {
                case 'ALPHA':
                    $builder->addText(
                        ChampSupp::getCsExtKey($cs['COD_TAB'], $cs['NUM_FIX']),
                        intval($cs['ALP_LONG']),
                        [
                            'label' => $cs['NOM'],
                            // TODO : validator mandatory
                        ]
                    );
                    break;
                default:
                // TODO
            }
        }
        return $builder->build();
    }

    /**
     * @return array<\stdClass>
     */
    public function getBaseFormEdiRoutage()
    {
        $pdo = $this->getPdo();
        return array_column(array_merge(
            [
                $this->switch('BDC_ELEC'), // Bon de commande électronique
                (object) [ // Routage d\'impression de Cde
                    'name' => 'ROUTAGECDE',
                    'type' => 'SELECT',
                    'choices' => function (ITrad $trad) {
                        return [
                            '' => $trad->t('Routage par défaut'),
                            'P' => $trad->t('Préimprimé'),
                            'B' => $trad->t('Blanc'),
                            'F' => $trad->t('Fax'),
                            'E' => $trad->t('Email'),
                        ];
                    },
                    // NOTE : disabled if BDC_ELEC == true (unlike the other input)
                ],
                (object) [ // Type de format
                    'name' => 'TYPE_FORM',
                    'type' => 'SELECT',
                    'choices' => function (ITrad $trad) {
                        return [
                            1 => $trad->t('PDF'),
                            2 => $trad->t('XML'),
                            3 => $trad->t('TXT'),
                            4 => $trad->t('PDF/XML'),
                            5 => $trad->t('PDF/TXT'),
                            6 => $trad->t('cXML'),
                        ];
                    },
                    // NOTE : disabled if BDC_ELEC == false
                ],

                // TODO ...
                
            ]
        ), null, 'name');
    }

//_____________________________________________________________________________
// Shorthand

    /**
     * @return array<\stdClass>
     */
    public function getFormModif(string $taxePays)
    {
        $form = $this->getBaseForm($taxePays);
        
        return $form;
    }

    /**
     * @return array<\stdClass>
     */
    public function getFormCreate(string $taxePays)
    {
        return $this->getBaseForm($taxePays);
    }

    /**
     * @param array<mixed> $fourniss
     * @return array<\stdClass>
     */
    public function getFormModifPartn(array $fourniss)
    {
        return $this->getBaseForm($fourniss['CODE_PAYS'] ?? 'FR');
    }

//_____________________________________________________________________________
// View

    /**
     * @param array<\stdClass> $form
     * @return array<\stdClass>
     */
    public function getFormView(array $form)
    {
        $trad = $this->container->get(ITrad::class);
        foreach ($form as $input) {
            if (isset($input->label)) {
                continue;
            }
            
            if ($input->type == 'TABLE') {
                $this->getFormView($input->listChild);
            }

            $input->label = $this->getInputLabel($trad, $input->name);
        }
        return $form;
    }
    
    public function getInputLabel(ITrad $trad, string $inputName) :string
    {
        switch ($inputName) {
            case 'ListChiffreAffaire':
                return $trad->t('Chiffre d’affaires');
            case 'ANNEE':
                return $trad->t('Année');
            case 'CHIFF_AFF':
                return $trad->t('Chiffre d’affaires (en K)');
            case 'DEVISE_CA':
                return $trad->t('Devise');
        }

        $archi = Fourniss::getArchitectureSt($trad);
        return $archi[ $inputName ]['nomChamp'] ?? '';
    }
}
