<?php

namespace App\Jobs\Tasks;

use App\Helpers\FirstParty\OSSUploader\OSSUploader;
use App\Models\Category;
use App\Models\ShopeeSellerScrape;
use Exception;

class ShopeeSellerTopProductScraperTask
{
    public static function handle(string $seller, string $country_iso, Category $category)
    {

        $country_iso = strtolower($country_iso);

        if (is_empty($seller)) {
            throw new Exception('Missing \'seller\' attribute.');
        }

        $shopee_seller_scrape = ShopeeSellerScrape::where('seller', $seller)
            ->where('country_iso', $country_iso)->first();

        if (! is_null($shopee_seller_scrape)) {
            $serialised = OSSUploader::readFile('r2', 'shopee/seller', $shopee_seller_scrape->filename);

            if (! is_empty($serialised)) {
                $obj = unserialize($serialised);
                $obj->shopee_seller_scrape = $shopee_seller_scrape;

                return $obj;
            }
        }

        $epoch = epoch_now_timestamp();

        $seller_shop_url = "https://shopee.com.my/{$seller}?page=0&sortBy=sales";

        $seller_shop_task = UrlCrawlerTask::handle($seller_shop_url, 'shopee/seller', $epoch, true, false);

        //dd($seller_shop_task);

        if (isset($seller_shop_task->response->jsonld)) {
            $top_rank_products = self::getSortedData($seller_shop_task->response->jsonld, 400);

            if (count($top_rank_products) > 0) {

                $product_found = null;

                foreach ($top_rank_products as $product) {
                    $product_task = UrlCrawlerTask::handle($product->url, 'shopee/seller', $epoch, true, true);

                    if ($product_task->response->status_code >= 0) {
                        $product_found = $product_task->response;
                        break;
                    }
                }

                $scraped = (object) [
                    'seller_shop_task' => (object) [
                        'response' => $seller_shop_task->response,
                    ],
                    'product_task' => (object) [
                        'response' => $product_task->response,
                    ],
                ];

                $serialised = serialize($scraped);

                $filename = $seller.'-'.$epoch.'-'.$country_iso.'.txt';

                OSSUploader::uploadFile('r2', 'shopee/seller', $filename, $serialised);

                $shopee_seller_scrape = new ShopeeSellerScrape;
                $shopee_seller_scrape->seller = $seller;
                $shopee_seller_scrape->country_iso = $country_iso;
                $shopee_seller_scrape->epoch = $epoch;
                $shopee_seller_scrape->filename = $filename;
                $shopee_seller_scrape->category_id = $category->id;

                if ($shopee_seller_scrape->save()) {
                    return (object) compact('seller_shop_task', 'product_task', 'shopee_seller_scrape');
                }

            }
        }

        return null;
    }

    private static function getSortedData($data, $minValue)
    {
        // Filter the items of type "Product" with an offer price greater than 200
        $filtered = array_filter($data, function ($item) use ($minValue) {
            $isProduct = $item->{'@type'} === 'Product';
            $lowPrice = floatval($item->offers?->lowPrice ?? 0);
            $price = floatval($item->offers?->price ?? 0);

            return $isProduct && ($lowPrice > $minValue) || ($price > $minValue);
        });

        // Sort the items based on `ratingCount` and `ratingValue` in descending order
        usort($filtered, function ($a, $b) {
            $ratingCountA = intval($a->aggregateRating?->ratingCount ?? 0);
            $ratingCountB = intval($b->aggregateRating?->ratingCount ?? 0);

            $ratingValueA = floatval($a->aggregateRating?->ratingValue ?? 0);
            $ratingValueB = floatval($b->aggregateRating?->ratingValue ?? 0);

            if ($ratingCountA !== $ratingCountB) {
                return $ratingCountB - $ratingCountA;
            }

            return $ratingValueB <=> $ratingValueA;
        });

        // Map the filtered and sorted items to a new array of objects
        return array_map(function ($item) {
            return (object) [
                'name' => $item->name ?? null,
                'description' => $item->description ?? null,
                'url' => $item->url ?? null,
                'image' => $item->image ?? null,
                'lowPrice' => floatval($item->offers?->lowPrice ?? 0),
                'highPrice' => floatval($item->offers?->highPrice ?? 0),
                'price' => floatval($item->offers?->price ?? 0),
                'priceCurrency' => $item->offers?->priceCurrency ?? null,
                'ratingCount' => intval($item->aggregateRating?->ratingCount ?? 0),
                'ratingValue' => floatval($item->aggregateRating?->ratingValue ?? 0),
            ];
        }, $filtered);
    }
}
