<?php
namespace App\Services\Parser\Portals;

use Illuminate\Support\Facades\Http;

class Encar
{
    /**
     * Интервал между запросами в секундах.
     * Переопределяет глобальный request_interval из config/parser.php.
     */
    const REQUEST_INTERVAL = 2;

    /**
     * Папка для временного хранения HTML-файлов
     */
    const TMP_DIR = __DIR__ . '/../tmp';

    /**
     * User-Agent для HTTP-запросов
     */
    const USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36';

    // -------------------------------------------------------------------------
    // Public API
    // -------------------------------------------------------------------------

    /**
     * Точка входа: загружает страницы и сохраняет HTML во временную папку.
     */
    public function parse(): void
    {
        $contents = $this->getContent();
        $this->saveContent($contents);
    }

    /**
     * Читает все HTML-файлы из tmp и возвращает массив:
     * [
     *   ['file' => '/absolute/path/to/file.html', 'html' => '<html>...'],
     *   ...
     * ]
     */
    public function getResult(): array
    {
        $tmpDir = self::TMP_DIR;

        if (! is_dir($tmpDir)) {
            return [];
        }

        $files   = glob($tmpDir . '/*.html') ?: [];
        $results = [];

        foreach ($files as $file) {
            $html = file_get_contents($file);

            if ($html === false) {
                error_log("[Encar] Не удалось прочитать файл: $file");
                continue;
            }

            $results[] = [
                'file' => $file,
                'html' => $html,
            ];
        }

        return $results;
    }

    /**
     * Удаляет все HTML-файлы из tmp.
     * Метод готов, но пока не вызывается из Parser.
     */
    public function clearData(): void
    {
        $tmpDir = self::TMP_DIR;

        if (! is_dir($tmpDir)) {
            return;
        }

        $files = glob($tmpDir . '/*.html') ?: [];

        foreach ($files as $file) {
            if (! unlink($file)) {
                error_log("[Encar] Не удалось удалить файл: $file");
            }
        }
    }

    // -------------------------------------------------------------------------
    // Private
    // -------------------------------------------------------------------------

    /**
     * Список ссылок для парсинга
     */
    private function getLinks(): array
    {
        return [
            'https://fem.encar.com/cars/detail/41664398?pageid=dc_carsearch&listAdvType=pic&carid=41664398&view_type=checked&wtClick_korList=015&advClickPosition=kor_pic_p1_g1',
            'https://fem.encar.com/cars/detail/41939059?pageid=dc_carsearch&listAdvType=pic&carid=41939059&view_type=checked&wtClick_korList=015&advClickPosition=kor_pic_p1_g2',
        ];
    }

    /**
     * Загружает HTML-контент по всем ссылкам.
     * Возвращает массив: [ ['url' => ..., 'html' => ...], ... ]
     */
    private function getContent(): array
    {
        $links   = $this->getLinks();
        $results = [];

        foreach ($links as $index => $url) {
            $html = $this->fetchUrl($url);

            if ($html !== false) {
                $body = $this->extractBody($html);

                if ($body !== null) {
                    $results[] = [
                        'url'  => $url,
                        'html' => $body,
                    ];
                } else {
                    error_log("[Encar] Не удалось извлечь <body>: $url");
                }
            } else {
                error_log("[Encar] Не удалось загрузить: $url");
            }

            // Пауза между запросами (кроме последнего)
            if ($index < count($links) - 1) {
                sleep(self::REQUEST_INTERVAL);
            }
        }

        return $results;
    }

/**
 * Извлекает содержимое тега <body> из HTML-строки.
 * Возвращает null если тег не найден.
 */
    private function extractBody(string $html): ?string
    {
        $dom = new \DOMDocument();

        // Подавляем ошибки парсинга (битый HTML, корейские символы и т.д.)
        libxml_use_internal_errors(true);

        // UTF-8 hint — иначе DOMDocument может неверно определить кодировку
        $dom->loadHTML('<?xml encoding="UTF-8">' . $html, LIBXML_NOWARNING | LIBXML_NOERROR);

        libxml_clear_errors();

        $body = $dom->getElementsByTagName('body')->item(0);

        if ($body === null) {
            return null;
        }

        // Сериализуем innerHTML тега <body> (без самих тегов <body></body>)
        $innerHTML = '';
        foreach ($body->childNodes as $child) {
            $innerHTML .= $dom->saveHTML($child);
        }

        return trim($innerHTML);
    }

    /**
     * Выполняет HTTP GET-запрос с кастомным User-Agent
     */
    private function fetchUrl(string $url): string | false
    {
        $response = Http::withHeaders([
            'User-Agent'      => self::USER_AGENT,
            'Accept'          => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
            'Accept-Language' => 'ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7',
            'Connection'      => 'keep-alive',
        ])
            ->timeout(30)
            ->withOptions(['allow_redirects' => true])
            ->get($url);

        if ($response->failed()) {
            return false;
        }

        return $response->body();
    }

    /**
     * Сохраняет полученный HTML в файлы в папке tmp
     */
    private function saveContent(array $contents): void
    {
        if (! is_dir(self::TMP_DIR)) {
            mkdir(self::TMP_DIR, 0755, true);
        }

        foreach ($contents as $item) {
            $carId    = $this->extractCarId($item['url']);
            $filename = self::TMP_DIR . '/' . $carId . '_' . time() . '.html';

            $written = file_put_contents($filename, $item['html']);

            if ($written === false) {
                error_log("[Encar] Не удалось сохранить файл: $filename");
            } else {
                echo "[Encar] Сохранено: $filename" . PHP_EOL;
            }
        }
    }

    /**
     * Извлекает carid из URL, либо возвращает md5-хэш URL
     */
    private function extractCarId(string $url): string
    {
        if (preg_match('/carid=(\d+)/', $url, $matches)) {
            return $matches[1];
        }

        return md5($url);
    }
}
