<?php

namespace AC_SYNC\Includes\Classes\Differential\Entities;

if (!defined('ABSPATH'))
    exit; // Exit if accessed directly
use AC_SYNC\Includes\Classes\Differential\Entities\Action_Wear_Entities as Entities;
use AC_SYNC\Includes\Classes\Differential\Entities\Action_Wear_Entities_Interface as EntitiesInterface;
use AC_SYNC\Includes\Classes\Api\Action_Wear_Api as Api;
use AC_SYNC\Includes\Classes\Logger\Action_Wear_Log as Log;
use AC_SYNC\Includes\Classes\Differential\Schema\Action_Wear_Quantity_Schema as QuantitySchema;

class Action_Wear_Quantity extends Entities implements EntitiesInterface
{

    const DRY_RUN = false;
    const UPDATE_TIMING = 1800;

    public function getUpdateTiming(): int
    {
        return self::UPDATE_TIMING;
    }

    public function execute(): bool
    {
        $date = date("Y-m-d H:i", $this->getExecutionTime());

        $quantities = Api::external(
            "GET",
            "/stockall?compress=0&output=json&from=$date"
        );

        $code = $quantities["code"];
        if ($code !== 200) {
            $error_msg = "Errore durante la chiamata al differenziale delle quantità, restituito codice: " . $code;
            Log::write($error_msg, Log::ERROR, Log::CONTEXT_CAMAC_API);
            throw new \Exception($error_msg);
        }

        $decoded = json_decode($quantities["raw"]["body"], true);

        $quantities = self::normalizeApiResponse($decoded);
        if ($quantities === null || count($quantities) === 0) {
            $this->updateExecutionTime();
            Log::write("Nessun aggiornamento di quantità trovato nell'arco di tempo che va da $date ad adesso", Log::INFO, Log::CONTEXT_CAMAC_API);
            return false;
        }

        $first_key = array_key_first($quantities);
        $firstItem = $quantities[$first_key];
        if (!is_array($firstItem)) {
            Log::write("Schema quantità non valido: formato risposta API inatteso. Primo elemento: " . gettype($firstItem), Log::ERROR, Log::CONTEXT_CAMAC_API);
            return false;
        }

        $this->setApiSchema(array_keys($firstItem));
        if (!$this->conformToSchema(new QuantitySchema)) {
            Log::write("Schema non conforme", Log::ERROR, Log::CONTEXT_CAMAC_API);
            return false;
        }

        // Collect all SKUs for batch lookup
        $allSkus = [];
        foreach ($quantities as $quantity) {
            if (!empty($quantity["sku"])) $allSkus[] = $quantity["sku"];
        }
        $allSkus = array_unique($allSkus);

        // Batch SKU -> post_id lookup (single query)
        global $wpdb;
        $skuToPostId = [];
        if (!empty($allSkus)) {
            $placeholders = implode(',', array_fill(0, count($allSkus), '%s'));
            $results = $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT pm.meta_value AS sku, pm.post_id
                    FROM {$wpdb->postmeta} pm
                    INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id
                    WHERE pm.meta_key = '_sku'
                    AND pm.meta_value IN ($placeholders)",
                    ...$allSkus
                )
            );
            foreach ($results as $row) {
                $skuToPostId[$row->sku] = (int) $row->post_id;
            }
        }

        $processed = 0;
        $updatedParentIds = [];
        foreach ($quantities as $quantity) {
            $sku = $quantity["sku"];
            $id = $skuToPostId[$sku] ?? 0;
            if ($id === 0)
                continue;
            $processed++;
            $qty_available = (float) $quantity["available"];
            $qty_supplier = (float) $quantity["supplier"];
            $qty_total_arrivals = (float) $quantity["total_arrivals"];
            if (self::DRY_RUN) {
                Log::write("Aggiorno la quantità del prodotto $sku, quantità disponibile: $qty_available, quantità fornitore: $qty_supplier, quantità total_arrivals: $qty_total_arrivals", Log::INFO, Log::CONTEXT_PRODUCT_UPDATE);
                continue;
            }
            // Direct meta updates instead of WC product load+save
            update_post_meta($id, '_manage_stock', 'yes');
            update_post_meta($id, '_stock', $qty_available);
            update_post_meta($id, '_stock_status', $qty_available > 0 ? 'instock' : 'outofstock');
            update_post_meta($id, "quantity_supplier", $qty_supplier);
            update_post_meta($id, "total_arrivals", $qty_total_arrivals);
            wc_delete_product_transients($id);

            // Track parent for stock status sync
            $parentId = wp_get_post_parent_id($id);
            if ($parentId) {
                $updatedParentIds[$parentId] = true;
            }
        }

        // Sync parent variable product stock status from children
        foreach (array_keys($updatedParentIds) as $parentId) {
            $parentProduct = wc_get_product($parentId);
            if ($parentProduct && $parentProduct->is_type('variable')) {
                $children = $parentProduct->get_children();
                $hasInStock = false;
                foreach ($children as $childId) {
                    if (get_post_meta($childId, '_stock_status', true) === 'instock') {
                        $hasInStock = true;
                        break;
                    }
                }
                $parentProduct->set_stock_status($hasInStock ? 'instock' : 'outofstock');
                $parentProduct->save();
            }
        }

        Log::write("Ho aggiornato le quantità da $date ad adesso, " . count($quantities) . " record presenti e $processed record aggiornati", Log::INFO, Log::CONTEXT_CAMAC_API);

        $this->updateExecutionTime();
        return true;
    }
}
