<?php

namespace Inside\IBCA\Console;

use Dompdf\Adapter\CPDF;
use Dompdf\Dompdf;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\View;
use Inside\Content\Models\Contents\FoldersHr;
use Inside\Content\Models\Contents\DocumentsHr;

class ExportHrGed extends Command
{
    /**
     * @var string
     */
    protected $name = 'bca:exporthrged';

    /*
     * @var string
     */
    protected $signature = 'bca:exporthrged';

    /**
     * @var string
     */
    protected $description = 'Export HR GED';

    /**
     * @var string
     */
    protected $basePath = 'export/hr_ged';

    public function handle(): void
    {
        $folders = FoldersHr::query()->where('status', 1)->where('pid', null)->get();

        $basePath = cms_base_path($this->basePath);

        if (!File::exists($basePath)) {
            File::makeDirectory($basePath, 0755, true);
        }

        foreach ($folders as $folder) {
            $this->exportFolder($folder, $basePath);
        }
    }

    protected function exportFolder(FoldersHr $folder, string $basePath): void
    {
        $folderPath = $basePath . '/' . trim($folder->title);

        if (!File::exists($folderPath)) {
            File::makeDirectory($folderPath, 0755, true);
        }

        $documents = $folder->reverseDocumentsHr;

        foreach ($documents as $document) {
            if ($document->status === 0) {
                continue;
            }

            $this->exportDocument($document, $folderPath);
        }

        $subFolders = $folder->reverseFoldersHr;

        foreach ($subFolders as $subFolder) {
            $this->exportFolder($subFolder, $folderPath);
        }

        $zipName = cms_base_path('bca-ged-rh.zip');
        $zip = new \ZipArchive();
        $zip->open($zipName, \ZipArchive::CREATE | \ZipArchive::OVERWRITE);
        $files = new \RecursiveIteratorIterator(
            new \RecursiveDirectoryIterator(cms_base_path($this->basePath)),
            \RecursiveIteratorIterator::LEAVES_ONLY
        );

        foreach ($files as $name => $file) {
            // Skip directories (they would be added automatically)
            if (!$file->isDir()) {
                // Get real and relative path for current file
                $filePath = $file->getRealPath();
                $relativePath = substr($filePath, strlen(cms_base_path($this->basePath)) + 1);

                // Add current file to archive
                $zip->addFile($filePath, $relativePath);
            }
        }

        // Zip archive will be created only after closing object
        $zip->close();
    }

    protected function exportDocument(DocumentsHr $document, string $folderPath): void
    {
        if ($document->sectionContent->count() === 0 && !empty($document->file)) {
            $pathinfo = pathinfo($document->file);
            $filePath = $folderPath . '/' . trim($document->title) . '.' . ($pathinfo['extension'] ?? '');

            File::copy(Storage::disk('local')->path($document->file), $filePath);
            return;
        }

        $view = 'document';
        $data = $this->formatContentData($document, $folderPath);
        $filePath = $folderPath . '/'. trim($document->title) . '.pdf';

        $view = View::make($view, $data);
        $html = $view->render();
        $html = preg_replace('/>\s+</', '><', $html) ?? '';

        $dompdf = new Dompdf();
        $dompdf->loadHtml($html);
        $dompdf->render();

        if (!empty($data['attachments'])) {
            /** @var CPDF $cpdf */
            $cpdf = $dompdf->getCanvas();
            $cpdf = $cpdf->get_cpdf();

            foreach ($data['attachments'] as $attachment) {
                $cpdf->addEmbeddedFile(
                    $attachment['path'],
                    $attachment['filename'],
                    $attachment['name']
                );
            }
        }

        File::put($filePath, $dompdf->output() ?: '');
    }

    public function formatContentData(DocumentsHr $content, string $folderPath): array
    {
        $data = [
            'attachments' => [],
            'document' => [],
        ];

        $sections = [];

        $this->attachFile($content, 'file', 'file', $folderPath, $data, $sections);

        foreach ($content->sectionContent as $section) {
            $type = str_replace('inside_section_', '', $section->getTable());

            switch ($type) {
                case 'accordion':
                    $sections[] = [
                        'type' => 'accordion',
                        'question' => $section->question,
                        'answer' => $this->convertImages($section->answer),
                    ];
                    break;
                case 'text':
                    $sections[] = [
                        'type' => 'text',
                        'body' => $this->convertImages($section->body),
                    ];
                    break;
                case 'file':
                    $this->attachFile($section, 'file', 'file', $folderPath, $data, $sections);
                    break;
                case 'image':
                    $this->attachFile($section, 'image', 'image', $folderPath, $data, $sections);
                    break;
                case 'text_with_image':
                    $this->attachFile($section, 'image', 'text_with_image', $folderPath, $data, $sections);
                    break;
                default:
                    // do nothing
                    break;
            }
        }

        $data['document'] = [
            'uuid' => $content->uuid,
            'title' => $content->title,
            'langcode' => $content->langcode,
            'type' => 'sop',
            'contents' => $sections,
            'is_rop' => false,
        ];

        return $data;
    }

    public function convertImages(string $text): string
    {
        preg_match_all('/< *img[^>]*src *= *["\']?([^"\']*)/i', $text, $matches);

        if (isset($matches[1])) {
            foreach ($matches[1] as $url) {
                $path = str_replace(['/storage', 'storage/app/', 'https://www.webca.fr'], ['storage', '', ''], $url);

                /*
                if (!Storage::disk('local')->exists($path) && !strstr($path, 'data:image')) {
                    $externalUrls = [
                        'http://frontals4i',
                        'http://mon-entreprise'
                    ];

                    foreach ($externalUrls as $externalUrl) {
                        if (strstr($path, $externalUrl)) {
                            continue 2;
                        }
                    }

                    $this->info(sprintf('Downloading inline file %s', $path));
                    $downloadPath = 'https://www.webca.fr/storage/app/' . $path;
                    $file = file_get_contents($downloadPath);

                    Storage::disk('local')->put($path, $file);
                }
                */

                if (!Storage::disk('local')->exists($path)) {
                    continue;
                }

                /** @var string $fileContent */
                $fileContent = file_get_contents(Storage::disk('local')->path($path));
                $base64 = 'data:' . mime_content_type(Storage::disk('local')->path($path)) . ';base64,' . base64_encode($fileContent);
                $text = str_replace($url, $base64, $text);
            }
        }

        /** @var string $text */
        $text = str_replace('<p>&nbsp;</p>', '<p class="spacer mini"></p>', $text);

        /** @var string $text */
        $text = preg_replace('/(<table|tr|td|tbody|thead)(.*)(width: [0-9]+px;)/i', '$1$2', $text);

        /** @var string $text */
        $text = preg_replace('/(<img([^>]*)>)/i', '<p class="image-wrapper">$1</p>', $text);

        return $text;
    }

    /**
     * @param mixed $content
     * @param string $field
     * @param string $type
     * @param string $folderPath
     * @param array $data
     * @param array $sections
     * @return void
     */
    protected function attachFile($content, string $field, string $type, string $folderPath, array &$data, array &$sections): void
    {
        if (!empty($content->{$field})) {
            /*
            if (!Storage::disk('local')->exists($content->{$field})) {
                $this->info(sprintf('Downloading %s %s %s', $type, $field, $content->{$field}));
                $downloadPath = 'https://www.webca.fr/storage/app/' . $content->{$field};
                $file = file_get_contents($downloadPath);

                Storage::disk('local')->put($content->{$field}, $file);
            }
            */

            $filePath = $folderPath . '/attachments/' . $content->{$field};

            if (!File::exists(pathinfo($filePath)['dirname'])) {
                File::makeDirectory(pathinfo($filePath)['dirname'], 0755, true);
            }

            File::copy(Storage::disk('local')->path($content->{$field}), $filePath);

            $data['attachments'][] = [
                'path' => $filePath,
                'filename' => pathinfo($filePath)['basename'],
                'name' => pathinfo($filePath)['filename']
            ];

            switch ($type) {
                case 'file':
                    $sections[] = [
                        'type' => 'file',
                        'filename' => pathinfo($filePath)['basename'],
                        'path' => 'attachments/' . $content->{$field},
                        'size' => $this->humanReadableFilesize((int)filesize($filePath)),
                    ];
                    break;
                case 'image':
                    $sections[] = [
                        'type' => 'image',
                        'body' => $this->convertImages(sprintf('<p><img src="%s" /></p>', '/' . env('APP_STORAGE_PATH') . '/' . $content->{$field})),
                    ];
                    break;
                case 'text_with_image':
                    $sections[] = [
                        'type' => 'text_with_image',
                        'image' => $this->convertImages(sprintf('<p><img src="%s" /></p>', '/' . env('APP_STORAGE_PATH') . '/' . $content->{$field})),
                        'body' => $this->convertImages($content->body),
                        'display' => $content->display,
                    ];
                    break;
            }
        }
    }

    protected function humanReadableFilesize(int $bytes, int $decimals = 2): string
    {
        $factor = floor((strlen((string)$bytes) - 1) / 3);
        if ($factor > 0) {
            $sz = 'KMGT';
        }
        return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . (isset($sz) ? @$sz[(int)$factor - 1] : '') . 'B';
    }
}
