<?php

require_once DOL_DOCUMENT_ROOT.'/custom/ntak/class/ntakinvoice.class.php';
require_once DOL_DOCUMENT_ROOT.'/custom/ntak/class/ntakconnector/ntak_client.class.php';
require_once DOL_DOCUMENT_ROOT.'/custom/ntak/class/ntaklogger.class.php';
require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
require_once DOL_DOCUMENT_ROOT.'/custom/ntak/class/ntaksendresult.class.php';
require_once DOL_DOCUMENT_ROOT.'/custom/multicompany/class/dao_multicompany.class.php';

class NtakSender
{
    public $db;
    private $unsentInvoices;
    private $validatedTickets;
    private $notSuccesses;
    private NtakLogger $ntakLogger;

    private $testInvoices = [
        //'RR2311-000283',
        //'RR2311-000282',
        //'RR2311-000283',
        // ...
        //'BBH2401-000025',
    ];

    public function __construct()
    {
        global $db;

        $this->db = $db;
        $this->ntakLogger = NtakLogger::getInstance();
    }
    /**
     * 
     */
    public function checkNtakStatus(): bool
    {
        $daoMulticompany = new DaoMulticompany($this->db);
        $daoMulticompany->getEntities();

        if (empty($daoMulticompany->entities)) {
            $this->ntakLogger->logIntoFile('Missing entities', LOG_ERR);
        } else {
            foreach ($daoMulticompany->entities as $entity) {
                $this->loadNtakStatuses($entity->id);
            }
        }

        return true;
    }
    /**
     * 
     */
    public function loadNtakStatuses(int $entity): void
    {
        $sql = "
            SELECT f.rowid, f.ref, e.ntak_id, e.ntak_status
            FROM llx_facture AS f 
            LEFT JOIN llx_facture_extrafields AS e ON e.fk_object=f.rowid 
            WHERE e.ntak_status ILIKE 'BEFOGADVA'
            AND f.entity={$entity}
            ORDER BY f.datec DESC 
        ";

        $rows = $this->db->query($sql);
        if ($rows) {
            while ($row = $this->db->fetch_object($rows)) {
                $ntakResult = $this->checkSentInvoice($row->ntak_id, $row->rowid);
                if (!empty($ntakResult['uzenetValaszok'][0]['statusz'])) {
                    $invoice = new Facture($this->db);
                    if ($invoice->fetch($row->rowid) > 0) {
                        $invoice->array_options['options_ntak_status'] = $ntakResult['uzenetValaszok'][0]['statusz'];
				        $invoice->updateExtraField('ntak_status');        
                    }
                }
            }
        }
    }
    /**
     * 
     */
    public function send(): bool
    {
        global $conf;
        
        $this->ntakLogger->logIntoFile('Start sending', LOG_INFO);
        $this->ntakLogger->logIntoFile('Entity:' . $conf->entity, LOG_INFO);
        return true;
        exit;


        $daoMulticompany = new DaoMulticompany($this->db);
        $daoMulticompany->getEntities();

        if (empty($daoMulticompany->entities)) {
            $this->ntakLogger->logIntoFile('Missing entities', LOG_ERR);
        } else {
            foreach ($daoMulticompany->entities as $entity) {
                for ($i = 0; $i < 10; $i++) {
                    $this->massSending($entity->id);
                }
            }
        }        

        $this->ntakLogger->logIntoFile('Finish sending', LOG_INFO);
        
        return true;
    }

    public function send2(): bool
    {
        global $conf;
        $this->ntakLogger->logIntoFile('Start sending', LOG_INFO);
        $this->ntakLogger->logIntoFile('Entity:' . $conf->entity, LOG_INFO);
        //exit;
        if (empty($conf->entity)) {
            $this->ntakLogger->logIntoFile('Missing entities', LOG_ERR);
        } else {
            //for ($i = 0; $i < 10; $i++) {
                $this->massSending($conf->entity);
            //}
        }        
        $this->ntakLogger->logIntoFile('Finish sending', LOG_INFO);
        return true;
    }

    /**
     * 
     */
    private function massSending(int $entityId): void
    {
        $this->setUnsentInvoices($entityId);

        if (!empty($this->unsentInvoices)) {
            $ntakClient = NtakClient::getInstance();
            $massData = [
                'programAdatok' => [],
                'tranzakcioAdatok' => []
            ];
            $invoices = [];

            foreach ($this->unsentInvoices as $unsentInvoiceData) {
                $invoice = new NtakInvoice($this->db);
                if ($invoice->fetch($unsentInvoiceData->rowid) > 0) {
                    $ntakSendResult = $ntakClient->send($invoice, false);

                    if (empty($massData['tranzakcioAdatok'])) {
                        $massData = $ntakSendResult->generatedData;
                    } else {
                        if (!empty($ntakSendResult)) {
                            if (!empty($ntakSendResult->generatedData['programAdatok'])) {
                                // filter 
                                foreach ($ntakSendResult->generatedData['programAdatok'] as $programData) {                
                                    $ref = $programData['tssProgramAzonosito'];
                                    $exists = array_filter($massData['programAdatok'], function ($item) use ($ref) {
                                        return ($item['tssProgramAzonosito'] === $ref);
                                    });
                                    if (empty($exists)) {
                                        $massData['programAdatok'][] = $programData;
                                    }
                                }

                                //$massData['programAdatok'] = array_merge($massData['programAdatok'], $ntakSendResult->generatedData['programAdatok']);
                            }

                            if (!empty($ntakSendResult->generatedData['tranzakcioAdatok'])) {
                                $massData['tranzakcioAdatok'] = array_merge($massData['tranzakcioAdatok'], $ntakSendResult->generatedData['tranzakcioAdatok']);
                            }                                                    
                        }                        
                    }
                    $invoices[] = $invoice;
                }
            }

            if (!empty($massData['tranzakcioAdatok'])) {

                $ntakSendResult = $ntakClient->sendToServer($massData);

                if (!empty($ntakSendResult->ntakId)) {                    
                    foreach ($invoices as $inv) {
                        $inv->array_options['options_ntak_id'] = $ntakSendResult->ntakId;
                        $inv->updateExtraField('ntak_id');
                        $inv->array_options['options_ntak_status'] = $ntakSendResult->ntakStatus;                        
                        $inv->updateExtraField('ntak_status');
                    }
                }
            }
        }
    }

    /**
     * 
     */
    public function checkSentInvoice(string $ntakId, int $invoiceId): array
    {
        return (NtakClient::getInstance())->checkWithLog($ntakId, $invoiceId);
    }

    /**
     * 
     */
    public function sendByInvoice(Facture $facture): ?NtakSendResult
    {
        $ntakSendResult = null;
        
        $this->ntakLogger->logIntoFile('Send invoice by ID ('.$facture->id.')', LOG_INFO);

        $invoice = new NtakInvoice($this->db);
        if ($invoice->fetch($facture->id) > 0) {
            $invoice->loadPayments();                
            // pass invoice to sender
            $ntakSendResult = (NtakClient::getInstance())->send($invoice);
        }

        $this->ntakLogger->logIntoFile('Send invoice finish', LOG_INFO);

        return $ntakSendResult;
    }

    /**
     * 
     */
    private function setUnsentInvoices(int $entityId): void
    {
        $this->ntakLogger->logIntoFile('Get unsent invoices from DB', LOG_INFO);

        $this->unsentInvoices = [];

        $testCondition = '';
        if (!empty($this->testInvoices)) {
            $testCondition = " AND f.ref IN ('".implode("','", $this->testInvoices)."') ";
        }
        /*
        $sql = "
            SELECT f.rowid, f.ref
            FROM ".$this->db->prefix()."facture AS f
            WHERE f.date_valid IS NOT NULL
            AND NOT EXISTS (
                SELECT 1
                FROM ".$this->db->prefix()."ntak_ntaklog AS l
                WHERE l.status = 1
                AND l.fk_facture = f.rowid
            )
            {$testCondition}
            ORDER BY f.datec ASC
        ";
        */
        /*
        $sql = "
            SELECT f.rowid, f.ref
            FROM ".$this->db->prefix()."facture AS f
            LEFT JOIN ".$this->db->prefix()."facture_extrafields AS e ON e.fk_object=f.rowid
            WHERE f.date_valid IS NOT NULL
            AND (e.ntak_status NOT ILIKE 'BEFOGADVA' OR e.ntak_status IS NULL)
            AND f.entity={$entityId}
            {$testCondition}
            ORDER BY f.datec DESC LIMIT 10            
        ";
        */
        //AND (e.ntak_status NOT ILIKE 'BEFOGADVA' OR e.ntak_status IS NULL) 
        $sql = "
            SELECT t.rowid, t.ref, t.prefs
            FROM (
                SELECT f.rowid, f.ref, STRING_AGG(p.ref, ', ') AS prefs
                FROM ".$this->db->prefix()."facture AS f 
                LEFT JOIN ".$this->db->prefix()."facture_extrafields AS e ON e.fk_object=f.rowid 
                LEFT JOIN ".$this->db->prefix()."facturedet AS fd ON fd.fk_facture=f.rowid
                LEFT JOIN ".$this->db->prefix()."product AS p ON p.rowid=fd.fk_product
                WHERE f.date_valid IS NOT NULL 
                AND e.ntak_status IS NULL
                AND f.entity={$entityId}
                AND f.multicurrency_total_ttc>0
                {$testCondition}
                GROUP BY f.rowid, f.ref
                ORDER BY f.datec DESC 
            ) AS t
            WHERE (t.prefs ILIKE '%,%' OR t.prefs NOT ILIKE '%card%') LIMIT 1
        ";

        //print $sql;exit;

        $rows = $this->db->query($sql);
        if ($rows) {
            while ($row = $this->db->fetch_object($rows)) {
                $this->unsentInvoices[] = $row;
            }
        }

        $numOfInvoices = count($this->unsentInvoices);
        $logMsg = 'There is no unsent invoice';
        if ($numOfInvoices > 0) {
            $logMsg = 'There are '.$numOfInvoices.' unsent invoices';
        }

        $this->ntakLogger->logIntoFile($logMsg, LOG_INFO);
    }

    /**
     * 
     */
    public function processValidatedTickets(): void
    {
        $this->ntakLogger->logIntoFile('Send ticket to validate', LOG_INFO);

        $ntakClient = NtakClient::getInstance();
        array_walk(
            $this->validatedTickets,
            function ($ticket) use ($ntakClient) {
                $ntakClient->validate(
                    $ticket->ticket_log_id, 
                    $ticket->fact_ref, 
                    $ticket->ntak_id, 
                    $ticket->prod_ref, 
                    $ticket->prod_date, 
                    $ticket->log_date,
                    $ticket->fact_id
                );
            }
        );

        

        $this->ntakLogger->logIntoFile('Ticket validated', LOG_INFO);
    }
}