<?php
namespace App\Controller;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

use Symfony\Component\Form\Form;

use App\Entity\Hosting;
use App\Entity\Dominio;
use App\Entity\PlanCosto;
use App\Entity\Correlativo;
use App\Entity\OrdenCompra;
use App\Entity\OrdenHosting;
use App\Entity\OrdenDominio;
use App\Entity\ExtensionCosto;
use App\Entity\Transferencia;
use App\Entity\Deposito;

use App\Form\Orden\OrdenCompraNuevoType;
use App\Form\Orden\OrdenCompraProcesarType;
use App\Form\Orden\OrdenCompraPagarType;


use Transbank\Webpay\{Configuration, Webpay};


class OrdenController extends AbstractController
{
    public function pagar(Request $request, $id) {

        $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED');

        $orden = $this->getDoctrine()->getRepository(OrdenCompra::class)->find($id);

        if(!$orden || ($this->getUser()->getId() != $orden->getUsuario()->getId() || $orden->getEstatus() != OrdenCompra::ESTATUS_PENDIENTE)
            ) {
            return $this->redirectToRoute('orden_listar');
        }

        $transf = new Transferencia();
        $deposito = new Deposito();
        $orden->addTransferencia($transf);
        $orden->addDeposito($deposito);

        $form = $this->createForm(OrdenCompraPagarType::class, $orden);
        $form->handleRequest($request);

        if ($form->isSubmitted()) {
            if($form->isValid()) {

                $this->limpiarPagos($form, $orden);
                $objDB = $this->getDoctrine()->getManager();
                $objDB->getConnection()->beginTransaction();
                $orden->setEstatus(OrdenCompra::ESTATUS_PAGADA);
                $objDB->persist($orden);
                $objDB->flush();
                $objDB->getConnection()->commit();
                $this->addFlash('success', 'Su informacion de pago ha sido guardada exitosamente');
                return $this->redirectToRoute('orden_ver', [
                    'id' => $orden->getId()
                ]);
            }
        }

        return $this->render('website/orden/pagar.html.twig', [
            'form' => $form->createView(),
            'orden' => $orden
        ]);
    }

    private function limpiarPagos(Form $form, OrdenCompra $ordenCompra) {

        $noPagar = false;
        if($form->has('noPagar')) {
            $noPagar = $form->get('noPagar')->getData();;
        }

        if(false == $noPagar) {
            $ordenCompra->setEstatus(OrdenCompra::ESTATUS_PAGADA);
        }

        $metodopago = $form->get('metodopago')->getData();

        if($noPagar || $metodopago != OrdenCompra::PAGO_DEPOSITO) {
            $depositos = $form->get('depositos');
            foreach ($depositos as $deposito)
            {
                $deposito = $deposito->getData();
                $ordenCompra->removeDeposito($deposito);
            }
        }

        if($noPagar || $metodopago != OrdenCompra::PAGO_TRANSFERENCIA) {
            $transferencias = $form->get('transferencias');
            foreach ($transferencias as $transferencia)
            {
                $transferencia = $transferencia->getData();
                $ordenCompra->removeTransferencia($transferencia);
            }
        }
    }

    public function registrar(Request $request, \Swift_Mailer $mailer) {

        $transaction = (new Webpay(Configuration::forTestingWebpayPlusNormal()))
               ->getNormalTransaction();

        $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED');

        $ordenCompra = new OrdenCompra();
        $ordenHosting = new OrdenHosting();
        $ordenDominio = new OrdenDominio();
        $transferencia = new Transferencia();
        $deposito = new Deposito();

        $ordenCompra->addOrdenHosting($ordenHosting)->addOrdenDominio($ordenDominio)->addDeposito($deposito)->addTransferencia($transferencia);

        $form = $this->createForm(OrdenCompraNuevoType::class, $ordenCompra);
        $form->handleRequest($request);

        if ($form->isSubmitted()) {
            if($form->isValid()) {

                $objDB = $this->getDoctrine()->getManager();
                $objDB->getConnection()->beginTransaction();
                try {
                    $procesar = $this->postValidRegistrar($form, $ordenCompra);
                    if($procesar) {
                        $this->limpiarPagos($form, $ordenCompra);

                        $correlativo = $this->getDoctrine()->getRepository(Correlativo::class)->findOneBy([], ['id' => 'DESC']);
                        $correlativoUsar = (((int)$correlativo->getCorrelativo()) + 1);
                        $correlativo->setCorrelativo($correlativoUsar);
                        $ordenCompra->setCorrelativo($correlativoUsar);
                        $objDB->persist($correlativo);
                        $objDB->persist($ordenCompra);
                        $objDB->flush();

                        /*
                        $objDB->getConnection()->rollBack();
                        $usuario = $this->getUser();
                        return $this->render(
                            'correo/nueva_orden.html.twig', [
                                'orden' => $ordenCompra,
                                'usuario' => $usuario,
                            ]
                        );
                        */

                        $objDB->getConnection()->commit();
                        $this->correoOrdenNuevo($mailer, $ordenCompra, $form);

                        $this->addFlash('success', 'Su Orden de compra ha sido generada exitosamente');
                        $this->addFlash('success', 'Se ha enviado a los correos electronicos una notificacion sobre su pedido');
                        return $this->redirectToRoute('orden_ver', [
                            'id' => $ordenCompra->getId()
                        ]);
                    }
                }
                catch (Exception $e) {
                    $objDB->getConnection()->rollBack();
                    $this->addFlash('danger', 'Ha surgido un error inesperado, intente de nuevo');
                }
            }
            else {
                $this->addFlash('warning', 'Debe ingresar los datos del formulario correctamente');
            }
        }

        return $this->render('website/orden/registrar.html.twig', [
            'form' => $form->createView()
        ]);
    }

    private function postValidRegistrar(Form $form, OrdenCompra $ordenCompra) {

        $procesar = true;
        $ordenCompra->setUsuario($this->getUser());
        $noFacturar = $form->get('noFacturar')->getData();
        if($noFacturar) {
            $ordenCompra->setOrdenFactura(null);
        }

        $totalHosting = 0;
        $hostings = $form->get('ordenHosting');
        foreach ($hostings as $hosting)
        {
            $omitirHosting = $hosting->get('omitirHosting')->getData();
            $hosting = $hosting->getData();
            if ($omitirHosting) {
                $ordenCompra->removeOrdenHosting($hosting);
            }
            else {
                $costoPlan = $this->getDoctrine()->getRepository(PlanCosto::class)->costoAnio($hosting->getPlanDestino()->getId(), $hosting->getDuracion());
                $hosting->setCosto($costoPlan['costo']);
                $hosting->setEstatus(OrdenHosting::ESTATUS_PENDIENTE);
                $totalHosting++;
            }
        }

        $totalDominio = 0;
        $dominios = $form->get('ordenDominio');
        foreach ($dominios as $dominio)
        {
            $omitirDominio = $dominio->get('omitirDominio')->getData();
            $dominio = $dominio->getData();
            if ($omitirDominio) {
                $ordenCompra->removeOrdenDominio($dominio);
            }
            else {
                $costoDominio = $this->getDoctrine()->getRepository(ExtensionCosto::class)->costoAnio($dominio->getExtension()->getId(), $dominio->getDuracion());
                $dominio->setCosto($costoDominio['costo']);
                $dominio->setEstatus(OrdenDominio::ESTATUS_PENDIENTE);
                $totalDominio++;
            }
        }

       if(($totalHosting + $totalDominio) == 0) {
            $procesar = false;
            $this->addFlash('danger', 'Debe al menos ordenar un servicio');
        }

        return $procesar;
    }


    private function correoOrdenNuevo(\Swift_Mailer $mailer, OrdenCompra $orden, Form $form) {

        $usuario = $this->getUser();
        $message = (new \Swift_Message('Orden de Compra'))
            ->setFrom('no.responder@netnexo.cl')
            ->addCc('gestion@netnexo.cl');

        $recibir = $form->get('recibir')->getData();
        $emailCopia = $form->get('emailCopia')->getData();

        if($recibir) {
            $emailUsuario = $this->getUser()->getEmail();
            $message->setTo($emailUsuario)->addCc('no.responder@netnexo.cl');
        }
        else {
            $message->setTo('no.responder@netnexo.cl');
        }

        if($emailCopia) {
            $emailCopia = $form["emailCopia"];
            $message->addCc($emailCopia);
        }

        $message->setBody(
                $this->renderView(
                    'correo/nueva_orden.html.twig', [
                        'orden' => $orden,
                        'usuario' => $usuario,
                    ]
                ),
                'text/html'
            );

        $mailer->send($message);
    }


    public function listar() {

        $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED');

        $objDB = $this->getDoctrine()->getManager();
        $objOrdenes = $this->getDoctrine()->getRepository(OrdenCompra::class);
        $ordenes = $objOrdenes->findBy(['usuario' => $this->getUser()], ['id' => 'DESC']);

        return $this->render('website/orden/listar.html.twig', [
            'ordenes' => $ordenes
        ]);
    }

    public function ver($id) {

        $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED');

        $orden = $this->getDoctrine()->getRepository(OrdenCompra::class)->find($id);

        if(!$orden || $this->getUser()->getId() != $orden->getUsuario()->getId()) {
            return $this->redirectToRoute('orden_listar');
        }

        return $this->render('website/orden/ver.html.twig', [
            'orden' => $orden
        ]);
    }

    public function anular($id)
    {
        $this->denyAccessUnlessGranted('IS_AUTHENTICATED_REMEMBERED');

        $error = true;
        $mensaje = '';
        $response = new JsonResponse();
        $ordenCompra = $this->getDoctrine()->getRepository(OrdenCompra::class)->find($id);

        if($ordenCompra) {
            if($this->getUser()->getId() == $ordenCompra->getUsuario()->getId()) {
                if($ordenCompra->getEstatus() == OrdenCompra::ESTATUS_PENDIENTE) {

                    $objDB = $this->getDoctrine()->getManager();
                    $objDB->getConnection()->beginTransaction();

                    try {
                        $ordenCompra->setEstatus(OrdenCompra::ESTATUS_ANULADA);
                        $ordenCompra->setObservacion('Anulacion realizada por el usuario');
                        $ordenCompra->setNota('Anulacion realizada por el usuario');
                        $ordenCompra->setFechaCierre((new \DateTime('now')));

                        $ordDominios = $ordenCompra->getOrdenDominio();
                        $ordHostings = $ordenCompra->getOrdenHosting();

                        foreach ($ordDominios as $ordDom) {
                            $ordDom->setObservacion('Anulacion realizada por el usuario');
                        }
                        foreach ($ordHostings as $ordHos) {
                            $ordHos->setObservacion('Anulacion realizada por el usuario');
                        }

                        $objDB->persist($ordenCompra);
                        $objDB->flush();
                        $response->setStatusCode(Response::HTTP_OK);
                        $error = false;
                        $mensaje = 'La Orden de Compra ha ha sido anulada con exito.';
                        $objDB->getConnection()->commit();
                    }
                    catch (Exception $e) {
                        $objDB->getConnection()->rollBack();
                        $mensaje = 'Ha surgido un error inesperado al intentar anular la Orden de Compra.';
                    }
                }
                else {
                    $mensaje = 'La Orden de Compra solo se puede anular si esta <strong>"Pendiente"</strong>.';
                }
            }
            else {
                $mensaje = 'Un error interno ha ocurrido, por favor intente de nuevo.';
            }
        }
        else {
            $mensaje = 'La Orden de Compra no existe.';
        }

        return $response->setData(['error' => $error, 'mensaje' => $mensaje]);
    }


    //////////////////////////
    // PARTE ADMINISTRATIVA //
    //////////////////////////


    public function listarAdmin(Request $request) {
        $objDB = $this->getDoctrine()->getManager();
        $objOrdenes = $this->getDoctrine()->getRepository(OrdenCompra::class);

        $ordenes = $objOrdenes->findBy([], ['id' => 'DESC']);

        return $this->render('admin/orden/listar.html.twig', [
            'ordenes' => $ordenes
        ]);
    }


    public function verAdmin($id) {

        $objDB = $this->getDoctrine()->getManager();
        $objOrden = $this->getDoctrine()->getRepository(OrdenCompra::class);
        $orden = $objOrden->find($id);

        if(!$orden) {
             return $this->redirectToRoute('orden_listar_admin');
        }

        return $this->render('admin/orden/ver.html.twig', [
            'orden' => $orden
        ]);
    }


    public function procesarAdmin(Request $request, \Swift_Mailer $mailer, $id) {

        $objDB = $this->getDoctrine()->getManager();
        $objOrden = $this->getDoctrine()->getRepository(OrdenCompra::class);
        $orden = $objOrden->find($id);

        if(!$orden || ($orden->getEstatus() != OrdenCompra::ESTATUS_PENDIENTE && $orden->getEstatus() != OrdenCompra::ESTATUS_PAGADA)) {
             return $this->redirectToRoute('orden_listar_admin');
        }

        $ordenClon = clone $orden;
        $form = $this->createForm(OrdenCompraProcesarType::class, $orden);
        $form->handleRequest($request);

        if ($form->isSubmitted()) {
            if($form->isValid()) {

                $this->postProcesar($form, $orden);
                $objDB = $this->getDoctrine()->getManager();
                $objDB->getConnection()->beginTransaction();
                $objDB->persist($orden);
                $objDB->flush();

                /*
                $objDB->getConnection()->rollBack();
                $usuario = $this->getUser();
                return $this->render(
                    'correo/confirmar_orden.html.twig', ['orden' => $orden, 'usuario' => $usuario,]
                );
                */
                $objDB->getConnection()->rollBack();
                //$objDB->getConnection()->commit();

                $this->correoOrdenProcesar($mailer, $orden);

                $this->addFlash('success', 'Se ha procesado la Orden de Compra exitosamente');
                return $this->redirectToRoute('orden_listar_admin');
        }
        }

        return $this->render('admin/orden/procesar.html.twig', [
            'orden' => $ordenClon,
            'form' => $form->createView()
        ]);
    }


    private function postProcesar(Form $form, OrdenCompra $ordenCompra) {

        $finalEstatus = OrdenCompra::ESTATUS_ANULADA;
        $ordenCompra->setFechaCierre((new \DateTime('now')))->setUsuarioAdmin($this->getUser());

        $hostings = $form->get('ordenHosting');
        foreach ($hostings as $ordHosting)
        {
            $ordHosting = $ordHosting->getData();
            if ($ordHosting->getEstatus() == OrdenHosting::ESTATUS_APROBADA ) {
                $finalEstatus = OrdenCompra::ESTATUS_PROCESADA;

                $inicio = new \DateTime();
                $final = new \DateTime();
                $final->add(new \DateInterval('P'.($ordHosting->getDuracion()).'Y'));
                $ordHosting->setFechaInicio($inicio)->setFechaFin($final);
                $hosting = new Hosting();
                $hosting->setPlan($ordHosting->getPlanDestino())
                    ->setUsuario($ordenCompra->getUsuario())
                    ->setEstatus(Hosting::ESTATUS_ACTIVO);
                $ordHosting->setHosting($hosting);
            }
        }

        $dominios = $form->get('ordenDominio');
        foreach ($dominios as $ordDominio)
        {
            $ordDominio = $ordDominio->getData();
            if ($ordDominio->getEstatus() == OrdenDominio::ESTATUS_APROBADA ) {
                $finalEstatus = OrdenDominio::ESTATUS_PROCESADA;

                $inicio = new \DateTime();
                $final = new \DateTime();
                $final->add(new \DateInterval('P'.($ordDominio->getDuracion()).'Y'));
                $ordDominio->setFechaInicio($inicio)->setFechaFin($final);
                $dominio = new Dominio();
                $dominio->setExtension($ordDominio->getExtension())
                    ->setUsuario($ordenCompra->getUsuario())
                    ->setNombre($ordDominio->getNombre())
                    ->setEstatus(Dominio::ESTATUS_ACTIVO);
                $ordDominio->setDominio($dominio);
            }
        }

        $ordenCompra->setEstatus($finalEstatus);
    }

    private function correoOrdenProcesar(\Swift_Mailer $mailer, OrdenCompra $orden) {

        $usuario = $orden->getUsuario();
        $message = (new \Swift_Message('Orden de Compra'))
            ->setFrom('no.responder@netnexo.cl')
            ->addCc('gestion@netnexo.cl')
            ->setTo($usuario->getEmail());

        $vista = 'correo/confirmar_orden.html.twig';
        if($orden->getEstatus() == OrdenCompra::ESTATUS_ANULADA) {
            $vista = 'correo/anular_orden.html.twig';
        }

        $message->setBody(
                $this->renderView(
                    $vista, [
                        'orden' => $orden,
                        'usuario' => $usuario,
                    ]
                ),
                'text/html'
            );

        $mailer->send($message);
    }



}