<?php
defined('BASEPATH') or exit('No direct script access allowed');

require $_SERVER['DOCUMENT_ROOT'] . '/public/order/autoload.php';

use \SzamlaAgent\SzamlaAgentAPI;
use \SzamlaAgent\Buyer;
use \SzamlaAgent\Document\Invoice\Invoice;
use \SzamlaAgent\Item\InvoiceItem;
use \SzamlaAgent\Ledger\InvoiceItemLedger;
use \SzamlaAgent\Log;
use \SzamlaAgent\Currency;
use \SzamlaAgent\Language;
use \SzamlaAgent\Seller;
use \SzamlaAgent\TaxPayer;

class SzamlaAgent
{
    public $error;

    private $db;
    private $debug = false;

    private $ctrID;
    private $partner;
    private $invoiceData;

    private $tax        = TaxPayer::TAXPAYER_HAS_TAXNUMBER;
    private $currency   = Currency::CURRENCY_EUR;
    private $lang       = Language::LANGUAGE_EN;
    private $prefix     = "EU";
    private $invPrefix  = "EUR";
    private $afa_key;
    private $period;

    private $invoice;

    function __construct($ctrID, $invoiceData, $period)
    {
        $this->ctrID        = $ctrID;
        $this->invoiceData  = $invoiceData;
        $this->period       = $period;
        $this->db           = &get_instance();

        if ($this->ctrID == '37')
            $this->debug = true;

        $this->setGeneralDatas();
        $this->setPartner();
    }

    private function agent()
    {
        if ($this->debug)
            $key = 'kjjyxaexnidzkjek22c4nidzkjmn3g8dnidzkj6ip2'; // Teszt Kulcs
        else
            $key = '3i73vj72wt7h3ig78wrawt7h3ik5batswt7h3inhzw'; // CADLine kulcs

        $agent = SzamlaAgentAPI::create($key, false, Log::LOG_LEVEL_DEBUG);
        $agent->setXmlFileSave(false);

        return $agent;
    }

    function createInvoice()
    {
        if (empty($this->partner))
            return true;

        try {
            $agent = $this->agent();

            if ($this->debug)
                $this->invoice = new Invoice(Invoice::INVOICE_TYPE_P_INVOICE); //Teszt Szamla
            else
                $this->invoice = new Invoice(Invoice::INVOICE_TYPE_E_INVOICE); // Elektronikus Szamla

            $this->setHeader();
            $this->setSeller();
            $this->setBuyer();

            $product = $this->getInvoiceProduct();
            $comment = $this->getComment();

            $quantity = $product->mennyiség;

            if ($this->invoiceData->category == 'lan' && $this->invoiceData->lan)
                $quantity = $this->invoiceData->lan;

            $itemData               = new stdClass();
            $itemData->productName  = $product->megnevezés;
            $itemData->price        = $this->invoiceData->price;
            $itemData->unit         = $product->egység;
            $itemData->comment      = $comment;
            $itemData->vat          = 0;
            $itemData->quantity     = $quantity;
            $itemData->ledgerNumber = $product->árbevétel_főkönyvi_szám;

            $this->addItem($itemData, true);

            if ($this->invoiceData->category != 'lan' && $this->invoiceData->lan) {
                $quantity = $this->invoiceData->lan - 1;

                if ($this->afa_key == "EUK")
                    $ledgerNumber = 931;
                else
                    $ledgerNumber = 9312;

                $inv = $this->db->db->query("SELECT t.megnevezés AS invName, t.egység AS unit
                    FROM szamla_agent.web_product wp
                    LEFT JOIN szamla_agent.termekek t ON wp.product_id = t.id
                    WHERE wp.web_id = {$this->invoiceData->id}")->row();

                $itemData               = new stdClass();
                $itemData->productName  = $inv->invName;
                $itemData->price        = Product::getLanPrice($this->ctrID, $this->invoiceData->type);
                $itemData->unit         = $inv->unit;
                $itemData->comment      = "{$this->invoiceData->hlNum}";
                $itemData->vat          = 0;
                $itemData->quantity     = $quantity;
                $itemData->ledgerNumber = $ledgerNumber;

                $this->addItem($itemData, true);
            }

            if ($this->invoiceData->hardlock) {
                if ($this->afa_key == "EUK")
                    $ledgerNumber = 931;
                else
                    $ledgerNumber = 9313;

                $itemData               = new stdClass();
                $itemData->productName  = $this->prefix . " ARCHLine.XP Hardlock";
                $itemData->price        = Product::getHardlockPrice($this->ctrID);
                $itemData->unit         = $product->egység;
                $itemData->comment      = "{$this->invoiceData->hlNum}";
                $itemData->vat          = 0;
                $itemData->ledgerNumber = $ledgerNumber;

                $this->addItem($itemData);
            }

            if ($this->invoiceData->floating_lic) {
                if ($this->afa_key == "EUK")
                    $ledgerNumber = 9313;
                else
                    $ledgerNumber = 9311;

                $itemData               = new stdClass();
                $itemData->productName  = $this->prefix . " ARCHLine.XP Floating License";
                $itemData->price        = Product::getFloatingPrice($this->ctrID);
                $itemData->unit         = $product->egység;
                $itemData->vat          = 0;
                $itemData->ledgerNumber = $ledgerNumber;

                $this->addItem($itemData);
            }

            if ($this->invoiceData->live) {
                if ($this->afa_key == "EUK")
                    $ledgerNumber = 931;
                else
                    $ledgerNumber = 9312;

                $itemData               = new stdClass();
                $itemData->productName  = $this->prefix . " ARCHLine.XP LIVE License";
                $itemData->price        = Product::getLivePrice($this->ctrID);
                $itemData->unit         = $product->egység;
                $itemData->comment      = "{$this->invoiceData->hlNumLive}";
                $itemData->vat          = 0;
                $itemData->ledgerNumber = $ledgerNumber;

                $this->addItem($itemData);
            }

            if ($this->invoiceData->prevSoftware) {
                $itemData               = new stdClass();
                $itemData->productName  = "Previous software(s)";
                $itemData->price        = Product::getPrevSoftwarePrice($this->ctrID);
                $itemData->unit         = $product->egység;
                $itemData->vat          = 0;

                $this->addItem($itemData);
            }

            if ($this->invoiceData->module) {
                $itemData               = new stdClass();
                $itemData->productName  = "{$this->invoiceData->module} Module";
                $itemData->price        = $this->invoiceData->modulePrice;
                $itemData->unit         = $product->egység;
                $itemData->vat          = 0;
                $itemData->quantity     = $product->mennyiség;
                $needQuantity           = $this->invoiceData->sub ? true : false;

                $this->addItem($itemData, $needQuantity);
            }

            if ($this->invoiceData->credit) {
                $itemData               = new stdClass();
                $itemData->productName  = "Non Recurring Discount";
                $itemData->price        = -$this->invoiceData->creditPrice;
                $itemData->unit         = $product->egység;
                $itemData->vat          = 0;

                $this->addItem($itemData);
            }

            return $agent->generateInvoice($this->invoice);
        } catch (\Exception $e) {
            if ($this->ctrID == '37')
                $this->error = $e->getMessage();
            else
                $this->error = 'Cannot create invoice.';

            return false;
        }
    }

    private function addItem($itemData, $mainProduct = false)
    {
        $needPeriod = Product::needPeriod($this->invoiceData->category, $this->invoiceData->type, $this->period);
        $quantity   = $mainProduct ? $itemData->quantity : floatval(1);
        $price      = $needPeriod ? round($itemData->price / $this->period, 2) : $itemData->price;
        $brut       = $price * $quantity;

        /*
        In this case, the user receives the perpetual  license only after paying the full price.
        The instalments are considered as a software subscription, which we invoice as a monthly subscription fee.
        The last invoice will include the purchase of the license (perpetual license) and the total amount will be indicated here.
        However, you will pay the same amount as in the previous months, because the subscription fees paid in the previous months will be shown as minus items.

        Attention, the user always receives the license activation code one month in advance. You will have the final infinite activation code only after we receive the full amount of the license purchase price.
 
        According to the above, the automatic invoice you received today has been cancelled and instead you received the new invoice for the first monthly payment that must be paid within 8 days.
        */
        $item = new InvoiceItem($itemData->productName, $price, $quantity, $itemData->unit, $this->afa_key);

        if ($needPeriod)
            $itemData->comment .= ' Perpetual subscription monthly fee';

        if ($itemData->comment != '')
            $item->setComment($itemData->comment);

        $item->setNetPrice($brut);
        $item->setVatAmount($itemData->vat);
        $item->setGrossAmount($brut);
        $item->setGrossAmount($brut);

        if ($itemData->ledgerNumber != '') {
            $itemLedger = new InvoiceItemLedger('', '', strval($itemData->ledgerNumber), '');
            $item->setLedgerData($itemLedger);
        }

        $this->invoice->addItem($item);
    }

    private function getInvoiceProduct()
    {
        $product = $this->db->db->query("SELECT * FROM szamla_agent.termekek WHERE id = {$this->invoiceData->productID}")->row();

        if ($this->invoiceData->sub)
            $product->mennyiség = floatval(3);
        else
            $product->mennyiség = floatval(1);

        return $product;
    }

    private function getComment()
    {
        if (!empty($this->invoiceData->serialArray)) {
            $hlNumArray = array();

            for ($i = 0; $i < count($this->invoiceData->serialArray); $i++) {
                array_push($hlNumArray, substr($this->invoiceData->serialArray[$i], 0, 6));
            }

            return implode(", ", $hlNumArray);
        }

        // ITC-nel a $comment, ha van instalments
        /*
        301073 
        1st partial payment: számla kiállitás + 8 nap
        2nd partial payment: 1st partial payment + 30 days
        3rd partial payment: 1st partial payment + 60 days
        */

        if ($this->invoiceData->category == 'subscription') {
            $datetime = new DateTime($this->invoiceData->expirationDate);
            $datetime->modify('-30 day');

            $from       = date('d/m/Y');
            $to         = $datetime->format('t/m/Y');
            $comment    = "{$this->invoiceData->hlNum} Billing Period: {$from} - {$to}";
        } else {
            if ($this->invoiceData->inclLive) {
                if ($this->ctrID == '33')
                    $comment = "Client: {$this->invoiceData->name} - Prof: {$this->invoiceData->hlNum}, Live: {$this->invoiceData->hlNumLive}";
                else
                    $comment = "Prof: {$this->invoiceData->hlNum}, Live: {$this->invoiceData->hlNumLive}";
            } else {
                if ($this->ctrID == '33')
                    $comment = "Client: {$this->invoiceData->name} - Serial: {$this->invoiceData->hlNum}";
                else
                    $comment = "{$this->invoiceData->hlNum}";
            }
        }

        return $comment;
    }

    private function setHeader()
    {
        $paymentDue = $this->getPaymentDue();

        $header = $this->invoice->getHeader();

        $header->setPaymentMethod(Invoice::PAYMENT_METHOD_TRANSFER);
        $header->setCurrency($this->currency);
        $header->setLanguage($this->lang);
        $header->setPaymentDue($paymentDue);
        $header->setOrderNumber($this->invoiceData->orderNumber);
        $header->setComment("*Please use the invoice number (E-EUR-" . date('Y') . "-xxx) as a reference number to identify your payment.

                Banktransfer info:
                K&H BANK Hungary
                IBAN: HU89 1040 0951 4955 4949 4954 1028
                SWIFT CODE: OKHBHUHB");

        if (!$this->debug)
            $header->setPrefix($this->invPrefix);

        $this->invoice->setHeader($header);
    }

    private function setSeller()
    {
        $seller = new Seller('K&H Bank EUR', 'IBAN: HU89 1040 0951 4955 4949 4954 1028');
        $seller->setEmailReplyTo('office@cadline.hu');
        $seller->setEmailSubject('Számlaértesítő / Invoice - CadLine Kft.');
        $seller->setEmailContent('Tisztelt/Dear ' . $this->partner->kapcsolattartó_neve . ',


            Mellékelten küldjük aktuális számláját.
                Kérjük, utaláskor a közlemény rovatban KIZÁRÓLAG a számlaszámot tüntesse fel! (pl.: E-HUF-' . date('Y') . '-xxxx)

                Amennyiben ezzel kapcsolatban bármilyen kérdése merülne fel, kérjük hívja Ügyfélszolgálatunkat, ahol munkatársaink készséggel állnak ügyfeleink rendelkezésére.

                Cadline Ltd invoice is attached. Please use the invoice number (E-EUR-' . date('Y') . '-xxx) as a reference number to identify your payment. Payment made via wire transfer must be made in full including any fees/charges for the wire transfer, which are your responsibility. (If your bank uses an intermediary bank, there may be additional charges.) If payment is not received in full, you will be invoiced for any balance due on the account.
                Payment must be completed by the "due date" of the invoice date.


                Üdvözlettel / Sincerely:
                CadLine Office');
        $this->invoice->setSeller($seller);
    }

    private function setBuyer()
    {
        $buyer = new Buyer($this->partner->partner, $this->partner->irányítószám, $this->partner->település, $this->partner->utca_házszám);
        $buyer->setTaxPayer($this->tax);

        if ($this->partner->közösségi_adószám != '')
            $buyer->setTaxNumberEU($this->partner->közösségi_adószám);
        elseif ($this->partner->adószám != "")
            $buyer->setTaxNumber($this->partner->adószám);

        if ($this->prefix == 'Non-EU')
            $this->afa_key = 'EUK';

        if ($this->prefix == 'EU')
            $this->afa_key = 'EU';

        $buyer->setEmail($this->partner->email);
        $buyer->setSendEmail(true);
        $this->invoice->setBuyer($buyer);
    }

    private function setPartner()
    {
        $partner = $this->db->db->query("SELECT * FROM szamla_agent.partnerek WHERE active = 1 AND ország = '{$this->ctrID}'")->row();

        if ($partner->közösségi_adószám == '' && $partner->adószám == "")
            $this->tax = TaxPayer::TAXPAYER_NO_TAXNUMBER;

        $this->partner = $partner;
    }

    private function getPaymentDue()
    {
        if ($this->ctrID == 55) {
            $date = new DateTime(date('Y-m'));
            $date->modify('+ 1 month');
            $paymentDue = $date->format('Y-m') . '-15';
        } else {
            $date = new DateTime(date('Y-m-d'));
            $date->modify('+' . $this->partner->fizetési_határidő . " day");
            $paymentDue = $date->format('Y-m-d');
        }

        return $paymentDue;
    }

    private function setGeneralDatas()
    {
        switch ($this->ctrID) {
            case '49': // Nemetorszag
                $this->lang = Language::LANGUAGE_DE;
                break;

            case '38': // Horvatorszag
                $this->lang = Language::LANGUAGE_HR;
                break;

            case '33': // Franciaorszag
                $this->lang = Language::LANGUAGE_FR;
                break;

            case '42': // Csehorszag
                $this->lang = Language::LANGUAGE_CZ;
                break;

            case '48': // Lengyelorszag
                $this->lang = Language::LANGUAGE_PL;
                break;

            case '34': // Spanyolorszag
                $this->lang = Language::LANGUAGE_ES;
                break;

            case '82':  //Korea
                $this->prefix = "Non-EU";
                break;

            case '61':  //Ausztralia
                $this->prefix = "Non-EU";
                break;

            case '88':  //Tajvan
                $this->prefix = "Non-EU";
                break;

            case '44':  //UK
                $this->prefix = "Non-EU";
                break;

            case '84':  //Vietnam
                $this->prefix = "Non-EU";
                break;

            case '52':  //Mexiko
                $this->prefix = "Non-EU";
                break;

            case '60':  //Malajzia
                $this->prefix = "Non-EU";
                break;

            case '65':  //Szingapur
                $this->prefix = "Non-EU";
                break;

            case '11': // USA
                $this->currency     = Currency::CURRENCY_USD;
                $this->prefix       = "Non-EU";
                $this->invPrefix    = "USD";
                break;

            case '55':  // Brazilia
                $this->prefix = "Non-EU";
                break;

            case '91':  // India
                $this->prefix = "Non-EU";
                break;

            case '13':  // Peru
                $this->prefix = "Non-EU";
                break;

            default: // Minden mas
                break;
        }

        return true;
    }
}
