<?php
/**
 * GGM Commerce Product Tools
 *
 * MCP Tools for product search and filtering
 * Tools are executable actions that AI can invoke
 *
 * @package GGM_Commerce
 * @since 1.0.0
 */

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
// phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching
// phpcs:disable PluginCheck.Security.DirectDB.UnescapedDBParameter

class GGM_Commerce_Product_Tools {

    /**
     * MCP Server instance
     * @var GGM_Commerce_MCP_Server
     */
    private $server;

    /**
     * Constructor
     *
     * @param GGM_Commerce_MCP_Server $server MCP server instance
     */
    public function __construct($server) {
        $this->server = $server;
        $this->register_tools();
    }

    /**
     * Register all product tools
     */
    private function register_tools() {
        // Search products
        $this->server->register_tool(
            'search_products',
            'Search products by name, description, or various filters',
            [
                'type' => 'object',
                'properties' => [
                    'search_term' => [
                        'type' => 'string',
                        'description' => 'Search term to match against product name, description, or SKU'
                    ],
                    'category_id' => [
                        'type' => 'integer',
                        'description' => 'Filter by category ID',
                        'minimum' => 1
                    ],
                    'tag_id' => [
                        'type' => 'integer',
                        'description' => 'Filter by tag ID',
                        'minimum' => 1
                    ],
                    'min_price' => [
                        'type' => 'number',
                        'description' => 'Minimum price filter',
                        'minimum' => 0
                    ],
                    'max_price' => [
                        'type' => 'number',
                        'description' => 'Maximum price filter',
                        'minimum' => 0
                    ],
                    'in_stock_only' => [
                        'type' => 'boolean',
                        'description' => 'Show only products in stock',
                        'default' => false
                    ],
                    'sort_by' => [
                        'type' => 'string',
                        'description' => 'Sort order: name, price_asc, price_desc, newest',
                        'enum' => ['name', 'price_asc', 'price_desc', 'newest'],
                        'default' => 'name'
                    ],
                    'limit' => [
                        'type' => 'integer',
                        'description' => 'Maximum number of results',
                        'minimum' => 1,
                        'maximum' => 100,
                        'default' => 20
                    ]
                ]
            ],
            [$this, 'search_products']
        );

        // Find product by SKU
        $this->server->register_tool(
            'find_product_by_sku',
            'Find a specific product by its SKU',
            [
                'type' => 'object',
                'properties' => [
                    'sku' => [
                        'type' => 'string',
                        'description' => 'Product SKU to search for'
                    ]
                ],
                'required' => ['sku']
            ],
            [$this, 'find_product_by_sku']
        );

        // Get product recommendations
        $this->server->register_tool(
            'get_product_recommendations',
            'Get product recommendations based on a product ID or category',
            [
                'type' => 'object',
                'properties' => [
                    'product_id' => [
                        'type' => 'integer',
                        'description' => 'Base product ID for recommendations',
                        'minimum' => 1
                    ],
                    'category_id' => [
                        'type' => 'integer',
                        'description' => 'Category ID for recommendations',
                        'minimum' => 1
                    ],
                    'limit' => [
                        'type' => 'integer',
                        'description' => 'Maximum number of recommendations',
                        'minimum' => 1,
                        'maximum' => 20,
                        'default' => 5
                    ]
                ]
            ],
            [$this, 'get_product_recommendations']
        );

        // Check product availability
        $this->server->register_tool(
            'check_product_availability',
            'Check stock availability for one or more products',
            [
                'type' => 'object',
                'properties' => [
                    'product_ids' => [
                        'type' => 'array',
                        'description' => 'Array of product IDs to check',
                        'items' => [
                            'type' => 'integer',
                            'minimum' => 1
                        ]
                    ]
                ],
                'required' => ['product_ids']
            ],
            [$this, 'check_product_availability']
        );

        // List available product types
        $this->server->register_tool(
            'list_product_types',
            'List all available product types, including which ones are active based on premium components',
            [
                'type' => 'object',
                'properties' => []
            ],
            [$this, 'list_product_types']
        );
    }

    /**
     * Search products with filters
     *
     * @param array $args Tool arguments
     * @return array Search results
     */
    public function search_products($args) {
        global $wpdb;

        $where = ["(p.status = 'active' OR p.status IS NULL)"];
        $params = [];
        $joins = [];

        // Search term
        if (!empty($args['search_term'])) {
            $search_term = '%' . $wpdb->esc_like($args['search_term']) . '%';
            $where[] = "(p.name LIKE %s OR p.description LIKE %s OR p.sku LIKE %s)";
            $params[] = $search_term;
            $params[] = $search_term;
            $params[] = $search_term;
        }

        // Category filter - use relationship table
        if (!empty($args['category_id'])) {
            $joins[] = "INNER JOIN {$wpdb->prefix}ggmc_product_categories pc ON p.id = pc.product_id";
            $where[] = "pc.category_id = %d";
            $params[] = intval($args['category_id']);
        }

        // Tag filter - use relationship table
        if (!empty($args['tag_id'])) {
            $joins[] = "INNER JOIN {$wpdb->prefix}ggmc_product_tags pt ON p.id = pt.product_id";
            $where[] = "pt.tag_id = %d";
            $params[] = intval($args['tag_id']);
        }

        // Price range
        if (isset($args['min_price'])) {
            $where[] = "p.price >= %f";
            $params[] = floatval($args['min_price']);
        }

        if (isset($args['max_price'])) {
            $where[] = "p.price <= %f";
            $params[] = floatval($args['max_price']);
        }

        // Stock filter
        if (!empty($args['in_stock_only'])) {
            $where[] = "p.stock > 0 AND (p.stock_status = 'instock' OR p.stock_status IS NULL)";
        }

        // Build sort clause
        $sort_by = isset($args['sort_by']) ? $args['sort_by'] : 'name';
        $order_by = match($sort_by) {
            'price_asc' => 'p.price ASC',
            'price_desc' => 'p.price DESC',
            'newest' => 'p.created_at DESC',
            default => 'p.name ASC'
        };

        // Limit
        $limit = isset($args['limit']) ? min(intval($args['limit']), 100) : 20;

        // Build query
        $join_clause = !empty($joins) ? implode(' ', $joins) : '';
        $where_clause = implode(' AND ', $where);
        $sql = "SELECT DISTINCT p.*
                FROM {$wpdb->prefix}ggmc_products p
                {$join_clause}
                WHERE {$where_clause}
                ORDER BY {$order_by}
                LIMIT %d";

        $params[] = $limit;

        if (count($params) > 0) {
            // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- $sql is built safely above, interpolated variables are sanitized
            $query = $wpdb->prepare($sql, $params);
        } else {
            $query = $sql;
        }

        // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- $query is prepared above or contains no user input
        $products = $wpdb->get_results($query);

        // Process products and add categories
        foreach ($products as &$product) {
            $product = $this->process_product_data($product);
            // Get categories from relationship table
            $categories = $wpdb->get_results($wpdb->prepare(
                "SELECT c.name, c.slug
                FROM {$wpdb->prefix}ggmc_categories c
                INNER JOIN {$wpdb->prefix}ggmc_product_categories pc ON c.id = pc.category_id
                WHERE pc.product_id = %d AND c.status = 'active'",
                $product->id
            ));
            $product->categories = $categories;
            $product->category_name = !empty($categories) ? $categories[0]->name : null;
            $product->category_slug = !empty($categories) ? $categories[0]->slug : null;
        }

        return [
            'success' => true,
            'products' => $products,
            'count' => count($products),
            'filters_applied' => [
                'search_term' => $args['search_term'] ?? null,
                'category_id' => $args['category_id'] ?? null,
                'tag_id' => $args['tag_id'] ?? null,
                'min_price' => $args['min_price'] ?? null,
                'max_price' => $args['max_price'] ?? null,
                'in_stock_only' => $args['in_stock_only'] ?? false,
                'sort_by' => $sort_by,
                'limit' => $limit
            ]
        ];
    }

    /**
     * Find product by SKU
     *
     * @param array $args Tool arguments
     * @return array Product data or error
     */
    public function find_product_by_sku($args) {
        $sku = sanitize_text_field($args['sku']);

        global $wpdb;

        $product = $wpdb->get_row($wpdb->prepare(
            "SELECT p.*
            FROM {$wpdb->prefix}ggmc_products p
            WHERE p.sku = %s",
            $sku
        ));

        if (!$product) {
            return [
                'success' => false,
                'error' => 'Product not found with SKU: ' . $sku
            ];
        }

        $product = $this->process_product_data($product);

        // Get categories from relationship table
        $categories = $wpdb->get_results($wpdb->prepare(
            "SELECT c.name, c.slug
            FROM {$wpdb->prefix}ggmc_categories c
            INNER JOIN {$wpdb->prefix}ggmc_product_categories pc ON c.id = pc.category_id
            WHERE pc.product_id = %d AND c.status = 'active'",
            $product->id
        ));
        $product->categories = $categories;
        $product->category_name = !empty($categories) ? $categories[0]->name : null;
        $product->category_slug = !empty($categories) ? $categories[0]->slug : null;

        return [
            'success' => true,
            'product' => $product
        ];
    }

    /**
     * Get product recommendations
     *
     * @param array $args Tool arguments
     * @return array Recommended products
     */
    public function get_product_recommendations($args) {
        global $wpdb;

        $limit = isset($args['limit']) ? min(intval($args['limit']), 20) : 5;

        // Base recommendations on product ID
        if (!empty($args['product_id'])) {
            $product_id = intval($args['product_id']);

            // Get the base product
            $base_product = $wpdb->get_row($wpdb->prepare(
                "SELECT * FROM {$wpdb->prefix}ggmc_products WHERE id = %d",
                $product_id
            ));

            if (!$base_product) {
                return [
                    'success' => false,
                    'error' => 'Base product not found'
                ];
            }

            // Get the first category of the base product from relationship table
            $base_category_id = $wpdb->get_var($wpdb->prepare(
                "SELECT category_id FROM {$wpdb->prefix}ggmc_product_categories WHERE product_id = %d LIMIT 1",
                $product_id
            ));

            // Get products in same category with similar price range
            $min_price = $base_product->price * 0.7;
            $max_price = $base_product->price * 1.3;

            $products = $wpdb->get_results($wpdb->prepare(
                "SELECT DISTINCT p.*
                FROM {$wpdb->prefix}ggmc_products p
                INNER JOIN {$wpdb->prefix}ggmc_product_categories pc ON p.id = pc.product_id
                WHERE pc.category_id = %d
                    AND p.id != %d
                    AND p.price BETWEEN %f AND %f
                    AND (p.status = 'active' OR p.status IS NULL)
                    AND p.stock > 0
                ORDER BY ABS(p.price - %f)
                LIMIT %d",
                $base_category_id,
                $product_id,
                $min_price,
                $max_price,
                $base_product->price,
                $limit
            ));

            $recommendation_basis = "Based on product: {$base_product->name}";
        }
        // Base recommendations on category
        elseif (!empty($args['category_id'])) {
            $category_id = intval($args['category_id']);

            $products = $wpdb->get_results($wpdb->prepare(
                "SELECT DISTINCT p.*
                FROM {$wpdb->prefix}ggmc_products p
                INNER JOIN {$wpdb->prefix}ggmc_product_categories pc ON p.id = pc.product_id
                WHERE pc.category_id = %d
                    AND (p.status = 'active' OR p.status IS NULL)
                    AND p.stock > 0
                ORDER BY p.created_at DESC
                LIMIT %d",
                $category_id,
                $limit
            ));

            $category = $wpdb->get_var($wpdb->prepare(
                "SELECT name FROM {$wpdb->prefix}ggmc_categories WHERE id = %d",
                $category_id
            ));

            $recommendation_basis = "Based on category: {$category}";
        }
        // Default: popular/newest products
        else {
            $products = $wpdb->get_results($wpdb->prepare(
                "SELECT p.*
                FROM {$wpdb->prefix}ggmc_products p
                WHERE (p.status = 'active' OR p.status IS NULL)
                    AND p.stock > 0
                ORDER BY p.created_at DESC
                LIMIT %d",
                $limit
            ));

            $recommendation_basis = "Popular and new products";
        }

        // Process products and add categories
        foreach ($products as &$product) {
            $product = $this->process_product_data($product);
            // Get categories from relationship table
            $categories = $wpdb->get_results($wpdb->prepare(
                "SELECT c.name, c.slug
                FROM {$wpdb->prefix}ggmc_categories c
                INNER JOIN {$wpdb->prefix}ggmc_product_categories pc ON c.id = pc.category_id
                WHERE pc.product_id = %d AND c.status = 'active'",
                $product->id
            ));
            $product->categories = $categories;
            $product->category_name = !empty($categories) ? $categories[0]->name : null;
        }

        return [
            'success' => true,
            'recommendations' => $products,
            'count' => count($products),
            'basis' => $recommendation_basis
        ];
    }

    /**
     * Check product availability
     *
     * @param array $args Tool arguments
     * @return array Availability data
     */
    public function check_product_availability($args) {
        if (empty($args['product_ids']) || !is_array($args['product_ids'])) {
            return [
                'success' => false,
                'error' => 'product_ids array is required'
            ];
        }

        global $wpdb;

        $product_ids = array_map('intval', $args['product_ids']);
        $placeholders = implode(',', array_fill(0, count($product_ids), '%d'));

        $products = $wpdb->get_results($wpdb->prepare(
            "SELECT
                id,
                name,
                sku,
                stock,
                stock_status,
                price
            FROM {$wpdb->prefix}ggmc_products
            WHERE id IN ($placeholders)", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare -- $placeholders is safely built from intval IDs
            $product_ids
        ));

        $availability = [];
        foreach ($products as $product) {
            $stock = intval($product->stock);
            $is_available = $stock > 0 && ($product->stock_status === 'instock' || $product->stock_status === null);

            $availability[] = [
                'product_id' => (int) $product->id,
                'name' => $product->name,
                'sku' => $product->sku,
                'stock' => $stock,
                'is_available' => $is_available,
                'status_message' => $is_available
                    ? "In stock ({$stock} available)"
                    : ($stock > 0 ? 'Out of stock' : 'No stock available'),
                'price' => (float) $product->price
            ];
        }

        // Check for missing products
        $found_ids = array_column($products, 'id');
        $missing_ids = array_diff($product_ids, $found_ids);

        if (!empty($missing_ids)) {
            foreach ($missing_ids as $missing_id) {
                $availability[] = [
                    'product_id' => $missing_id,
                    'error' => 'Product not found'
                ];
            }
        }

        return [
            'success' => true,
            'availability' => $availability,
            'checked_count' => count($product_ids)
        ];
    }

    /**
     * Process product data
     *
     * @param object $product Product object
     * @return object Processed product
     */
    private function process_product_data($product) {
        // Build images array from image_id and gallery_ids
        $product->images = [];

        // Add main image from image_id
        if (!empty($product->image_id)) {
            $image_url = wp_get_attachment_url($product->image_id);
            if ($image_url) {
                $product->images[] = $image_url;
                $product->image_url = $image_url; // For backwards compatibility
            }
        }

        // Add gallery images from gallery_ids
        if (!empty($product->gallery_ids)) {
            $gallery_ids = array_filter(array_map('intval', explode(',', $product->gallery_ids)));
            foreach ($gallery_ids as $gallery_id) {
                $gallery_url = wp_get_attachment_url($gallery_id);
                if ($gallery_url) {
                    $product->images[] = $gallery_url;
                }
            }
        }

        // Type casting
        $product->id = (int) $product->id;
        $product->price = (float) $product->price;
        $product->stock = isset($product->stock) ? (int) $product->stock : 0;

        // Product type (default to simple)
        $product->product_type = $product->product_type ?? 'simple';

        // Availability flag
        $product->is_available = ($product->stock > 0 && ($product->stock_status === 'instock' || $product->stock_status === null));

        return $product;
    }

    /**
     * List available product types
     *
     * Returns all product types with their availability based on active premium components
     *
     * @param array $args Tool arguments (unused)
     * @return array Result
     */
    public function list_product_types($args = []) {
        $all_types = GGM_Commerce_Helpers::get_product_types();
        $license = GGM_Commerce_License::instance();
        $result = [];

        foreach ($all_types as $slug => $type) {
            $active = true;

            // Check if this type requires a premium component
            if (!empty($type['premium']) && !empty($type['premium_slug'])) {
                $active = $license->is_widget_activated($type['premium_slug']);
            }

            $result[] = [
                'slug' => $slug,
                'label' => $type['label'],
                'description' => $type['description'],
                'premium' => !empty($type['premium']),
                'active' => $active,
            ];
        }

        return [
            'success' => true,
            'product_types' => $result,
            'count' => count($result)
        ];
    }
}
