<?php

namespace Webkul\WebkulCsvBundle\Controller\Rest;

use Oro\Bundle\ConfigBundle\Entity\ConfigValue;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Intl\Intl;
use Symfony\Component\Validator\Constraints\NotBlank;
use Webkul\WebkulCsvBundle\Component\Version;
use Webkul\WebkulCsvBundle\Entity\TemplateConfiguration;

/**
 * Configuration rest controller in charge of the webkul csv connector configuration managements
 */
class ConfigurationController extends Controller
{
    const SECTION = 'webkul_csv_connector';

    public function getActiveCurrenciesAction()
    {
        $currencies = [];
        $repo = $this->getDoctrine()->getRepository('PimCatalogBundle:Currency');
        $codes = $repo->getActivatedCurrencyCodes();
        
        foreach (Intl::getCurrencyBundle()->getCurrencyNames() as $currencyCode => $currencyName) {
            foreach ($codes as $code) {
                if ($currencyCode == $code) {
                    $currencies[$currencyCode] = $currencyName;
                }
            }
        }
        
        return new JsonResponse($currencies);
    }

    public function getLogFileAction()
    {
        $log_dir = $this->getParameter('logs_dir');
        $env = $this->getParameter('kernel.environment');
        $path = $log_dir."/webkul_shopify_batch.".$env.".log";
        
        $fs=new Filesystem();
        if (!$fs->exists($path)) {
            $fs->touch($path);
        }
        
        $response = new Response();
        $response->headers->set('Content-type', 'application/octet-stream');
        $response->headers->set('Content-Disposition', sprintf('attachment; filename="%s"', "webkul_shopify_batch.".$env.".log"));
        $response->setContent(file_get_contents($path));
        $response->setStatusCode(200);
        $response->headers->set('Content-Transfer-Encoding', 'binary');
        $response->headers->set('Pragma', 'no-cache');
        $response->headers->set('Expires', '0');
        
        return $response;
    }

    // create the template
    public function createTemplateAction(Request $request)
    {
        $em = $this->getDoctrine()->getManager();
        $params = json_decode($request->getContent(), true);
        $form = $this->getConfigForm();
        $form->submit($params);
        $form->handleRequest($request);
        $host = $request->getHost();
        
        if ($request->getPort() && !in_array($request->getPort(), [443, 80])) {
            $host .= ':' . $request->getPort();
        }
        
        $serverdetail = [
            'hostname' => $host,
            'scheme'   => $request->getScheme(),
        ];

        if ($form->isSubmitted() && $form->isValid()) {
            $repo = $em->getRepository('WebkulCsvBundle:TemplateConfiguration');
            $configValue = $repo->findOneBy([
                'name' => $params['name']
                ]);
            if (!$configValue) {
                $configValue = new TemplateConfiguration();
            } else {
                return new JsonResponse(['name'=> 'This value is already used.'], RESPONSE::HTTP_BAD_REQUEST);
            }

            $configValue->setName($params['name']);
            $em->persist($configValue);
            $em->flush();

            $oroRepo = $em->getRepository('OroConfigBundle:ConfigValue');
            foreach ($serverdetail as $key => $value) {
                $field = $oroRepo->findOneBy([
                    'section' => self::SECTION,
                    'name' => $key
                    ]);
    
                if (!$field) {
                    $field = new ConfigValue();
                    $field->setName($key);
                    $field->setSection(self::SECTION);
                    $field->setValue($value);
                    $em->persist($field);
                } else {
                    $field->setValue($value);
                    $em->persist($field);
                }
                $em->flush();
            }
        } else {
            return new JsonResponse($this->getFormErrors($form), RESPONSE::HTTP_BAD_REQUEST);
        }

        return new JsonResponse([
            'meta' => [
                'id' => $configValue->getId()
            ]
        ]);
    }

    /**
     * Get template
     *
     *
     * @return JsonResponse
     */
    public function getTemplateAction(Request $request, $identifier)
    {
        $templates = [];
        $cacheDriver = new \Doctrine\Common\Cache\ArrayCache();
        $deleted = $cacheDriver->deleteAll();
        $em = $this->getDoctrine()->getManager();
        $mapping = $em->getRepository('WebkulCsvBundle:TemplateConfiguration')->find($identifier);

        $templates['templatename'] = $mapping ? $mapping->getName() : '';
        $templates['rawValues'] = $mapping ?  json_decode($mapping->getRawValues(), true) : [];
        $templates['id'] = $mapping ? $mapping->getId() : '';

        return new JsonResponse($templates);
    }

    /**
     * Get template
     *
     *
     * @return JsonResponse
     */
    public function getActiveTemplateAction()
    {
        $data = [];
        $em = $this->getDoctrine()->getManager();
        $stores = $em->getRepository('WebkulCsvBundle:TemplateConfiguration')->findBy([
            'active' => 1
            ]);
        foreach ($stores as $store) {
            $data[$store->getId()] = $store->getName();
        }
        return new JsonResponse($data);
    }

    /**
     * Update template
     *
     *
     * @return JsonResponse
     */
    public function updateTemplateAction(Request $request, $identifier)
    {
        $em = $this->getDoctrine()->getManager();
        $params = json_decode($request->getContent(), true);

        $form = $this->getConfigForm();
        $form->submit($params);
        $form->handleRequest($request);
        if ($form->isSubmitted()) {
            if ($params) {
                $repo = $em->getRepository('WebkulCsvBundle:TemplateConfiguration');
                $configValue = $repo->findOneBy([
                    'name' => $params['templatename'],
                    ]);

                if ($configValue && !$configValue->getId() == $identifier) {
                    return new JsonResponse(['name'=> 'This value is already used.'], RESPONSE::HTTP_BAD_REQUEST);
                } else {
                    $configValue = $repo->findOneBy([
                        'id' => $identifier
                        ]);
                    $configValue->setName($params['templatename']);
                    $configValue->setRawValues(json_encode($params['rawValues']));
                    
                    $em->persist($configValue);
                    $em->flush();
                }
            } else {
                return new JsonResponse(['name'=> 'This value should not be blank.'], RESPONSE::HTTP_BAD_REQUEST);
            }
        } else {
            return new JsonResponse($this->getFormErrors($form), RESPONSE::HTTP_BAD_REQUEST);
        }

        return new JsonResponse(['successful' => true]);
    }

    /**
     * toogle status
     *
     * @return JsonResponse
     */
    public function toggleStatusAction($id, Request $request)
    {
        $em = $this->getDoctrine()->getManager();
        $template = $em->getRepository(TemplateConfiguration::class)->findOneById($id);

        if ($template) {
            $template->setActive($template->getActive() ? 0 : 1);
            $em->persist($template);
            $em->flush();
        }

        if (!$request->isXmlHttpRequest()) {
            return $this->redirect($this->generateUrl('webkul_csv_connector_configuration'));
        }

        return new JsonResponse(['successful' => true]);
    }

    /**
     * Remove Template
     *
     * @return JsonResponse
     */
    public function deleteTemplateAction($id)
    {
        $em = $this->getDoctrine()->getManager();
        $mapping = $em->getRepository('WebkulCsvBundle:TemplateConfiguration')->find($id);
        if (!$mapping) {
            throw new NotFoundHttpException(
                sprintf('Instance with id "%s" not found', $id)
            );
        }
        $em->remove($mapping);
        $em->flush();

        return new Response(null, Response::HTTP_NO_CONTENT);
    }

    /**
     * GET Job Instace class versionwise
     * @param Request $request
     *
     * @return JsonResponse
     */
    public function getJobInstanceClassAction(Request $request)
    {
        if (!$request->isXmlHttpRequest()) {
            return new RedirectResponse('/');
        }

        $version = new \AkeneoVersion();
        $jobInstanceClass = 'Akeneo\Component\Batch\Model\JobInstance';

        if ($version::VERSION > '3.0') {
            $jobInstanceClass = 'Akeneo\Tool\Component\Batch\Model\JobInstance';
        }
        
        return new JsonResponse(['history_class'=> $jobInstanceClass]);
    }

    private function getConfigForm()
    {
        $form = $this->createFormBuilder(null, [
                    'allow_extra_fields' => true,
                    'csrf_protection' => false
                ]);

        foreach ($this->getTemplateWithContraints() as $field => $constraint) {
            $form->add($field, null, [
                'constraints' => is_array($constraint) ? $constraint : [
                    $constraint
                ]
            ]);
        }

        return $form->getForm();
    }

    private function getTemplateWithContraints()
    {
        return [
            'name' => [new NotBlank()],
        ];
    }
    
    private function getFormErrors($form)
    {
        $errorContext = [];
        foreach ($form->getErrors(true) as $key => $error) {
            $errorContext[$error->getOrigin()->getName()] = $error->getMessage();
        }

        return $errorContext;
    }

    /**
     * GET version of connector
     *
     * @return JsonResponse
     */
    public function getVersionAction()
    {
        return new JsonResponse(['version'=> Version::CURRENT_VERSION]);
    }
}
