<?php

namespace AC_SYNC\Includes\Classes\Sync;

if (!defined('ABSPATH')) exit;

use AC_SYNC\Includes\Classes\Api\Action_Wear_Api as Api;
use AC_SYNC\Includes\Classes\Logger\Action_Wear_Log as Log;

class Action_Wear_Sync_Cache
{
    const CACHE_TTL = 7200;

    private static $priceCache = null;
    private static $quantityCache = null;

    public static function getPrice($variationSku)
    {
        $data = self::getPriceData();
        return isset($data[$variationSku]) ? $data[$variationSku] : null;
    }

    public static function getQuantity($variationSku)
    {
        $data = self::getQuantityData();
        return isset($data[$variationSku]) ? $data[$variationSku] : null;
    }

    public static function warmPriceCache()
    {
        $data = self::getPriceData();
        return !empty($data);
    }

    public static function warmQuantityCache()
    {
        $data = self::getQuantityData();
        return !empty($data);
    }

    public static function flush()
    {
        $priceFile = self::getCacheFilePath('prices');
        $quantityFile = self::getCacheFilePath('quantities');

        if (file_exists($priceFile)) @unlink($priceFile);
        if (file_exists($quantityFile)) @unlink($quantityFile);

        self::$priceCache = null;
        self::$quantityCache = null;

        Log::write("SyncCache: Flushed price and quantity cache files", Log::INFO, Log::CONTEXT_CRONJOB);
    }

    private static function getPriceData()
    {
        if (self::$priceCache !== null) {
            return self::$priceCache;
        }

        $data = self::readCacheFile('prices');
        if ($data !== null) {
            self::$priceCache = $data;
            return $data;
        }

        $data = self::fetchAndCachePrices();
        self::$priceCache = $data;
        return $data;
    }

    private static function getQuantityData()
    {
        if (self::$quantityCache !== null) {
            return self::$quantityCache;
        }

        $data = self::readCacheFile('quantities');
        if ($data !== null) {
            self::$quantityCache = $data;
            return $data;
        }

        $data = self::fetchAndCacheQuantities();
        self::$quantityCache = $data;
        return $data;
    }

    private static function getCacheFilePath($type)
    {
        $uploadDir = wp_upload_dir();
        $cacheDir = $uploadDir['basedir'] . '/actionwear-cache';

        if (!is_dir($cacheDir)) {
            wp_mkdir_p($cacheDir);
            @file_put_contents($cacheDir . '/.htaccess', 'deny from all');
            @file_put_contents($cacheDir . '/index.php', '<?php // Silence is golden');
        }

        return $cacheDir . '/sync-cache-' . $type . '.json';
    }

    private static function readCacheFile($type)
    {
        $file = self::getCacheFilePath($type);

        if (!file_exists($file)) {
            return null;
        }

        $age = time() - filemtime($file);
        if ($age > self::CACHE_TTL) {
            @unlink($file);
            return null;
        }

        $content = @file_get_contents($file);
        if ($content === false) {
            return null;
        }

        $data = @json_decode($content, true);

        if (!is_array($data)) {
            @unlink($file);
            return null;
        }

        return $data;
    }

    private static function writeCacheFile($type, $data)
    {
        $file = self::getCacheFilePath($type);
        $content = json_encode($data);
        @file_put_contents($file, $content, LOCK_EX);
    }

    private static function fetchAndCachePrices()
    {
        try {
            $response = Api::external("GET", "/pricesall?compress=0&output=json", array("timeout" => 300));

            if ($response['code'] !== 200) {
                Log::write("SyncCache: Price API error code " . $response['code'], Log::ERROR, Log::CONTEXT_CRONJOB);
                return array();
            }

            $decoded = json_decode($response['body'], true);
            $priceItems = isset($decoded[0]) ? $decoded[0] : $decoded;

            if (!is_array($priceItems)) {
                Log::write("SyncCache: Invalid price API response", Log::ERROR, Log::CONTEXT_CRONJOB);
                return array();
            }

            $map = array();
            foreach ($priceItems as $item) {
                $skus = isset($item['sku']) ? $item['sku'] : array();
                if (!is_array($skus)) $skus = array($skus);
                $basePrice = isset($item['prezzo unita'])
                    ? floatval(str_replace(',', '.', $item['prezzo unita']))
                    : null;

                if ($basePrice !== null) {
                    foreach ($skus as $sku) {
                        if ($sku) {
                            $map[$sku] = array('base_price' => $basePrice);
                        }
                    }
                }
            }

            self::writeCacheFile('prices', $map);
            Log::write("SyncCache: Cached " . count($map) . " price entries to file", Log::INFO, Log::CONTEXT_CRONJOB);

            return $map;
        } catch (\Throwable $e) {
            Log::write("SyncCache: Failed to fetch prices - " . $e->getMessage(), Log::ERROR, Log::CONTEXT_CRONJOB);
            return array();
        }
    }

    private static function fetchAndCacheQuantities()
    {
        try {
            $response = Api::external("GET", "/stockall?compress=0&output=json", array("timeout" => 300));

            if ($response['code'] !== 200) {
                Log::write("SyncCache: Quantity API error code " . $response['code'], Log::ERROR, Log::CONTEXT_CRONJOB);
                return array();
            }

            $decoded = json_decode($response['body'], true);

            if (!is_array($decoded)) {
                Log::write("SyncCache: Invalid quantity API response", Log::ERROR, Log::CONTEXT_CRONJOB);
                return array();
            }

            $map = array();
            foreach ($decoded as $sku => $stockData) {
                if (is_array($stockData)) {
                    $map[$sku] = $stockData;
                }
            }

            self::writeCacheFile('quantities', $map);
            Log::write("SyncCache: Cached " . count($map) . " quantity entries to file", Log::INFO, Log::CONTEXT_CRONJOB);

            return $map;
        } catch (\Throwable $e) {
            Log::write("SyncCache: Failed to fetch quantities - " . $e->getMessage(), Log::ERROR, Log::CONTEXT_CRONJOB);
            return array();
        }
    }
}
