<?php
declare(strict_types=1);

namespace Instinctor\Services;

use Instinctor\Core\Config;
use Instinctor\Core\DB;


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

/**
 * ProductAddonService - Per-product add-ons (gift wrap, engraving, etc.)
 * @since 2.0.44
 */
class ProductAddonService
{
    /** @var bool|null Cached table-existence result */
    private static ?bool $tableExists = null;

    public static function isActive(): bool
    {
        return \Instinctor\Core\StoreFeatures::isFeatureEnabled('product_addons');
    }

    /**
     * Fast table-existence check (cached per request)
     */
    public static function tableExists(): bool
    {
        if (self::$tableExists !== null) {
            return self::$tableExists;
        }
        $table = DB::prefix() . 'instinctor_product_addons';
        self::$tableExists = (DB::get_var("SHOW TABLES LIKE '{$table}'") === $table);
        return self::$tableExists;
    }

    /**
     * Get add-ons for a specific product
     */
    public static function getProductAddons(int $productId): array
    {
        if (!self::tableExists()) {
            return [];
        }
        $table = DB::prefix() . 'instinctor_product_addons';
        return DB::get_results(
            DB::prepare(
                "SELECT * FROM {$table} WHERE product_id = %d AND is_active = 1 ORDER BY sort_order ASC",
                $productId
            ),
            ARRAY_A
        ) ?: [];
    }

    /**
     * Get global add-ons (apply to all products)
     */
    public static function getGlobalAddons(): array
    {
        if (!self::tableExists()) {
            return [];
        }
        $table = DB::prefix() . 'instinctor_product_addons';
        return DB::get_results(
            "SELECT * FROM {$table} WHERE product_id IS NULL AND is_active = 1 ORDER BY sort_order ASC",
            ARRAY_A
        ) ?: [];
    }

    /**
     * Get all add-ons for a product (global first, then product-specific)
     */
    public static function getAllAddons(int $productId): array
    {
        if (!self::isActive()) {
            return [];
        }
        return array_merge(
            self::getGlobalAddons(),
            self::getProductAddons($productId)
        );
    }

    /**
     * Look up display labels for a set of selected addon IDs+values.
     * Returns array of ['name' => string, 'value' => string, 'price_label' => string]
     *
     * @param array $selectedAddons  [addon_id => value]
     */
    public static function getAddonLabels(array $selectedAddons): array
    {
        if (empty($selectedAddons) || !self::tableExists()) {
            return [];
        }
        $table = DB::prefix() . 'instinctor_product_addons';
        $ids   = array_map('intval', array_keys($selectedAddons));
        $in    = implode(',', $ids);

        $rows = DB::get_results(
            "SELECT id, name, type, price, price_type FROM {$table} WHERE id IN ({$in})",
            ARRAY_A
        ) ?: [];

        $labels = [];
        foreach ($rows as $row) {
            $aid   = intval($row['id']);
            $value = (string)($selectedAddons[$aid] ?? '');
            $priceLabel = '';
            if (floatval($row['price']) > 0) {
                $priceLabel = $row['price_type'] === 'percent'
                    ? '+' . floatval($row['price']) . '%'
                    : '+' . CurrencyService::formatPrice(floatval($row['price']));
            }
            $displayValue = $row['type'] === 'checkbox' ? '' : $value;
            $labels[] = [
                'name'        => $row['name'],
                'value'       => $displayValue,
                'price_label' => $priceLabel,
            ];
        }
        return $labels;
    }

    /**
     * Save add-on
     */
    public static function saveAddon(array $data): int
    {
        $table = DB::prefix() . 'instinctor_product_addons';

        $options = [];
        if (!empty($data['options'])) {
            if (is_array($data['options'])) {
                $options = $data['options'];
            } else {
                $options = array_values(array_filter(array_map('trim', explode("\n", $data['options']))));
            }
        }

        $addonData = [
            'product_id'  => !empty($data['product_id']) ? intval($data['product_id']) : null,
            'name'        => sanitize_text_field($data['name'] ?? ''),
            'description' => sanitize_textarea_field($data['description'] ?? ''),
            'type'        => sanitize_text_field($data['type'] ?? 'checkbox'),
            'price'       => floatval($data['price'] ?? 0),
            'price_type'  => sanitize_text_field($data['price_type'] ?? 'flat'),
            'options'     => wp_json_encode($options),
            'required'    => intval($data['required'] ?? 0),
            'max_length'  => intval($data['max_length'] ?? 0),
            'is_active'   => intval($data['is_active'] ?? 1),
            'sort_order'  => intval($data['sort_order'] ?? 0),
        ];

        if (!empty($data['id'])) {
            DB::update($table, $addonData, ['id' => intval($data['id'])]);
            return intval($data['id']);
        } else {
            DB::insert($table, $addonData);
            return DB::insert_id();
        }
    }

    /**
     * Delete add-on
     */
    public static function deleteAddon(int $id): bool
    {
        $table = DB::prefix() . 'instinctor_product_addons';
        return DB::delete($table, ['id' => $id]) !== false;
    }

    /**
     * Calculate add-ons total price (single batch query).
     * File-type addons are excluded — files require dedicated upload handling.
     */
    public static function calculateAddonsTotal(array $selectedAddons, float $productPrice): float
    {
        if (empty($selectedAddons) || !self::tableExists()) {
            return 0.0;
        }

        // Filter out empty/unselected values up front
        $active = [];
        foreach ($selectedAddons as $addonId => $value) {
            if ($value !== '' && $value !== null && $value !== false) {
                $active[intval($addonId)] = $value;
            }
        }
        if (empty($active)) {
            return 0.0;
        }

        $table = DB::prefix() . 'instinctor_product_addons';
        $in    = implode(',', array_keys($active));

        // Single query for all active addon IDs
        $addons = DB::get_results(
            "SELECT id, type, price, price_type FROM {$table} WHERE id IN ({$in}) AND is_active = 1",
            ARRAY_A
        ) ?: [];

        $total = 0.0;
        foreach ($addons as $addon) {
            if ($addon['type'] === 'file') continue; // file uploads excluded from price
            $price = floatval($addon['price']);
            if ($price <= 0) continue;
            $total += $addon['price_type'] === 'percent'
                ? $productPrice * ($price / 100)
                : $price;
        }

        return round($total, 2);
    }

    /**
     * Render add-ons form HTML (lightweight alias)
     */
    public static function renderAddonsForm(int $productId): string
    {
        return self::renderAddonsHtml($productId, $productId);
    }

    /**
     * Render add-ons form HTML.
     *
     * @param int $productId  0 = global addons only
     * @param int $formKey    Unique key for DOM IDs; defaults to productId
     */
    public static function renderAddonsHtml(int $productId, int $formKey = 0): string
    {
        $addons = self::getAllAddons($productId);

        if (empty($addons)) {
            return '';
        }

        // Use a random suffix when formKey is 0 to avoid ID collisions
        $fk = ($formKey > 0) ? $formKey : 0;
        // Always add a unique suffix to prevent duplicate IDs on multi-grid pages
        static $counter = 0;
        $counter++;
        $wrapId = 'ia-addons-' . $fk . '-' . $counter;

        $html = '<div id="' . esc_attr($wrapId) . '" class="instinctor-product-addons" data-product-id="' . esc_attr((string)$productId) . '" style="margin:12px 0">';

        foreach ($addons as $addon) {
            $options  = json_decode($addon['options'] ?? '[]', true) ?: [];
            $price    = floatval($addon['price']);
            $priceLbl = '';
            if ($price > 0) {
                // Build price label; formatPrice returns raw text (not HTML), safe to esc_html later
                $priceLbl = $addon['price_type'] === 'percent'
                    ? ' (+' . floatval($addon['price']) . '%)'
                    : ' (+' . CurrencyService::formatPrice($price) . ')';
            }
            $req = $addon['required'] ? ' required' : '';
            $aid = intval($addon['id']);

            $html .= '<div class="instinctor-addon-item" style="margin-bottom:10px"'
                . ' data-addon-id="' . $aid . '"'
                . ' data-price="' . esc_attr((string)$price) . '"'
                . ' data-price-type="' . esc_attr($addon['price_type']) . '"'
                . ' data-required="' . ($addon['required'] ? '1' : '0') . '"'
                . ' data-type="' . esc_attr($addon['type']) . '"'
                . '>';

            switch ($addon['type']) {
                case 'checkbox':
                    $html .= '<label style="display:flex;align-items:flex-start;gap:8px;cursor:pointer;font-size:13px">';
                    $html .= '<input type="checkbox" class="ia-addon-check" name="addons[' . $aid . ']" value="1"' . $req . ' style="margin-top:2px;flex-shrink:0">';
                    $html .= '<span><strong>' . esc_html($addon['name']) . '</strong>' . esc_html($priceLbl) . '</span>';
                    $html .= '</label>';
                    break;

                case 'text':
                    $html .= '<div style="font-size:13px;font-weight:600;margin-bottom:4px">'
                        . esc_html($addon['name']) . esc_html($priceLbl) . '</div>';
                    $ml    = intval($addon['max_length']);
                    $html .= '<input type="text" class="ia-addon-text" name="addons[' . $aid . ']"' . $req
                        . ' style="width:100%;height:34px;padding:0 10px;border:1px solid #ddd;border-radius:4px;font-size:13px;box-sizing:border-box"'
                        . ($ml > 0 ? ' maxlength="' . $ml . '"' : '') . '>';
                    break;

                case 'textarea':
                    $html .= '<div style="font-size:13px;font-weight:600;margin-bottom:4px">'
                        . esc_html($addon['name']) . esc_html($priceLbl) . '</div>';
                    $ml    = intval($addon['max_length']);
                    $html .= '<textarea class="ia-addon-text" name="addons[' . $aid . ']"' . $req
                        . ' rows="3" style="width:100%;padding:8px 10px;border:1px solid #ddd;border-radius:4px;font-size:13px;box-sizing:border-box;resize:vertical"'
                        . ($ml > 0 ? ' maxlength="' . $ml . '"' : '') . '></textarea>';
                    break;

                case 'select':
                    $html .= '<div style="font-size:13px;font-weight:600;margin-bottom:4px">'
                        . esc_html($addon['name']) . esc_html($priceLbl) . '</div>';
                    $html .= '<select class="ia-addon-select" name="addons[' . $aid . ']"' . $req
                        . ' style="width:100%;height:34px;padding:0 10px;border:1px solid #ddd;border-radius:4px;font-size:13px;box-sizing:border-box">';
                    $html .= '<option value="">' . esc_html(instinctor__('Select…')) . '</option>';
                    foreach ($options as $opt) {
                        $html .= '<option value="' . esc_attr($opt) . '">' . esc_html($opt) . '</option>';
                    }
                    $html .= '</select>';
                    break;

                case 'file':
                    // File upload note — actual upload handling requires multipart POST
                    $html .= '<div style="font-size:13px;font-weight:600;margin-bottom:4px">'
                        . esc_html($addon['name']) . esc_html($priceLbl) . '</div>';
                    $html .= '<input type="file" class="ia-addon-file" name="addons_files[' . $aid . ']"' . $req
                        . ' style="font-size:13px">';
                    $html .= '<p style="margin:3px 0 0;font-size:11px;color:#aaa">'
                        . esc_html(instinctor__('File will be submitted with your order note.')) . '</p>';
                    break;
            }

            if (!empty($addon['description'])) {
                $html .= '<p style="margin:4px 0 0;font-size:11px;color:#888">' . esc_html($addon['description']) . '</p>';
            }

            $html .= '</div>';
        }

        $html .= '</div>'; // .instinctor-product-addons

        return $html;
    }

    /**
     * Create database tables
     */
    public static function createTables(): void
    {
        $charset = DB::get_charset_collate();

        $table = DB::prefix() . 'instinctor_product_addons';

        $sql = "CREATE TABLE IF NOT EXISTS {$table} (
            id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
            product_id bigint(20) unsigned DEFAULT NULL,
            name varchar(255) NOT NULL,
            description text,
            type varchar(20) DEFAULT 'checkbox',
            price decimal(10,2) DEFAULT 0,
            price_type varchar(20) DEFAULT 'flat',
            options longtext,
            required tinyint(1) DEFAULT 0,
            max_length int DEFAULT 0,
            is_active tinyint(1) DEFAULT 1,
            sort_order int DEFAULT 0,
            PRIMARY KEY (id),
            KEY product_id (product_id)
        ) {$charset};";

        require_once ABSPATH . 'wp-admin/includes/upgrade.php';
        dbDelta($sql);
    }
}

