<?php

namespace App\Helper;

use App\Curl\CurlRequest;
use Exception;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

class LegacyHelper
{
    private const MIME_TYPES = [
        'txt' => 'text/plain',
        'htm' => 'text/html',
        'html' => 'text/html',
        'php' => 'text/html',
        'css' => 'text/css',
        'js' => 'application/javascript',
        'json' => 'application/json',
        'xml' => 'application/xml',
        'swf' => 'application/x-shockwave-flash',
        'flv' => 'video/x-flv',

        // images
        'png' => 'image/png',
        'jpe' => 'image/jpeg',
        'jpeg' => 'image/jpeg',
        'jpg' => 'image/jpeg',
        'gif' => 'image/gif',
        'bmp' => 'image/bmp',
        'ico' => 'image/vnd.microsoft.icon',
        'tiff' => 'image/tiff',
        'tif' => 'image/tiff',
        'svg' => 'image/svg+xml',
        'svgz' => 'image/svg+xml',

        // archives
        'zip' => 'application/zip',
        'rar' => 'application/x-rar-compressed',
        'exe' => 'application/x-msdownload',
        'msi' => 'application/x-msdownload',
        'cab' => 'application/vnd.ms-cab-compressed',

        // audio/video
        'mp3' => 'audio/mpeg',
        'qt' => 'video/quicktime',
        'mov' => 'video/quicktime',

        // adobe
        'pdf' => 'application/pdf',
        'psd' => 'image/vnd.adobe.photoshop',
        'ai' => 'application/postscript',
        'eps' => 'application/postscript',
        'ps' => 'application/postscript',

        // ms office
        'doc' => 'application/msword',
        'rtf' => 'application/rtf',
        'xls' => 'application/vnd.ms-excel',
        'ppt' => 'application/vnd.ms-powerpoint',
        'docx' => 'application/msword',
        'xlsx' => 'application/vnd.ms-excel',
        'pptx' => 'application/vnd.ms-powerpoint',

        // open office
        'odt' => 'application/vnd.oasis.opendocument.text',
        'ods' => 'application/vnd.oasis.opendocument.spreadsheet'
    ];

    public static function transferToLegacy(
        Request $request,
        string $legacy_external_prefix,
        string $legacy_url
    ): Response {
        $originalController = preg_replace(
            "@^$legacy_external_prefix@",
            '',
            $request->getPathInfo()
        );

        if (null === $originalController) {
            throw new Exception('Original controller not found');
        }

        $originalQueryString = $request->getQueryString();

        //@TODO : delete on linux server
        // $originalController = str_replace("/", "\\", $originalController); //windows

        $extension = strrchr($originalController, '.');

        if ($extension != '.html' && $extension != '.php' && $extension != false) {
            $file_path = "{$originalController}";
            try {
                $mime = self::getMime($file_path, $extension);
                $response = new BinaryFileResponse($file_path);
                $response->headers->set('Content-Type', $mime ?: 'application/octet-stream');
                return $response;
            } catch (FileNotFoundException $e) {
                // try normal access by url
            }
        }

        $separator = '';
        if (!$extension) {
            $separator = '/';
        }

        $url = "{$legacy_url}{$originalController}{$separator}?{$originalQueryString}";

        $curl_handler = new CurlRequest();

        try {
            $options_array = [
                CURLOPT_URL => $url,
                CURLOPT_HEADER => false,
                CURLOPT_VERBOSE => true,
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_COOKIESESSION => false,
                CURLOPT_COOKIEFILE => 'cookies.txt',
                CURLOPT_COOKIEJAR => 'cookies.txt'
            ];

            $curl_handler->setOptions($options_array);

            if ($request->getMethod() == 'POST') {
                $postParameters = $request->request->all();

                if (!is_array($postParameters)) {
                    throw new Exception();
                }

                // upload file to transfer
                if (isset($_FILES['fileToUpload'])) {
                    $data = [
                        'fileToUpload' => curl_file_create(
                            $_FILES['fileToUpload']['tmp_name'],
                            $_FILES['fileToUpload']['type'],
                            $_FILES['fileToUpload']['name']
                        )
                    ];

                    $postParameters = array_merge($postParameters, $data);
                    $curl_handler->setOptions([CURLOPT_HEADER => true]);
                }

                $curl_handler->setOptions([
                    CURLOPT_POST => true,
                    CURLOPT_POSTFIELDS => $postParameters
                ]);
            }

            $result = $curl_handler->execute();

            if (!is_string($result)) {
                throw new NotFoundHttpException(
                    (int)$curl_handler->getInfo(CURLINFO_HTTP_CODE) .
                    $curl_handler->getErrorMessage()
                );
            }

            $response = new Response($result);
            $contentType = $curl_handler->getInfo(CURLINFO_CONTENT_TYPE);

            $response->headers->set('Content-Type', $contentType);

            return $response;
        } finally {
            $curl_handler->close();
        }
    }

    public static function getMime(?string $filepath, string $extension): ?string
    {
        if (null === $filepath) {
            throw new \InvalidArgumentException('File cannot be null.');
        }

        $extension_without_dot = strtolower(str_replace('.', '', $extension));

        if (array_key_exists($extension_without_dot, self::MIME_TYPES)) {
            return self::MIME_TYPES[$extension_without_dot];
        }

        $file = new File($filepath, true);

        if (! $file->isReadable()) {
            throw new FileException('File must be readable.');
        }

        return $file->getMimeType();
    }
}