<?php

namespace App\Controller\Base;

use App\Electronico\Comprobante;
use App\Entity\Model\AbstractInvoice;
use App\Entity\Model\Item;
use App\Entity\Model\Ncredito;
use App\Util\RestApiFunciones;
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 AbstractCreditoController extends AbstractController
{
    protected function cargarImpuestos(AbstractInvoice $credito)
    {
        $basecero = 0;
        $baseiva = 0;

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

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

            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) {
                        //continue;
                        $iva = $subtotal * ($porcentaje / 100);

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

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

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


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

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

        $credito->setBasecero($basecero);
        $credito->setBaseiva($baseiva);
    }

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

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

            $error = false;

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

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

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

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

        return $respuesta;
    }

    protected function generarXml(Ncredito $credito)
    {
        try {
            $empresa = $credito->getEmpresa();

            $serie = $credito->getSerie();

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

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

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

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

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

            $error = false;
            $notacredito = $emisor->generarXmlCredito($credito, $error);

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


            try {
                $serializer = SerializerBuilder::create()->build();
                $xml = $serializer->serialize($notacredito, 'xml');
                $xml = trim(preg_replace('/\s+/', ' ', $xml));
                $credito->setXml($xml);

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

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

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

        return $credito;
    }

    protected function getNcreditoTotalsFromPost(array $post, AbstractInvoice $credito, 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($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) {
                    continue;
                }
                $item->setTaxes($tax);
                //}

                //$item->setTaxes($postItem['taxes']);
            }
            $totals['items'][$index] = [
                'gross_amount' => $formatter->formatCurrency($item->getGrossAmount(), $currency),
            ];
            $credito->addItem($item);
        }
        $credito->checkAmounts();

        $totals += [
            'invoice_base_amount' => $formatter->formatCurrency($credito->getBaseAmount(), $currency),
            'invoice_tax_amount' => $formatter->formatCurrency($credito->getTaxAmount(), $currency),
            'invoice_gross_amount' => $formatter->formatCurrency($credito->getGrossAmount(), $currency),
            'pago_gross_amount' => 0,
        ];

        return $totals;
    }

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

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

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

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

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

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

        $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 $creditos)
    {
        $pages = [];
        foreach ($creditos as $credito) {
            $pages[] = $this->getInvoicePrintPdfHtml($credito, true);
        }

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

        return new Response($html);
    }

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

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

    protected function generarPdf(Ncredito $credito)
    {
        $filename = 'NC_' . $credito->getSerie() . "-" . str_pad($credito->getNumber(), 9, '0', STR_PAD_LEFT) . '.pdf';

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

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

        $app_url .= 'ncreditoride.php';

        $error = false;
        $mensaje = "";
        $docPdf = RestApiFunciones::getPdf($error, $app_url, $credito->getClaveAcceso(), $xml, $mensaje, $credito->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(Ncredito $credito)
    {
        $em = $this->getDoctrine()->getManager();

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

            return true;
        }
    }

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

        $xmlAutorizado = null;

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

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

        $error = false;
        $mensaje = "";

        //$filename = 'FAC_' . $credito->getSerie() . "-" . str_pad($credito->getNumber(), 9, '0', STR_PAD_LEFT) . '.pdf';

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

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

        $app_url .= 'ncreditoride.php';

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

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

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

