<?php
/**
 * Weighted Average Cost (WAC / CUMP / Moyenne Pondérée) engine.
 *
 * @package Bizmart
 * @license GPL-2.0-or-later
 * @since   3.0
 */
if (!defined('ABSPATH')) exit;

/**
 * Get the configured valuation method.
 * @return string 'wac' | 'last_price' | 'manual'
 */
function bizmart_get_valuation_method(): string {
    if (!function_exists('bizmart_get_option')) return 'last_price';
    $m = bizmart_get_option('biz_valuation_method', 'last_price');
    return in_array($m, ['wac', 'last_price', 'manual'], true) ? $m : 'last_price';
}

/**
 * Calculate Batch WAC for a single product.
 *
 * @param int         $product_id  WC product or variation ID
 * @param string|null $before_date Optional date cutoff (for historical WAC)
 * @return float WAC rounded to 2 decimals, or 0.0 if no invoice data
 */
function bizmart_get_wac(int $product_id, ?string $before_date = null): float {
    global $wpdb;

    $items_table    = $wpdb->prefix . 'bizmart_invoice_items';
    $invoices_table = $wpdb->prefix . 'bizmart_invoices';

    if (!bizmart_table_exists('bizmart_invoice_items') || !bizmart_table_exists('bizmart_invoices')) {
        return 0.0;
    }

    $sql = "SELECT
                SUM(ii.quantity * ii.purchase_price) AS total_cost,
                SUM(ii.quantity) AS total_qty
            FROM {$items_table} ii
            JOIN {$invoices_table} i ON ii.invoice_id = i.id
            WHERE ii.product_id = %d
              AND i.doc_status = 'approved'
              AND i.deleted_at IS NULL
              AND ii.purchase_price > 0
              AND ii.quantity > 0";

    $params = [$product_id];

    if ($before_date) {
        $sql .= " AND i.created_at <= %s";
        $params[] = $before_date . ' 23:59:59';
    }

    $row = $wpdb->get_row($wpdb->prepare($sql, ...$params));

    if (!$row || !$row->total_qty || (float)$row->total_qty <= 0) {
        return 0.0;
    }

    return round((float)$row->total_cost / (float)$row->total_qty, 2);
}

/**
 * Calculate WAC for ALL products at once (single query).
 * Returns associative array [product_id => wac].
 * Cached: transient bizmart_all_wac_v1 (10 min).
 */
function bizmart_get_all_wac(bool $use_cache = true): array {
    global $wpdb;

    $blog_id   = (int) get_current_blog_id();
    $cache_key = 'bizmart_all_wac_v1_' . $blog_id;
    $ttl       = 10 * MINUTE_IN_SECONDS;

    if ($use_cache) {
        $cached = get_transient($cache_key);
        if (is_array($cached)) {
            return $cached;
        }
    }

    $items_table    = $wpdb->prefix . 'bizmart_invoice_items';
    $invoices_table = $wpdb->prefix . 'bizmart_invoices';

    if (!bizmart_table_exists('bizmart_invoice_items') || !bizmart_table_exists('bizmart_invoices')) {
        return [];
    }

    // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- table names only, no user input
    $rows = $wpdb->get_results(
        "SELECT
            ii.product_id,
            SUM(ii.quantity * ii.purchase_price) / SUM(ii.quantity) AS wac
         FROM {$items_table} ii
         JOIN {$invoices_table} i ON ii.invoice_id = i.id
         WHERE i.doc_status = 'approved'
           AND i.deleted_at IS NULL
           AND ii.purchase_price > 0
           AND ii.quantity > 0
         GROUP BY ii.product_id"
    );

    $result = [];
    if ($rows) {
        foreach ($rows as $r) {
            $result[(int)$r->product_id] = round((float)$r->wac, 2);
        }
    }

    set_transient($cache_key, $result, $ttl);
    return $result;
}

/**
 * Invalidate WAC cache. Called on invoice save/delete.
 */
function bizmart_invalidate_wac_cache(): void {
    $blog_id = (int) get_current_blog_id();
    delete_transient('bizmart_all_wac_v1_' . $blog_id);
}

// Invalidate WAC when invoices change
add_action('bizmart_invoice_saved', 'bizmart_invalidate_wac_cache');
add_action('bizmart_invoice_deleted', 'bizmart_invalidate_wac_cache');
// Also hook into the general product cache invalidation
add_action('bizmart_product_cache_invalidated', 'bizmart_invalidate_wac_cache');
