<?php
/**
 * GGM Commerce Variation Tools
 *
 * MCP Tools for product variation management
 * Tools are executable actions that AI can invoke
 *
 * @package GGM_Commerce
 * @since 1.0.0
 */

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

class GGM_Commerce_Variation_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 variation tools
     */
    private function register_tools() {
        // List variation attributes
        $this->server->register_tool(
            'list_variation_attributes',
            'List all variation attribute types (e.g., Color, Size)',
            [
                'type' => 'object',
                'properties' => [
                    'status' => [
                        'type' => 'string',
                        'description' => 'Filter by status',
                        'enum' => ['active', 'inactive', 'all'],
                        'default' => 'active'
                    ]
                ]
            ],
            [$this, 'list_variation_attributes']
        );

        // Create variation attribute
        $this->server->register_tool(
            'create_variation_attribute',
            'Create a new variation attribute type (e.g., Color with Red, Blue, Green options)',
            [
                'type' => 'object',
                'properties' => [
                    'name' => [
                        'type' => 'string',
                        'description' => 'Attribute name (required), e.g., "Color", "Size"'
                    ],
                    'attribute_type' => [
                        'type' => 'string',
                        'description' => 'Attribute input type',
                        'enum' => ['select', 'color', 'image', 'button'],
                        'default' => 'select'
                    ],
                    'options' => [
                        'type' => 'array',
                        'description' => 'Array of option values, e.g., ["Red", "Blue", "Green"]',
                        'items' => ['type' => 'string']
                    ],
                    'display_order' => [
                        'type' => 'integer',
                        'description' => 'Display order',
                        'default' => 0
                    ]
                ],
                'required' => ['name']
            ],
            [$this, 'create_variation_attribute']
        );

        // Update variation attribute
        $this->server->register_tool(
            'update_variation_attribute',
            'Update a variation attribute type',
            [
                'type' => 'object',
                'properties' => [
                    'attribute_id' => [
                        'type' => 'integer',
                        'description' => 'Attribute ID to update (required)',
                        'minimum' => 1
                    ],
                    'name' => [
                        'type' => 'string',
                        'description' => 'New attribute name'
                    ],
                    'options' => [
                        'type' => 'array',
                        'description' => 'Updated option values',
                        'items' => ['type' => 'string']
                    ],
                    'status' => [
                        'type' => 'string',
                        'description' => 'Attribute status',
                        'enum' => ['active', 'inactive']
                    ]
                ],
                'required' => ['attribute_id']
            ],
            [$this, 'update_variation_attribute']
        );

        // Delete variation attribute
        $this->server->register_tool(
            'delete_variation_attribute',
            'Delete a variation attribute type (removes from all products)',
            [
                'type' => 'object',
                'properties' => [
                    'attribute_id' => [
                        'type' => 'integer',
                        'description' => 'Attribute ID to delete (required)',
                        'minimum' => 1
                    ]
                ],
                'required' => ['attribute_id']
            ],
            [$this, 'delete_variation_attribute']
        );

        // Get product variations
        $this->server->register_tool(
            'get_product_variations',
            'Get all variations for a product with their attribute values',
            [
                'type' => 'object',
                'properties' => [
                    'product_id' => [
                        'type' => 'integer',
                        'description' => 'Product ID (required)',
                        'minimum' => 1
                    ],
                    'status' => [
                        'type' => 'string',
                        'description' => 'Filter by status',
                        'enum' => ['active', 'inactive', 'all'],
                        'default' => 'active'
                    ]
                ],
                'required' => ['product_id']
            ],
            [$this, 'get_product_variations']
        );

        // Configure product variation attributes
        $this->server->register_tool(
            'configure_product_variations',
            'Set which variation attributes a product uses (e.g., Color and Size)',
            [
                'type' => 'object',
                'properties' => [
                    'product_id' => [
                        'type' => 'integer',
                        'description' => 'Product ID (required)',
                        'minimum' => 1
                    ],
                    'attribute_ids' => [
                        'type' => 'array',
                        'description' => 'Array of variation attribute IDs to use',
                        'items' => ['type' => 'integer']
                    ],
                    'enable_variations' => [
                        'type' => 'boolean',
                        'description' => 'Enable variations for this product',
                        'default' => true
                    ],
                    'stock_mode' => [
                        'type' => 'string',
                        'description' => 'Stock management mode',
                        'enum' => ['parent', 'variation'],
                        'default' => 'variation'
                    ]
                ],
                'required' => ['product_id', 'attribute_ids']
            ],
            [$this, 'configure_product_variations']
        );

        // Create product variation
        $this->server->register_tool(
            'create_product_variation',
            'Create a single product variation with specific attribute values',
            [
                'type' => 'object',
                'properties' => [
                    'product_id' => [
                        'type' => 'integer',
                        'description' => 'Product ID (required)',
                        'minimum' => 1
                    ],
                    'attributes' => [
                        'type' => 'object',
                        'description' => 'Attribute values as {attribute_id: value}, e.g., {"1": "Red", "2": "Large"}',
                        'additionalProperties' => ['type' => 'string']
                    ],
                    'sku' => [
                        'type' => 'string',
                        'description' => 'Variation SKU'
                    ],
                    'price' => [
                        'type' => 'number',
                        'description' => 'Variation price (overrides parent)',
                        'minimum' => 0
                    ],
                    'sale_price' => [
                        'type' => 'number',
                        'description' => 'Variation sale price',
                        'minimum' => 0
                    ],
                    'stock' => [
                        'type' => 'integer',
                        'description' => 'Stock quantity',
                        'minimum' => 0
                    ],
                    'is_default' => [
                        'type' => 'boolean',
                        'description' => 'Set as default variation',
                        'default' => false
                    ]
                ],
                'required' => ['product_id', 'attributes']
            ],
            [$this, 'create_product_variation']
        );

        // Update product variation
        $this->server->register_tool(
            'update_product_variation',
            'Update an existing product variation',
            [
                'type' => 'object',
                'properties' => [
                    'variation_id' => [
                        'type' => 'integer',
                        'description' => 'Variation ID to update (required)',
                        'minimum' => 1
                    ],
                    'sku' => [
                        'type' => 'string',
                        'description' => 'Variation SKU'
                    ],
                    'price' => [
                        'type' => 'number',
                        'description' => 'Variation price',
                        'minimum' => 0
                    ],
                    'sale_price' => [
                        'type' => 'number',
                        'description' => 'Variation sale price',
                        'minimum' => 0
                    ],
                    'stock' => [
                        'type' => 'integer',
                        'description' => 'Stock quantity',
                        'minimum' => 0
                    ],
                    'stock_status' => [
                        'type' => 'string',
                        'description' => 'Stock status',
                        'enum' => ['instock', 'outofstock', 'onbackorder']
                    ],
                    'is_default' => [
                        'type' => 'boolean',
                        'description' => 'Set as default variation'
                    ],
                    'status' => [
                        'type' => 'string',
                        'description' => 'Variation status',
                        'enum' => ['active', 'inactive']
                    ]
                ],
                'required' => ['variation_id']
            ],
            [$this, 'update_product_variation']
        );

        // Delete product variation
        $this->server->register_tool(
            'delete_product_variation',
            'Delete a product variation',
            [
                'type' => 'object',
                'properties' => [
                    'variation_id' => [
                        'type' => 'integer',
                        'description' => 'Variation ID to delete (required)',
                        'minimum' => 1
                    ]
                ],
                'required' => ['variation_id']
            ],
            [$this, 'delete_product_variation']
        );

        // Generate variations from attributes
        $this->server->register_tool(
            'generate_product_variations',
            'Auto-generate all variations from attribute combinations',
            [
                'type' => 'object',
                'properties' => [
                    'product_id' => [
                        'type' => 'integer',
                        'description' => 'Product ID (required)',
                        'minimum' => 1
                    ],
                    'base_sku' => [
                        'type' => 'string',
                        'description' => 'Base SKU prefix for generated variations'
                    ],
                    'base_price' => [
                        'type' => 'number',
                        'description' => 'Default price for all variations',
                        'minimum' => 0
                    ],
                    'base_stock' => [
                        'type' => 'integer',
                        'description' => 'Default stock for all variations',
                        'minimum' => 0
                    ]
                ],
                'required' => ['product_id']
            ],
            [$this, 'generate_product_variations']
        );

        // Bulk update variation prices
        $this->server->register_tool(
            'bulk_update_variation_prices',
            'Update prices for all variations of a product',
            [
                'type' => 'object',
                'properties' => [
                    'product_id' => [
                        'type' => 'integer',
                        'description' => 'Product ID (required)',
                        'minimum' => 1
                    ],
                    'price_change' => [
                        'type' => 'number',
                        'description' => 'Amount to change price (positive or negative)'
                    ],
                    'change_type' => [
                        'type' => 'string',
                        'description' => 'How to apply the change',
                        'enum' => ['fixed', 'percent'],
                        'default' => 'fixed'
                    ],
                    'apply_to' => [
                        'type' => 'string',
                        'description' => 'Which price field to update',
                        'enum' => ['price', 'sale_price', 'both'],
                        'default' => 'price'
                    ]
                ],
                'required' => ['product_id', 'price_change']
            ],
            [$this, 'bulk_update_variation_prices']
        );
    }

    /**
     * List variation types (formerly variation attributes)
     */
    public function list_variation_attributes($args) {
        $variations = GGM_Commerce_Variations::instance();
        $types = $variations->get_variation_types([
            'status' => $args['status'] ?? 'active'
        ]);

        $result = array_map(function($type) {
            return [
                'id' => (int) $type['id'],
                'name' => $type['name'],
                'slug' => $type['slug'],
                'input_type' => $type['input_type'],
                'options' => $type['options'],
                'display_order' => (int) $type['display_order'],
                'status' => $type['status']
            ];
        }, $types);

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

    /**
     * Create variation type (formerly variation attribute)
     */
    public function create_variation_attribute($args) {
        if (empty($args['name'])) {
            return ['success' => false, 'error' => 'Variation type name is required'];
        }

        $variations = GGM_Commerce_Variations::instance();
        $type_id = $variations->create_variation_type([
            'name' => sanitize_text_field($args['name']),
            'input_type' => sanitize_key($args['input_type'] ?? $args['attribute_type'] ?? 'select'),
            'options' => $args['options'] ?? [],
            'display_order' => intval($args['display_order'] ?? 0),
            'status' => 'active'
        ]);

        if (!$type_id) {
            return ['success' => false, 'error' => 'Failed to create variation type'];
        }

        return [
            'success' => true,
            'type_id' => $type_id,
            'message' => 'Variation type created successfully'
        ];
    }

    /**
     * Update variation type (formerly variation attribute)
     */
    public function update_variation_attribute($args) {
        // Accept both type_id and attribute_id for backwards compatibility
        $type_id = $args['type_id'] ?? $args['attribute_id'] ?? null;
        if (empty($type_id)) {
            return ['success' => false, 'error' => 'Variation type ID is required'];
        }

        $variations = GGM_Commerce_Variations::instance();
        $data = [];

        if (isset($args['name'])) {
            $data['name'] = sanitize_text_field($args['name']);
        }
        if (isset($args['options'])) {
            $data['options'] = $args['options'];
        }
        if (isset($args['status'])) {
            $data['status'] = sanitize_key($args['status']);
        }
        if (isset($args['input_type'])) {
            $data['input_type'] = sanitize_key($args['input_type']);
        }

        $result = $variations->update_variation_type((int) $type_id, $data);

        if (!$result) {
            return ['success' => false, 'error' => 'Failed to update variation type'];
        }

        return [
            'success' => true,
            'message' => 'Variation type updated successfully'
        ];
    }

    /**
     * Delete variation type (formerly variation attribute)
     */
    public function delete_variation_attribute($args) {
        // Accept both type_id and attribute_id for backwards compatibility
        $type_id = $args['type_id'] ?? $args['attribute_id'] ?? null;
        if (empty($type_id)) {
            return ['success' => false, 'error' => 'Variation type ID is required'];
        }

        $variations = GGM_Commerce_Variations::instance();
        $result = $variations->delete_variation_type((int) $type_id);

        if (!$result) {
            return ['success' => false, 'error' => 'Failed to delete variation type'];
        }

        return [
            'success' => true,
            'message' => 'Variation attribute deleted successfully'
        ];
    }

    /**
     * Get product variations
     */
    public function get_product_variations($args) {
        if (empty($args['product_id'])) {
            return ['success' => false, 'error' => 'Product ID is required'];
        }

        $variations = GGM_Commerce_Variations::instance();
        $product_variations = $variations->get_variations((int) $args['product_id'], [
            'status' => $args['status'] ?? 'active'
        ]);

        // Also get the product's variation configuration
        $config = $variations->get_product_variation_config((int) $args['product_id']);

        $result = array_map(function($var) {
            return [
                'id' => (int) $var['id'],
                'product_id' => (int) $var['product_id'],
                'sku' => $var['sku'],
                'price' => $var['price'] !== null ? (float) $var['price'] : null,
                'sale_price' => $var['sale_price'] !== null ? (float) $var['sale_price'] : null,
                'stock' => $var['stock'] !== null ? (int) $var['stock'] : null,
                'stock_status' => $var['stock_status'],
                'is_default' => (bool) $var['is_default'],
                'status' => $var['status'],
                'attributes' => array_map(function($attr) {
                    return [
                        'type_id' => (int) $attr['variation_type_id'],
                        'type_name' => $attr['type_name'] ?? $attr['attribute_name'] ?? '',
                        'value' => $attr['option_value'] ?? $attr['attribute_value'] ?? ''
                    ];
                }, $var['attributes'] ?? [])
            ];
        }, $product_variations);

        return [
            'success' => true,
            'product_id' => (int) $args['product_id'],
            'configured_types' => array_map(function($c) {
                return [
                    'type_id' => (int) $c['variation_type_id'],
                    'name' => $c['name'],
                    'slug' => $c['slug'],
                    'options' => $c['options']
                ];
            }, $config),
            'variations' => $result,
            'count' => count($result)
        ];
    }

    /**
     * Configure product variation attributes
     */
    public function configure_product_variations($args) {
        if (empty($args['product_id'])) {
            return ['success' => false, 'error' => 'Product ID is required'];
        }

        $variations = GGM_Commerce_Variations::instance();
        $product_id = (int) $args['product_id'];
        $attribute_ids = array_map('intval', $args['attribute_ids'] ?? []);

        // Set variation configuration
        $variations->set_product_variation_config($product_id, $attribute_ids);

        // Enable/disable variations
        $enable = $args['enable_variations'] ?? true;
        $stock_mode = $args['stock_mode'] ?? 'variation';
        $variations->set_product_has_variations($product_id, $enable, $stock_mode);

        return [
            'success' => true,
            'product_id' => $product_id,
            'configured_attributes' => count($attribute_ids),
            'variations_enabled' => $enable,
            'stock_mode' => $stock_mode,
            'message' => 'Product variation configuration updated'
        ];
    }

    /**
     * Create product variation
     */
    public function create_product_variation($args) {
        if (empty($args['product_id'])) {
            return ['success' => false, 'error' => 'Product ID is required'];
        }

        if (empty($args['attributes'])) {
            return ['success' => false, 'error' => 'Attributes are required'];
        }

        $variations = GGM_Commerce_Variations::instance();

        // Convert attributes object to proper format
        $attributes = [];
        foreach ($args['attributes'] as $attr_id => $value) {
            $attributes[(int) $attr_id] = sanitize_text_field($value);
        }

        $variation_id = $variations->create_variation((int) $args['product_id'], [
            'attributes' => $attributes,
            'sku' => sanitize_text_field($args['sku'] ?? ''),
            'price' => isset($args['price']) ? (float) $args['price'] : null,
            'sale_price' => isset($args['sale_price']) ? (float) $args['sale_price'] : null,
            'stock' => isset($args['stock']) ? (int) $args['stock'] : null,
            'is_default' => !empty($args['is_default'])
        ]);

        if (!$variation_id) {
            return ['success' => false, 'error' => 'Failed to create variation'];
        }

        return [
            'success' => true,
            'variation_id' => $variation_id,
            'message' => 'Variation created successfully'
        ];
    }

    /**
     * Update product variation
     */
    public function update_product_variation($args) {
        if (empty($args['variation_id'])) {
            return ['success' => false, 'error' => 'Variation ID is required'];
        }

        $variations = GGM_Commerce_Variations::instance();
        $data = [];

        if (isset($args['sku'])) {
            $data['sku'] = sanitize_text_field($args['sku']);
        }
        if (array_key_exists('price', $args)) {
            $data['price'] = $args['price'] !== null ? (float) $args['price'] : null;
        }
        if (array_key_exists('sale_price', $args)) {
            $data['sale_price'] = $args['sale_price'] !== null ? (float) $args['sale_price'] : null;
        }
        if (array_key_exists('stock', $args)) {
            $data['stock'] = $args['stock'] !== null ? (int) $args['stock'] : null;
        }
        if (isset($args['stock_status'])) {
            $data['stock_status'] = sanitize_key($args['stock_status']);
        }
        if (isset($args['is_default'])) {
            $data['is_default'] = (bool) $args['is_default'];
        }
        if (isset($args['status'])) {
            $data['status'] = sanitize_key($args['status']);
        }

        $result = $variations->update_variation((int) $args['variation_id'], $data);

        if (!$result) {
            return ['success' => false, 'error' => 'Failed to update variation'];
        }

        return [
            'success' => true,
            'message' => 'Variation updated successfully'
        ];
    }

    /**
     * Delete product variation
     */
    public function delete_product_variation($args) {
        if (empty($args['variation_id'])) {
            return ['success' => false, 'error' => 'Variation ID is required'];
        }

        $variations = GGM_Commerce_Variations::instance();
        $result = $variations->delete_variation((int) $args['variation_id']);

        if (!$result) {
            return ['success' => false, 'error' => 'Failed to delete variation'];
        }

        return [
            'success' => true,
            'message' => 'Variation deleted successfully'
        ];
    }

    /**
     * Generate all variations from attribute combinations
     */
    public function generate_product_variations($args) {
        if (empty($args['product_id'])) {
            return ['success' => false, 'error' => 'Product ID is required'];
        }

        $variations = GGM_Commerce_Variations::instance();
        $product_id = (int) $args['product_id'];

        // Get configured attributes for this product
        $config = $variations->get_product_variation_config($product_id);

        if (empty($config)) {
            return ['success' => false, 'error' => 'No variation attributes configured for this product'];
        }

        // Build all combinations
        $all_options = [];
        foreach ($config as $attr) {
            if (!empty($attr['options'])) {
                $all_options[$attr['variation_type_id']] = [
                    'name' => $attr['name'],
                    'values' => $attr['options']
                ];
            }
        }

        if (empty($all_options)) {
            return ['success' => false, 'error' => 'No attribute options available to generate variations'];
        }

        // Generate combinations
        $combinations = $this->generate_combinations($all_options);

        // Get existing variations to avoid duplicates
        $existing = $variations->get_variations($product_id, ['status' => 'all']);
        $existing_combos = [];
        foreach ($existing as $var) {
            $combo_key = [];
            foreach ($var['attributes'] as $attr) {
                $combo_key[$attr['variation_type_id']] = $attr['option_value'];
            }
            ksort($combo_key);
            $existing_combos[] = wp_json_encode($combo_key);
        }

        $created = 0;
        $skipped = 0;
        $base_sku = $args['base_sku'] ?? '';
        $base_price = isset($args['base_price']) ? (float) $args['base_price'] : null;
        $base_stock = isset($args['base_stock']) ? (int) $args['base_stock'] : null;

        foreach ($combinations as $combo) {
            // Check if this combination already exists
            $combo_sorted = $combo;
            ksort($combo_sorted);
            if (in_array(wp_json_encode($combo_sorted), $existing_combos, true)) {
                $skipped++;
                continue;
            }

            // Generate SKU from attribute values
            $sku_parts = [$base_sku];
            foreach ($combo as $value) {
                $sku_parts[] = strtoupper(substr(preg_replace('/[^a-zA-Z0-9]/', '', $value), 0, 3));
            }
            $sku = implode('-', array_filter($sku_parts));

            $variation_id = $variations->create_variation($product_id, [
                'attributes' => $combo,
                'sku' => $sku,
                'price' => $base_price,
                'stock' => $base_stock
            ]);

            if ($variation_id) {
                $created++;
            }
        }

        return [
            'success' => true,
            'product_id' => $product_id,
            'total_combinations' => count($combinations),
            'created' => $created,
            'skipped_existing' => $skipped,
            'message' => "Generated {$created} variation(s), skipped {$skipped} existing"
        ];
    }

    /**
     * Generate all combinations of attribute options
     */
    private function generate_combinations($attributes) {
        $result = [[]];

        foreach ($attributes as $attr_id => $attr_data) {
            $new_result = [];
            foreach ($result as $combination) {
                foreach ($attr_data['values'] as $value) {
                    $new_combo = $combination;
                    $new_combo[$attr_id] = $value;
                    $new_result[] = $new_combo;
                }
            }
            $result = $new_result;
        }

        return $result;
    }

    /**
     * Bulk update variation prices
     */
    public function bulk_update_variation_prices($args) {
        if (empty($args['product_id'])) {
            return ['success' => false, 'error' => 'Product ID is required'];
        }

        if (!isset($args['price_change'])) {
            return ['success' => false, 'error' => 'Price change amount is required'];
        }

        $variations = GGM_Commerce_Variations::instance();
        $product_id = (int) $args['product_id'];
        $price_change = (float) $args['price_change'];
        $change_type = $args['change_type'] ?? 'fixed';
        $apply_to = $args['apply_to'] ?? 'price';

        // Get all variations
        $product_variations = $variations->get_variations($product_id, ['status' => 'all']);

        if (empty($product_variations)) {
            return ['success' => false, 'error' => 'No variations found for this product'];
        }

        $updated = 0;

        foreach ($product_variations as $var) {
            $data = [];

            // Update regular price
            if (in_array($apply_to, ['price', 'both'], true) && $var['price'] !== null) {
                $current_price = (float) $var['price'];
                if ($change_type === 'percent') {
                    $new_price = $current_price * (1 + ($price_change / 100));
                } else {
                    $new_price = $current_price + $price_change;
                }
                $data['price'] = max(0, round($new_price, 2));
            }

            // Update sale price
            if (in_array($apply_to, ['sale_price', 'both'], true) && $var['sale_price'] !== null) {
                $current_sale = (float) $var['sale_price'];
                if ($change_type === 'percent') {
                    $new_sale = $current_sale * (1 + ($price_change / 100));
                } else {
                    $new_sale = $current_sale + $price_change;
                }
                $data['sale_price'] = max(0, round($new_sale, 2));
            }

            if (!empty($data)) {
                $result = $variations->update_variation((int) $var['id'], $data);
                if ($result) {
                    $updated++;
                }
            }
        }

        return [
            'success' => true,
            'product_id' => $product_id,
            'variations_updated' => $updated,
            'change_applied' => $price_change,
            'change_type' => $change_type,
            'applied_to' => $apply_to,
            'message' => "Updated prices for {$updated} variation(s)"
        ];
    }
}
