<?php
declare(strict_types=1);
defined('ABSPATH') || exit;

class DSProofwp_AliExpress_Scraper
{
    private const MAX_REVIEWS = 20;
    private const PAGE_SIZE   = 10;

    private const FEEDBACK_API_BASE = 'https://feedback.aliexpress.com/pc/searchEvaluation.do';

    /**
     * Extract the numeric product ID from an AliExpress product URL.
     */
    public function extract_product_id(string $url): ?string
    {
        $parsed = wp_parse_url($url);

        if (! is_array($parsed) || empty($parsed['host'])) {
            return null;
        }

        $host = strtolower($parsed['host']);

        // Allow aliexpress.com and any subdomain (www, de, fr, etc.)
        if ($host !== 'aliexpress.com' && ! str_ends_with($host, '.aliexpress.com')) {
            return null;
        }

        $path = $parsed['path'] ?? '';

        // Match /item/{numeric_id}.html
        if (preg_match('#/item/(\d+)\.html#', $path, $matches)) {
            return $matches[1];
        }

        return null;
    }

    /**
     * Fetch a single page of reviews from the AliExpress feedback API.
     */
    public function fetch_page(string $product_id, int $page = 1, bool $translate = true, string $filter = 'all'): array
    {
        $query_args = [
            'productId'  => $product_id,
            'lang'       => 'en_US',
            'page'       => $page,
            'pageSize'   => self::PAGE_SIZE,
            'filter'     => $filter,
            'sort'       => 'default',
            'starFilter' => 'all_stars',
        ];

        if ($translate) {
            $query_args['translate'] = 'Y';
        }

        $url = add_query_arg($query_args, self::FEEDBACK_API_BASE);

        $empty_result = [
            'error'          => '',
            'reviews'        => [],
            'total'          => 0,
            'average_rating' => 0.0,
        ];

        // Use direct cURL execution to bypass Local environment HTTP/Streams transport issues,
        // force IPv4 resolve, and skip peer SSL checks for local stability.
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 15);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
        curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
            'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
            'Accept-Language: en-US,en;q=0.5',
            'Referer: https://www.aliexpress.com/',
        ]);

        $body = curl_exec($ch);

        if (curl_errno($ch)) {
            $errno     = curl_errno($ch);
            $error_msg = curl_error($ch);
            curl_close($ch);

            if ($errno === 28) { // CURLE_OPERATION_TIMEDOUT
                $empty_result['error'] = 'Connection timed out. AliExpress seems to be taking too long to respond. Please try again in a few moments.';
            } elseif ($errno === 6 || $errno === 7) { // CURLE_COULDNT_RESOLVE_HOST, CURLE_COULDNT_CONNECT
                $empty_result['error'] = 'Unable to reach AliExpress. Please verify your network connection and try again.';
            } else {
                $empty_result['error'] = 'Could not connect to AliExpress (' . $error_msg . '). Please try again.';
            }

            return $empty_result;
        }

        $status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);

        if ($status_code !== 200) {
            $empty_result['error'] = sprintf('AliExpress API returned an unexpected response (HTTP %d). Please try again later.', $status_code);
            return $empty_result;
        }

        $data = json_decode($body, true);

        if (! is_array($data)) {
            $empty_result['error'] = 'Failed to parse AliExpress API response.';

            return $empty_result;
        }

        $raw_reviews = $data['data']['evaViewList'] ?? [];
        $total       = (int) ($data['data']['totalNum'] ?? 0);
        $avg_rating  = (float) ($data['data']['avgStarRate'] ?? 0);

        $reviews = [];

        if (is_array($raw_reviews)) {
            foreach ($raw_reviews as $raw) {
                $reviews[] = $this->normalize_review($raw);
            }
        }

        return [
            'reviews'        => $reviews,
            'total'          => $total,
            'average_rating' => $avg_rating,
        ];
    }

    /**
     * Fetch all reviews up to MAX_REVIEWS, paginating as needed.
     */
    public function fetch_all(string $product_id, bool $translate = true, string $filter = 'all'): array
    {
        $max_pages     = (int) ceil(self::MAX_REVIEWS / self::PAGE_SIZE);
        $all_reviews   = [];
        $total         = 0;
        $average_rating = 0.0;

        for ($page = 1; $page <= $max_pages; $page++) {
            if ($page > 1) {
                sleep(1);
            }

            $result = $this->fetch_page($product_id, $page, $translate, $filter);

            if (! empty($result['error'])) {
                // If the first page fails, propagate the error immediately
                if ($page === 1) {
                    return $result;
                }

                // For subsequent pages, stop collecting but return what we have
                break;
            }

            $total          = $result['total'];
            $average_rating = $result['average_rating'];

            foreach ($result['reviews'] as $review) {
                $all_reviews[] = $review;

                if (count($all_reviews) >= self::MAX_REVIEWS) {
                    break 2;
                }
            }

            // No more reviews available
            if (count($result['reviews']) < self::PAGE_SIZE) {
                break;
            }
        }

        return [
            'reviews'        => $all_reviews,
            'total'          => $total,
            'average_rating' => $average_rating,
        ];
    }

    /**
     * Normalize a raw review from the AliExpress API into a consistent structure.
     */
    private function normalize_review(array $raw): array
    {
        $author_name = (string) ($raw['buyerName'] ?? $raw['anonymousName'] ?? 'AliExpress Customer');
        $rating      = (int) ($raw['buyerEval'] ?? $raw['evalStar'] ?? 5);
        $content     = (string) ($raw['buyerTranslationFeedback'] ?? $raw['buyerFeedback'] ?? $raw['evalContent'] ?? '');
        $date        = (string) ($raw['evalDate'] ?? $raw['evalDateStr'] ?? '');
        $country     = (string) ($raw['buyerCountry'] ?? '');

        // Clamp rating to 1-5
        $rating = max(1, min(5, $rating));

        // Collect images
        $images = [];

        $raw_images = $raw['images'] ?? $raw['evalImages'] ?? [];

        if (is_array($raw_images)) {
            foreach ($raw_images as $img) {
                if (is_string($img) && $img !== '') {
                    $images[] = $img;
                } elseif (is_array($img) && ! empty($img['url'])) {
                    $images[] = (string) $img['url'];
                }
            }
        }

        return [
            'author_name' => $author_name,
            'rating'      => $rating,
            'content'     => $content,
            'date'        => $date,
            'images'      => $images,
            'country'     => $country,
        ];
    }
}
