<?php

    namespace MNM\Spitzner\Cron;

    use Psr\Log\LoggerInterface;
    use MNM\Spitzner\Model\ExportLogEntryFactory;
    use Magento\Sales\Model\OrderFactory;
    use Magento\Framework\Filesystem\DirectoryList;
    use Magento\Customer\Api\CustomerRepositoryInterface;
    use Magento\Catalog\Api\ProductRepositoryInterface;

    class ExportOrders {
        const STORE_ID = 1;

        CONST ORIGINAL_CONTRACT = "HP-PT-001";

        private $payment_mapping = array(
                                    'debitpayment'   => 'ZS26',
                                    'banktransfer'   => 'ZB24',
                                    'paypal_express' => 'ZB95');

        protected $logger;
        protected $exportLogEntryFactory;
        protected $orderFactory;
        protected $directoryList;
        protected $customerRepository;
        protected $productRepository;

        public function __construct(LoggerInterface $logger,
                                    ExportLogEntryFactory $exportLogEntryFactory,
                                    OrderFactory $orderFactory,
                                    DirectoryList $dir,
                                    CustomerRepositoryInterface $cri,
                                    ProductRepositoryInterface $pri)
        {
            $this->logger =                 $logger;
            $this->exportLogEntryFactory =  $exportLogEntryFactory;
            $this->orderFactory =           $orderFactory;
            $this->directoryList =          $dir;
            $this->customerRepository =     $cri;
            $this->productRepository =      $pri;
        }

        public function execute()
        {
            $interface_path =       $this->directoryList->getRoot().'/export/';
            $export_path =          $interface_path.'copy/';
            $file_name =            date("YmdHis") . '_orders_spitzner.csv';
            $file_path =            $export_path . $file_name;
            $new_last_exported_id = 0;
            $lastId =               0;

            $exportLogEntrys = $this->exportLogEntryFactory->create()->getCollection()
                                ->setPageSize(1)
                                ->setOrder('exportlog_id', 'DESC');

            $data = $exportLogEntrys->getFirstItem();

            if($data->getId())
            {
                $lastId = $data->getLastExportedOrderId();

                $orders = $this->orderFactory->create()->getCollection()
                            ->addFieldToSelect('*')
                            ->addFieldToFilter('entity_id', ['gt' => $lastId]);

                if($orders->count())
                {
                    $file_pointer = fopen($file_path, "w+");
                    if (!$file_pointer)
                    {
                        $this->logger->error('MNM\Spitzner - Exporting orders - unable to write export file');
                        return;
                    }

                    $this->write_csv_head_row($file_pointer);

                    foreach ($orders as $order) {
                        $new_last_exported_id = $this->write_order($order, $file_pointer);
                    }

                    if ($new_last_exported_id > 0)
                    {
                        //save last saved
                        $entry = $this->exportLogEntryFactory->create();
                        $entry->setData([
                                    'exported_at' => date('Y-m-d H:i:s'),
                                    'last_exported_order_id' => $new_last_exported_id]);
                        $entry->save();
                    }

                    fclose($file_pointer);
                    if(!copy($file_path, $interface_path.$file_name))
                    {
                        $this->logger->error('MNM\Spitzner - Exporting orders - Could not copy file '.$file_path.' to '.$interface_path.$file_name);
                    }

                    if($lastId < $new_last_exported_id)
                    {
                        $this->logger->info('MNM\Spitzner - Exporting orders - from '.$lastId.' to '.$new_last_exported_id.' into '.$interface_path.$file_name);
                    }
                }
            }
        }

        protected function write_order($order, $file_pointer)
        {
            $increment_id = $order->getIncrementId();

            $this->logger->info('MNM\Spitzner - Exporting orders - exporting order with ID ' . $increment_id);

            /* customer information */
            $customer =                 $order->getCustomer();
            if($customer)
            {
                $customer_id =              $customer->getCustomerNumber() ?? ''; // Spitzner Kundennummer
                $customer_external_id  =    $customer->getId(); // Magento Kundennummer
                $email =                    empty($customer->getEmail()) ? $order->getCustomerEmail() : $customer->getEmail();
                $day_of_birth =             date('Y-m-d', strtotime($customer->getDob()));
                $day_of_birth =             ($day_of_birth == '1970-01-01') ? "" : $day_of_birth;
            }
            else
            {
                $customer_id =          '';
                $customer_external_id = '';
                $email =                $order->getCustomerEmail();
                $day_of_birth =         '';
            }

            $coupon_code =              trim(mb_strtoupper($order->getCouponCode() ?? '', 'UTF-8'));

            /* address information */
            $billing_address =  $order->getBillingAddress();

            if (empty($email))
            {
                $email =            $billing_address->getEmail();
            }

            $billing_salutation 	= $billing_address->getPrefix();
            $billing_title       	= $billing_address->getSuffix();
            $billing_firstname 	    = trim($billing_address->getFirstname());
            $billing_lastname  	    = trim($billing_address->getLastname());

            $billing_street1 = $billing_street2 = '';
            try {
                $billing_street1        = trim($billing_address->getStreetLine(1));
                $billing_street2        = trim($billing_address->getStreetLine(2));
            }
            catch(\Exception $e)
            {}

            $billing_street_string  = ($billing_street1 == $billing_street2) ? $billing_street1 : $billing_street1 . " " . $billing_street2;
            $billing_street  	    = trim($billing_street_string);
            //remove multiple whitespaces
            $billing_street         = preg_replace('/\s\s+/', ' ', $billing_street);

            $billing_zip     	    = trim($billing_address->getPostcode());
            $billing_city    	    = trim($billing_address->getCity());
            $billing_country 	    = trim($billing_address->getCountryId());
            $billing_company 	    = trim($billing_address->getCompany() ?? '');


            $shipping_address = $order->getShippingAddress();

            $shipping_salutation 	= $shipping_address->getPrefix();
            $shipping_title       	= $shipping_address->getSuffix();
            $shipping_firstname 	= trim($shipping_address->getFirstname());
            $shipping_lastname  	= trim($shipping_address->getLastname());

            $shipping_street1       = trim($shipping_address->getStreetLine(1));
            $shipping_street2       = trim($shipping_address->getStreetLine(2));

            $shipping_dhlpostnumber = '';
            if(strpos($shipping_street1, 'Packstation') === 0)
            {
                //remove "Nr."
                $shipping_street1 = str_replace('Nr. ', '', $shipping_street1);
                //set Postnumber
                $shipping_dhlpostnumber = $shipping_street2;
                $shipping_street2 = '';
            }
            $shipping_street_string = ($shipping_street1 == $shipping_street2) ? $shipping_street1 : $shipping_street1 . " " . $shipping_street2;
            $shipping_street  	    = trim($shipping_street_string);
            //remove multiple whitespaces
            $shipping_street        = preg_replace('/\s\s+/', ' ', $shipping_street);

            //$shipping_dhlpostnumber = trim($shipping_address->getDhlPostNumber());

            $shipping_zip     	    = trim($shipping_address->getPostcode());
            $shipping_city    	    = trim($shipping_address->getCity());
            $shipping_country 	    = trim($shipping_address->getCountryId());
            $shipping_company 		= '';
            if(!empty($shipping_dhlpostnumber))
            {
                $shipping_company = $shipping_dhlpostnumber;
            }
            else
            {
                $shipping_company = trim($shipping_address->getCompany() ?? '');
            }

            // only export shipping address if different from billing address
            $shipping_same_as_billing   = $shipping_firstname == $billing_firstname
                                            && $shipping_lastname == $billing_lastname
                                            && $shipping_street   == $billing_street
                                            && $shipping_zip      == $billing_zip
                                            && $shipping_city     == $billing_city
                                            && $shipping_country  == $billing_country;

            $telephone	            = $shipping_address->getTelephone();
            $fax		            = $shipping_address->getFax();


            /* payment methods */
            $payment =          $order->getPayment()->getMethodInstance();
            $payment_code   =   $payment->getCode();
            $payment_type   =   isset($this->payment_mapping[$payment_code]) ? $this->payment_mapping[$payment_code] : $payment_code;

            $account_owner = $account_number = $account_blz = $account_swift = $account_iban = '';

            if($payment_code == 'debitpayment')
            {
                $info = $payment->getInfoInstance()->getAdditionalInformation();

                $account_owner  = $info['additional_data']['bank_account_owner'];
                $account_swift  = $info['additional_data']['bic'];
                $account_iban   = $info['additional_data']['iban'];
            }

            /* items */
            $export_data =  [];
            $products =     [];

            foreach($order->getAllItems() as $item)
            {
                $sku      = $this->productRepository->getById($item->getProductId())->getData('spi_sku');
                $quantity = intval($item->getQtyOrdered());

                if(!isset($products[$sku]))
                {
                    $products[$sku] = 0;
                }

                $products[$sku] += $quantity;
            }

            foreach($products as $sku => $quantity)
            {
                $export_data[] = array(
                    self::ORIGINAL_CONTRACT,	// Auftrags-Ursprung
                    $increment_id,				// Bestellnummer
                    $sku,						// Artikelnummer
                    $quantity,					// Ab Werk
                    $customer_id,       		// Kundennummer
                    '',						    // Kontaktart
                    '',					    	// Kontaktdatum
                    '',				    		// Lieferdatum
                    '',			    			// Absprache
                    '',		    				// Dienstleister
                    '',	    					// Dialogservice
                    (empty($coupon_code) ? '' : '#' . $coupon_code),    // Änderung (#CouponCode)
                    $billing_salutation,		// Anrede
                    $billing_title,				// Titel
                    $billing_firstname,			// Vorname
                    $billing_lastname,			// Name

                    $billing_street,			// Straße, Hsnr.
                    $billing_country,			// Land
                    $billing_zip,				// PLZ
                    $billing_city,				// Ort
                    '', 						// Ortszusatz
                    $telephone,				    // Telefon
                    $fax,						// Telefax

                    $email,						// E-Mail
                    '',						    // Homepage
                    $day_of_birth,	   			// Geburtstag
                    '',			    			// Anschreiben an
                    $customer_external_id,  	// Externe-Kundennummer
                    $payment_type,	    		// Bezahlart
                    $account_owner,				// Kontoinhaber
                    $account_number,			// Kontonummer
                    $account_blz,				// Bankleitzahl
                    $account_swift,				// Swift-BIC
                    $account_iban,			    // IBAN

                    ($shipping_same_as_billing) ? '' : $shipping_salutation,				    // Anrede (Lieferanschrift)
                    ($shipping_same_as_billing) ? '' : $shipping_title,						// Titel (Lieferanschrift)
                    ($shipping_same_as_billing) ? '' : $shipping_firstname,				    // Vorname (Lieferanschrift)
                    ($shipping_same_as_billing) ? '' : $shipping_lastname,					// Name (Lieferanschrift)
                    ($shipping_same_as_billing) ? '' : $shipping_street,			// Straße, Hsnr. (Lieferanschrift)
                    ($shipping_same_as_billing) ? '' : $shipping_country,			// Land (Lieferanschrift)
                    ($shipping_same_as_billing) ? '' : $shipping_zip,				// PLZ (Lieferanschrift)
                    ($shipping_same_as_billing) ? '' : $shipping_city,				// Ort (Lieferanschrift)
                    '', 						// Ortszusatz
                    '', 						// Leerfeld
                    '', 						// Leerfeld
                    $billing_company, 			// Firmenname
                    $shipping_company, 			// Firmenname (Lieferanschrift)

                    'END',						// END
                );
            }

            foreach($export_data as $csv)
            {
                fputcsv($file_pointer, $csv, ';');
            }

            // return the order id to log the last exported id for differential exports
            return $order->getId();
        }

        protected function write_csv_head_row($file_pointer)
        {
            fputcsv($file_pointer, array("Auftrags-Ursprung",
                    "Bestellnummer",
                    "Artikelnummer",
                    "Ab Werk",
                    "Kundennummer",
                    "Kontaktart",
                    "Kontaktdatum",
                    "Lieferdatum",
                    "Absprache",
                    "Dienstleister",
                    "Dialogservice",
                    "Änderung",
                    "Anrede",
                    "Titel",
                    "Vorname",
                    "Name",
                    "Straße, Hsnr.",
                    "Land",
                    "PLZ",
                    "Ort",
                    "Ortszusatz",
                    "Telefon",
                    "Telefax",
                    "E-Mail",
                    "Homepage",
                    "Geburtstag",
                    "Anschreiben an",
                    "Externe-Kundennummer",
                    "Bezahlart",
                    "Kontoinhaber",
                    "Kontonummer",
                    "Bankleitzahl",
                    "BIC",
                    "IBAN",
                    "LA_Anrede",
                    "LA_Titel",
                    "LA_Vorname",
                    "LA_Name",
                    "LA_Straße, Hsnr.",
                    "LA_Land",
                    "LA_PLZ",
                    "LA_Ort",
                    "LA_Ortszusatz",
                    "Leerfeld",
                    "Leerfeld",
                    "Firmenname",
                    "LA_Firmenname",
                    "END"
                ), ';');
        }
    }
