<?php

namespace App\Helper;

use App\Entity\Order;
use App\Repository\OrderRepository;
use Psr\Log\LoggerInterface;
use Symfony\Component\Filesystem\Exception\IOExceptionInterface;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;


class Hiltes
{
    // init file system
    protected $fsObject;
    protected $current_dir_path;
    protected $apiKey;
    protected $hiltesApiHash = '';
    protected $hiltesUsr;
    protected $hiltesPass;
    protected $hiltesApiUrl;


    public function __construct(private OrderRepository $orderRepository, private LoggerInterface $logger)
    {
        $this->fsObject = new Filesystem();
        $this->current_dir_path = getcwd();

        $this->hiltesApiUrl = $_ENV['HILTES_API_URL'];
        $this->hiltesUsr = $_ENV['HILTES_API_USER'];
        $this->hiltesPass = $_ENV['HILTES_API_PASS'];
    }


    /**
     * @param string $data
     * @return void
     */
    public function export(string $data)
    {
        try {
            $new_file_path = $this->current_dir_path . "/hiltes/c2h/" . $this->createFileName();

            if (!$this->fsObject->exists($new_file_path)) {
                $this->fsObject->touch($new_file_path);
                $this->fsObject->chmod($new_file_path, 0777);
                $this->fsObject->dumpFile($new_file_path, $data);
            }
        } catch (IOExceptionInterface $exception) {
            echo "Error creating file at" . $exception->getPath();
        }
    }

    /**
     * Aufbau des Dateinamens:
     * WU + Datum(TTMM) + Fortlaufendenummer (x2) + “.“ +Filialnummer(x4)
     * Beispieldateiname : WU220401.0001
     */
    public function createFileName(): string
    {
        $date = date('dm');
        $number = '01';
        $filial = '0001';
        return 'WU' . $date . $number . '.' . $filial;
    }

    /**
     * @param $orderData
     * @return bool|void
     */
    public function createRequest($orderData)
    {

        $this->loginToHiltes('', '');

        /**
         * @var Order
         */
        $order = $this->orderRepository->findOneBy(array('orderId' => $orderData->getOrderId()));


        if ($order) {
            //foreach ($orders as $order) {
            if ($order->getStatus() != 2) {
                $this->logger->error('Order not ready for export ' . $order->getOrderId());
                return false;
            }

            $tA = $order->getData()[0];#json_decode($order->getData());

            #dump($tA);

            #*** Umkonvertieren des Datumstings *****************
            if (!empty($tA['salesdate'])) {
                $tA['orderdate'] = gmdate('Y-m-d\TH:i:s.v\Z', $tA['salesdate'] ? strtotime($tA['salesdate']) : time());
            } else {
                $tA['orderdate'] = gmdate('Y-m-d\TH:i:s.v\Z', time());
            }

            #*** Aufbau des Arrays ******************************
            $arr = array(
                'File' => array(
                    "BranchNumber" => 8, #Die Filialnummer
                    "ShopNumber" => 1, #Die Shopnummer
                    "SalesDate" => $tA['orderdate'], #Das Umsatzdatu
                    "DistributionChannel" => 5, #Der Vertriebskanal
                ),
                'SaleList' => array(),
                'CustomerList' => array(),
            );
            #*** Items ***************
            if (!empty($tA['positions']) && is_array($tA['positions'])) {
                $tSalNr = array();
                foreach ($tA['positions'] as $v) {
                    if ($v['type'] == 'versandposition' || $v['sku'] == '') {
//                            $SalesNumber = '000001';
//                            $SalesGoodsGroupNumber = 9350;

                        // Versandkosten werden nicht übermittelt
                        continue;
                    } else {
                        $SalesNumber = (!empty($v['gtin']) ? $v['gtin'] : $v['sku']);
                        if (preg_match('/^([0-9]+)_/', $SalesNumber, $tP)) {
                            $SalesNumber = $tP[1];
                        }
                        if (isset($tSalNr[$SalesNumber])) {
                            $tSalNr[$SalesNumber]++;
                            $SalesNumber .= $tSalNr[$SalesNumber];
                        } else {
                            $tSalNr[$SalesNumber] = 0;
                        }
                        $SalesGoodsGroupNumber = 0;
                    }

                    #dump($SalesNumber);
                    #********
                    $v['CalculatedSellingPrice'] = round(str_replace(',', '.', $v['price']), 2);
                    $v['AchievedSalesPrice'] = round(str_replace(',', '.', $v['CalculatedSellingPrice']), 2);

                    $arr['SaleList'][] = array(
                        "OrderNumber" => $tA['externOrderId'], #X
                        "SalesLabel" => 'Ean',#$v['sku'],#X
                        "SalesLabelNumber" => $SalesNumber,#X
                        "SalesGoodsGroupNumber" => $SalesGoodsGroupNumber,
                        #"SizeDescription" => '',#"string",
                        "CustomerNumber" => $tA['kundenummer'],
                        #"TypeOfEstate" => 0,
                        "Amount" => $v['menge'],#X
                        "CalculatedSellingPrice" => $v['CalculatedSellingPrice'], #X Kalkulierter Verkaufspreis
                        "AchievedSalesPrice" => $v['AchievedSalesPrice'], #X Erzielter Verkaufspreis
                        "TransactionType" => "Sale", #X Die Vorgangsart Sale=Verkauf Exchange=Umtausch / Storno
                        "ReceiptNumber" => substr($order->getOrderId(), 3), #Die Belegnummer
                        "DateOfSale" => $tA['orderdate'],#X  das Verkaufsdatum mit Verkaufszeit
                        "PaymentMethod" => 'Invoice',#X "CreditCard",
                        "Currency" => 'EUR',#X "string",
                        "Unit" => "Piece",#X
                        "DistributionChannel" => 5,
                    );

                }
            }
            #*** Kunde *******************************
            $arr['CustomerList'][] = array(
                "CustomerNumber" => $tA['kundenummer'], # Fake Daten
                "Surname" => $tA['name'],#"string",
                "Forename" => $tA['vorname'],#"string",
                "AddressCity" => $tA['ort'],#"string",
                "AddressZipCode" => $tA['plz'], "string",
                "AddressStreet" => $tA['strasse'],#"string",
                "AddressCountry" => substr($tA['land'], 0, 3),#"string",

            );

            //$data = $this->createJson($arr);
            $this->logger->info(var_export($arr, 1));

            try {
                return $this->sendOrderToHiltes($arr);
            } catch (\Exception $e) {
                $this->logger->error('Send Order Error ' . $e->getMessage() . __LINE__);
                return false;
            }
        }
    }

    /**
     * @param $usr
     * @param $pass
     * @return bool
     */
    public function loginToHiltes($usr, $pass): bool
    {
        $url = $this->hiltesApiUrl . '/api/Authentication/authenticate';

        $param = array(
            'Username' => (!empty($usr) ? $usr : $this->hiltesUsr),
            'Password' => (!empty($pass) ? $pass : $this->hiltesPass),
#			'parse_mode' => 'html',
#			'disable_notification' => $disable_notification,
#			'text' => $message_text
        );

        $r = $this->sendToHiltes($url, $param);

        if ($r === false) {
            $this->logger->error('Login Error ' . $r . __LINE__);
            return false;
        }

        $t = json_decode($r, true);
        if ($t['Success']) {
            $this->hiltesApiHash = $t['Data'];
            return true;
        } else {
            $this->logger->error('Login Error ' . var_dump($t['Errors']) . __LINE__);
            return false;
        }
    }

    /**
     * Sends a request to the specified URL using CURL.
     *
     * @param string $url The URL to send the request to.
     * @param mixed $param The data to send with the request. It should be an associative array.
     * @param bool $auth (Optional) Indicates whether to include authorization in the request headers. Default is false.
     * @return mixed The response from the server.
     */
    public function sendToHiltes($url, $param, $auth = false)
    {
        $ch = curl_init($url);
        if ($auth) {
            $authorization = "Authorization: Bearer " . $this->hiltesApiHash;
        } else {
            $authorization = false;
        }

        # Setup request to send json via POST.
        $payload = json_encode($param);

        curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json', $authorization));
        curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
        # Return response instead of printing.
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        # Send request.
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }

    /**
     * Creates a JSON object based on the given data.
     *
     * @param mixed $data The data to be converted to JSON.
     * @return array The JSON object.
     */
    public function createJson($data)
    {
        $arr = array(
            'File' => array(
                "BranchNumber" => $data['BranchNumber'], #Die Filialnummer
                "ShopNumber" => $data['ShopNumber'], #Die Shopnummer
                "SalesDate" => $data['SalesDate'], #Das Umsatzdatu
                "DistributionChannel" => $data['DistributionChannel'] #Der Vertriebskanal
            ),
            'SaleList' => array(),
            'CustomerList' => array(),
        );
        #*** Sale List
        if (!empty($data['SaleList'])) {
            foreach ($data['SaleList'] as $v) {
                $arr['SaleList'][] = array(
                    "OrderNumber" => $v['OrderNumber'],
                    "SalesLabel" => $v['SalesLabel'], #Das Etikettkennzeichen
                    "SalesLabelNumber" => $v['SalesLabelNumber'], #Etikettennummer
                    "SalesGoodsGroupNumber" => $v['SalesGoodsGroupNumber'],

                    #"CustomerNumber" => $v['CustomerNumber'],
                    #"TypeOfEstate" => $v['TypeOfEstate'],
                    "Amount" => $v['Amount'],
                    "CalculatedSellingPrice" => $v['CalculatedSellingPrice'],
                    "AchievedSalesPrice" => $v['AchievedSalesPrice'],
                    "TransactionType" => $v['TransactionType'],
                    "ReceiptNumber" => $v['ReceiptNumber'],
                    "DateOfSale" => $v['SalesDate'],#"2023-09-14T11:54:26.708Z",
                    "PaymentMethod" => $v['PaymentMethod'],
                    "Currency" => $v['Currency'],
                    "Unit" => $v['Unit'],
                    "DistributionChannel" => $v['DistributionChannel']
                );
            }
        }
        #*** Sale List
        if (true) {
            foreach ($data['CustomerList'] as $v) {
                $arr['CustomerList'][] = array(
                    "CustomerNumber" => $v['CustomerNumber'],
                    #"CardNumber" => $v['CardNumber'],
                    #"SalutionNumber" => $v['SalutionNumber'],
                    "Surname" => $v['Surname'],
                    "Forename" => $v['Forename'],
                    "AddressCity" => $v['AddressCity'],
                    "AddressZipCode" => $v['AddressZipCode'],
                    "AddressStreet" => $v['AddressStreet'],
                    "AddressCountry" => $v['AddressCountry'],
                    #"PostOfficeBox" => $v['PostOfficeBox'],
                    #"PostOfficeBoxZipCode" => $v['PostOfficeBoxZipCode'],
                    #"Title" => $v['Title'],
                    #"PhoneNumber1" => $v['PhoneNumber1'],
                    #"PhoneNumber2" => $v['PhoneNumber2'],
                    #"FaxNumber" => $v['FaxNumber'],#"string",
                    #"BirthDay" => $v['BirthDay'],
                    #"Gender" => $v['Gender'],
                    #"EmailAddress" => $v['EmailAddress'],
                    #"Discount" => $v['Discount'],
                    #"Limit" => $v['Limit'],
                    #"LockMark" => $v['LockMark'],
                    #"DubiousMark" => $v['DubiousMark'],
                    #"DubiousText" => $v['DubiousText'],
                    #"DirectDebit" => $v['DirectDebit'],
                    #"BankName1" => $v['BankName1'],#"string",
                    #"BankAccountNumber1" => $v['BankAccountNumber1'],#"string",
                    #"BankCodeNumber1" => $v['BankCodeNumber1'],#"string",
                    #"BankName2" => $v['BankName2'],#"string",
                    #"BankAccountNumber2" => $v['BankAccountNumber2'],#"string",
                    #"BankCodeNumber2" => $v['BankCodeNumber2'],#"string",
                    #"BankName3" => $v['BankName3'],#"string",
                    #"BankAccountNumber3" => $v['BankAccountNumber3'],#"string",
                    #"BankCodeNumber3" => $v['BankCodeNumber3'],#"string",
                    #"CreditcardNumber1" => $v['CreditcardNumber1'],#"string",
                    #"CreditcardNumber2" => $v['CreditcardNumber2'],#"string",
                    #"CreditcardNumber3" => $v['CreditcardNumber3'],#"string",
                    #"CreditcardNumber4" => $v['CreditcardNumber4'],#"string",
                    #"ChangeIndicator" => $v['ChangeIndicator'],
                    #"Newsletter" => $v['Newsletter'],
                    #"Password" => $v['Password'],
                    #"AdBan" => $v['AdBan']
                );
            }
        }
        #dump($arr);
        return $arr;
    }

    /**
     * @param $data
     * @return bool
     * @throws \Exception
     */
    public function sendOrderToHiltes($data): bool
    {
        $url = $this->hiltesApiUrl . '/api/WebSale/import';

        $param = $data;
        //dump($param);
        $r = $this->sendToHiltes($url, $param, true);
        //$r = true;

        if ($r === false) {
            $this->logger->error('Send Order Error ' . __LINE__);
            return false;
        }

        $t = json_decode($r, true);

        try {
            $order = $this->orderRepository->findOneBy(array('orderId' => $data['SaleList'][0]['OrderNumber']));
            $order->setStatus(3);
            $order->setHiltes(var_export($r, 1));

            $this->orderRepository->update($order, true);
        } catch (\Exception $exception) {
            $this->logger->error('Send Order Error ' . $exception->getMessage() . __LINE__);
            return false;
        }

        if ($t['Success']) {
            return true;
        } else {
            $this->logger->error('Send Order Error ' . var_export($t['errors'], 1) . __LINE__);
            return false;
        }
    }

}