<?php

namespace App\Controller\Base;

use App\Electronico\Comprobante;
use App\Entity\Model\AbstractInvoice;
use App\Entity\Model\Empresa;
use App\Entity\Model\Invoice;
use App\Entity\Model\Item;
use App\Util\RestApiFunciones;
use Doctrine\Common\Annotations\AnnotationRegistry;
use DOMDocument;
use JMS\Serializer\SerializerBuilder;
use Symfony\Component\Config\Definition\Exception\Exception;
use Symfony\Component\Form\Extension\Core\DataTransformer\MoneyToLocalizedStringTransformer;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;

abstract class AbstractInvoiceController extends AbstractController
{

    protected function cargarImpuestos(AbstractInvoice $invoice)
    {
        $basecero = 0;
        $baseiva = 0;
        $valiva=0;
        $base_iva5 = 0;

        foreach ($invoice->getItems() as $item) {

            //$item = new Item();$iva = 0;
            $p = $item->getProduct();

            if($p)
                $item->setProduct($p);

            //$item = new Item();
            if($item->getDiscount()*1 >= 100)
                $item->setDiscount($item->getDiscountPercent());

            $item->setNeto($item->getNetAmount());
            $item->setValdescuento($item->getDiscountAmount());

            $subtotal = $item->getQuantity() * $item->getUnitaryCost();

            if ($item->getTaxes() != null) {

                $tax = $item->getTaxes();
                //foreach ($postItem['taxes'] as $taxId) {
                //$tax = $taxRepo->find($taxId);
                //$tax = new Tax();
                if ($tax != null) {
                    $porcentaje = (double)$tax->getValue();
                    if ($porcentaje > 0) {
                        if($porcentaje == 5 || $porcentaje == 5.00){
                            $iva = $item->getNeto() * ($porcentaje / 100);

                            //$baseiva += $subtotal;
                            $base_iva5 += $item->getNeto();
                            $valiva += $iva;

                            $item->setValiva($iva);
                            $item->addTax($tax);
                            $item->setSubtotal($subtotal);
                            $invoice->setPorIva($tax->getValue());
                        }
                        else {
                            $iva = $item->getNeto() * ($porcentaje / 100);

                            //$baseiva += $subtotal;
                            $baseiva += $item->getNeto();
                            $valiva += $iva;

                            $item->setValiva($iva);
                            $item->addTax($tax);
                            $item->setSubtotal($subtotal);
                            $invoice->setPorIva($tax->getValue());
                        }
                    } else {
                        $basecero += $item->getNeto();

                        $item->setValiva(0);
                        $item->addTax($tax);
                        $item->setSubtotal($subtotal);
                        //$invoice->setPorIva($tax->getValue());
                    }
                }
            }


            //$item->addTax($tax);
            //}
            /*} else {
                $basecero += $subtotal;

                $item->setSubtotal($subtotal);
                $item->setValIva($iva);
            }
            */
        }

        $invoice->setTotalFactura($basecero+$baseiva+$valiva+$base_iva5);
        $invoice->setBasecero($basecero);
        $invoice->setBaseiva($baseiva);

        $invoice->setBaseIva5($base_iva5);
    }

    protected function consultarAutorizacion(Invoice $invoice)
    {
        $respuesta = null;
        try {
            $em = $this->getDoctrine()->getManager();

            $app_url = $this->getParameter('api_url');

            $error = false;

            $resp = RestApiFunciones::consultarAutoComprobante($error, $app_url, $invoice->getClaveAcceso());

            if ($error) {
                $this->addTranslatedMessage($resp, 'danger');
                $invoice->setSinrespuesta(true);
                $invoice->setMensajeError($resp);
                $em->persist($invoice);
                $em->flush();

            } else {
                if ($resp->autorizado) {
                    $this->addTranslatedMessage('Comprobante autorizado, fecha: ' . $resp->fecha);
                    $invoice->setAutorizado(true);
                    $invoice->setSinrespuesta(false);
                    $invoice->setMensajeError("");
                    $invoice->setFechaAutorizacion($resp->fecha);
                    $invoice->setXmlAutorizado($resp->comprobante);
                    $invoice->setStatus(Invoice::CLOSED);
                    $invoice->setForcefullyClosed(true);
                    $em->persist($invoice);
                    $em->flush();

                } else {
                    $this->addTranslatedMessage($resp, 'danger');
                }
            }
        } catch (Exception $e) {
            return $e->getMessage();
        }

        return $respuesta;
    }

    public $logger;

    protected function generarXml(Invoice $invoice, $codigosaux=null)
    {
        try {
            $empresa = $invoice->getEmpresa();
            //$empresa = new Empresa();

            $serie = $invoice->getSerie();

            $numero = str_pad($invoice->getNumber(), 9, "0", STR_PAD_LEFT);

            $emisor = new Comprobante(null, $empresa, $serie);

            $resp = $emisor->generaClave($invoice->getIssueDate()->format('d/m/Y'), "01", $numero);

            if ($resp !== null) {
                $this->addTranslatedMessage($resp, 'danger');
                return null;
            }

            $invoice->setClaveAcceso($emisor->getClaveAcceso());

            $codauxtransporte = null;
            if($empresa->getTipoTransportista() && $codigosaux) {
                if($empresa->getTipoTransportista() !== 'X') {

                    if($empresa->getTipoTransportista() === '3')
                        $codauxtransporte = $codigosaux['codauxsocio'];
                    elseif($empresa->getTipoTransportista() === '2' || $empresa->getTipoTransportista() === '1' )
                        $codauxtransporte = $codigosaux['codauxoperadora'];

                }
            }

            $error = false;
            $factura = $emisor->generarXml($invoice, $error, $codauxtransporte);

            if ($error)
                $this->addTranslatedMessage($factura, 'danger');

            try {
                $serializer = SerializerBuilder::create()->build();
                $xml = $serializer->serialize($factura, 'xml');

                $dom = new DOMDocument("1.0","UTF-8");
                $dom->loadXML($xml);
                $xml = $dom->saveXML(null, LIBXML_NOEMPTYTAG);
                $xml = trim(preg_replace('#\s+#', ' ', $xml));
                $invoice->setXml($xml);

            } catch (Exception $e) {
                $this->addTranslatedMessage($e->getMessage(), 'danger');
                return null;
            }

            $em = $this->getDoctrine()->getManager();
            $em->persist($invoice);
            $em->flush();

        } catch (Exception $e) {
            $this->addTranslatedMessage($e->getMessage(), 'danger');
            return null;
        }

        return $invoice;
    }

    protected function getInvoiceTotalsFromPost(array $post, AbstractInvoice $invoice, string $locale): array
    {
        $user = $this->getUser();

        $em = $this->getDoctrine()->getManager();

        $empresaRepo = $em->getRepository('App\Entity\Model\Empresa');
        $empresa = $empresaRepo->findOneByUser($user->getRuc());

        $taxRepo = $em->getRepository('App\Entity\Model\Tax');
        //$currency = $em->getRepository('SiwappConfigBundle:Property')->get('currency', 'EUR');
        $currency = $empresa == null ? 'USD' : $empresa->getCurrency();
        $formatter = new \NumberFormatter($locale, \NumberFormatter::CURRENCY);
        //$transformer = new MoneyToLocalizedStringTransformer(2, true);
        $transformer = new MoneyToLocalizedStringTransformer($empresa->getDecPunit(), true);

        $totals = [];

        foreach ($post['items'] as $index => $postItem) {
            $item = new Item($taxRepo->findTaxDefault($empresa->getId()));
            $item->setUnitaryCost($transformer->reverseTransform($postItem['unitary_cost']));
            $item->setQuantity($postItem['quantity']);
            $item->setDiscount($postItem['discount_percent']);
            if (isset($postItem['taxes'])) {
                //foreach($postItem['taxes'] as $taxId) {
                $tax = $taxRepo->find($postItem['taxes']);
                if ($tax)
                    $item->setTaxes($tax);

            }

            $servicio = false;
            if (isset($postItem['product']))
                if (strlen($postItem['product']) === 0)
                    $servicio = true;

            $totals['items'][$index] = [
                'gross_amount' => $formatter->formatCurrency($item->getGrossAmount(), $currency),
                'servicio' => $servicio
            ];

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

        $pagoTotal = 0;
        foreach ($post['pagos'] as $index => $pago) {
            $pagoTotal += $transformer->reverseTransform($pago['valor']);
        }

        $totals += [
            'invoice_base_amount' => $formatter->formatCurrency($invoice->getBaseAmount(), $currency),
            'invoice_discount_amount' => $formatter->formatCurrency($invoice->getDiscountAmount(), $currency),
            'invoice_tax_amount' => $formatter->formatCurrency($invoice->getTaxAmount(), $currency),
            'invoice_gross_amount' => $formatter->formatCurrency($invoice->getGrossAmount(), $currency),
            'pago_gross_amount' => number_format($invoice->getGrossAmount(), 2),
        ];

        return $totals;
    }

    protected function addTranslatedMessage($message, $status = 'success')
    {
        $this->get('session')
            ->getFlashBag()
            ->add($status, $this->translator->trans($message, [], 'invoice'));
    }

    protected function bulkDelete(array $invoices)
    {
        $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');

        $em = $this->getDoctrine()->getManager();

        foreach ($invoices as $invoice) {
            $em->remove($invoice);
        }
        $em->flush();
        $this->addTranslatedMessage('flash.bulk_deleted');

        return $this->redirect($this->generateUrl('invoice_index'));
    }

    protected function bulkPdf(array $invoices)
    {
        $pages = [];
        foreach ($invoices as $invoice) {
            $pages[] = $this->getInvoicePrintPdfHtml($invoice);
        }

        $html = $this->get('siwapp_core.html_page_merger')->merge($pages, '<div class="pagebreak"> </div>');
        $pdf = $this->getPdf($html);

        return new Response($pdf, 200, [
            'Content-Type' => 'application/pdf',
            'Content-Disposition' => 'attachment; filename="Invoices.pdf"'
        ]);
    }

    protected function bulkPrint(array $invoices)
    {
        $pages = [];
        foreach ($invoices as $invoice) {
            $pages[] = $this->getInvoicePrintPdfHtml($invoice, true);
        }

        $html = $this->get('siwapp_core.html_page_merger')->merge($pages, '<div class="pagebreak"> </div>');

        return new Response($html);
    }

    protected function bulkEmail(array $invoices)
    {
        $em = $this->getDoctrine()->getManager();
        foreach ($invoices as $invoice) {
            $message = $this->getEmailMessage($invoice);
            $result = $this->get('mailer')->send($message);
            if ($result) {
                $invoice->setSentByEmail(true);
                $em->persist($invoice);
            }
        }
        $em->flush();
        $this->addTranslatedMessage('flash.bulk_emailed');

        return $this->redirect($this->generateUrl('invoice_index'));
    }

    protected function generarPdf(Invoice $invoice)
    {
        $filename = 'FAC_' . $invoice->getSerie() . "-" . str_pad($invoice->getNumber(), 9, '0', STR_PAD_LEFT) . '.pdf';

        if ($invoice->getAutorizado())
            $xml = $invoice->getXmlAutorizado();
        else
            $xml = $invoice->getXml();

        $app_url = $this->getParameter('api_url').'facturaride.php';

        $error = false;
        $mensaje = "";
        $docPdf = RestApiFunciones::getPdf($error, $app_url, $invoice->getClaveAcceso(), $xml, $mensaje, $invoice->getEmpresa()->getRuc());

        if ($error) {
            $this->addTranslatedMessage('ERRROR AL GENERAR EL PDF, ' . $mensaje, 'danger');
        } else {
            file_put_contents($filename, $docPdf);

            header("Cache-Control: public");
            header("Content-Description: File Transfer");
            header("Content-Disposition: attachment; filename=$filename");
            header("Content-Type: application/pdf");
            header('Content-Length: ' . filesize($filename));
            //header("Content-Transfer-Encoding: binary");
            header('Accept-Ranges: bytes');
            echo $docPdf;

            try {
                unlink($filename);
            } catch (\Exception $ex) {

            }

        }
    }

    protected function delete(Invoice $invoice)
    {
        $em = $this->getDoctrine()->getManager();

        if ($invoice->getAutorizado() && $invoice->getAmbiente() == 2 ) {
            $this->addTranslatedMessage('Factura no puede ser eliminada, estado: AUTORIZADO, ambiente: PRODUCCION', 'warning');
            return false;
        } else {
            $em->remove($invoice);
            $em->flush();
            $this->addTranslatedMessage('flash.deleted');

            return true;
        }
    }

    protected function enviarMail($email, Invoice $invoice)
    {
        $em = $this->getDoctrine()->getManager();

        $xmlAutorizado = null;

        if ($invoice->getAutorizado())
            $xmlAutorizado = $invoice->getXmlAutorizado();

        $numero = $invoice->getSerie() . '-' . str_pad($invoice->getNumber(), 9, '0', STR_PAD_LEFT);

        $error = false;
        $mensaje = "";

        if ($invoice->getAutorizado())
            $data = $invoice->getXmlAutorizado();
        else
            $data = $invoice->getXml();

        $app_url = $this->getParameter('api_url');

        $app_url .= 'facturaride.php';

        $docPdf = RestApiFunciones::getPdf($error, $app_url, $invoice->getClaveAcceso(), $data, $mensaje, $invoice->getEmpresa()->getRuc());

        if ($error) {
            $this->addTranslatedMessage('ERRROR AL GENERAR EL PDF, ' . $mensaje, 'danger');
        } else {
            $result = RestApiFunciones::envioMailComprobante(
                $invoice->getCustomerName(),
                $numero,
                $invoice->getClaveAcceso(),
                $invoice->getFechaAutorizacion(),
                "Factura",
                $email,
                $docPdf,
                $xmlAutorizado,
                $invoice->getEmpresa()
            );

            if ($result) {
                $this->addTranslatedMessage('MENSAJE ENVIADO A: ' . $email);
                $invoice->setSentByEmail(true);
                $em->persist($invoice);
                $em->flush();
            } else
                $this->addTranslatedMessage('ERRROR, ' . $result, 'danger');
        }
    }
}

