<?php
/**
 * GGM Commerce Shipment Tools
 *
 * MCP Tools for shipment and fulfillment management
 * 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_Shipment_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 shipment tools
     */
    private function register_tools() {
        // List carriers
        $this->server->register_tool(
            'list_carriers',
            'List available shipping carriers',
            [
                'type' => 'object',
                'properties' => []
            ],
            [$this, 'list_carriers']
        );

        // List shipment statuses
        $this->server->register_tool(
            'list_shipment_statuses',
            'List available shipment statuses',
            [
                'type' => 'object',
                'properties' => []
            ],
            [$this, 'list_shipment_statuses']
        );

        // Create shipment
        $this->server->register_tool(
            'create_shipment',
            'Create a new shipment for an order',
            [
                'type' => 'object',
                'properties' => [
                    'order_id' => [
                        'type' => 'integer',
                        'description' => 'Order ID (required)',
                        'minimum' => 1
                    ],
                    'carrier' => [
                        'type' => 'string',
                        'description' => 'Carrier slug (royal_mail, dpd, dhl, ups, fedex, evri, yodel, parcelforce, usps, other)',
                        'default' => 'other'
                    ],
                    'carrier_service' => [
                        'type' => 'string',
                        'description' => 'Carrier service name (e.g., "Standard", "Express")'
                    ],
                    'tracking_number' => [
                        'type' => 'string',
                        'description' => 'Tracking number'
                    ],
                    'tracking_url' => [
                        'type' => 'string',
                        'description' => 'Tracking URL'
                    ],
                    'weight' => [
                        'type' => 'number',
                        'description' => 'Package weight',
                        'minimum' => 0
                    ],
                    'weight_unit' => [
                        'type' => 'string',
                        'description' => 'Weight unit',
                        'enum' => ['kg', 'g', 'lb', 'oz'],
                        'default' => 'kg'
                    ],
                    'shipping_cost' => [
                        'type' => 'number',
                        'description' => 'Shipping cost',
                        'minimum' => 0
                    ]
                ],
                'required' => ['order_id']
            ],
            [$this, 'create_shipment']
        );

        // Get shipment
        $this->server->register_tool(
            'get_shipment',
            'Get shipment details by ID',
            [
                'type' => 'object',
                'properties' => [
                    'shipment_id' => [
                        'type' => 'integer',
                        'description' => 'Shipment ID (required)',
                        'minimum' => 1
                    ]
                ],
                'required' => ['shipment_id']
            ],
            [$this, 'get_shipment']
        );

        // Get order shipments
        $this->server->register_tool(
            'get_order_shipments',
            'Get all shipments for an order',
            [
                'type' => 'object',
                'properties' => [
                    'order_id' => [
                        'type' => 'integer',
                        'description' => 'Order ID (required)',
                        'minimum' => 1
                    ]
                ],
                'required' => ['order_id']
            ],
            [$this, 'get_order_shipments']
        );

        // Update shipment tracking
        $this->server->register_tool(
            'update_shipment_tracking',
            'Update tracking information for a shipment',
            [
                'type' => 'object',
                'properties' => [
                    'shipment_id' => [
                        'type' => 'integer',
                        'description' => 'Shipment ID (required)',
                        'minimum' => 1
                    ],
                    'tracking_number' => [
                        'type' => 'string',
                        'description' => 'Tracking number'
                    ],
                    'tracking_url' => [
                        'type' => 'string',
                        'description' => 'Tracking URL'
                    ],
                    'carrier' => [
                        'type' => 'string',
                        'description' => 'Carrier slug'
                    ],
                    'carrier_service' => [
                        'type' => 'string',
                        'description' => 'Carrier service'
                    ]
                ],
                'required' => ['shipment_id']
            ],
            [$this, 'update_shipment_tracking']
        );

        // Update shipment status
        $this->server->register_tool(
            'update_shipment_status',
            'Update the status of a shipment',
            [
                'type' => 'object',
                'properties' => [
                    'shipment_id' => [
                        'type' => 'integer',
                        'description' => 'Shipment ID (required)',
                        'minimum' => 1
                    ],
                    'status' => [
                        'type' => 'string',
                        'description' => 'New status (required)',
                        'enum' => ['pending', 'label_created', 'shipped', 'in_transit', 'out_for_delivery', 'delivered', 'failed', 'returned', 'cancelled']
                    ]
                ],
                'required' => ['shipment_id', 'status']
            ],
            [$this, 'update_shipment_status']
        );

        // Mark shipped
        $this->server->register_tool(
            'mark_shipment_shipped',
            'Mark a shipment as shipped (in transit)',
            [
                'type' => 'object',
                'properties' => [
                    'shipment_id' => [
                        'type' => 'integer',
                        'description' => 'Shipment ID (required)',
                        'minimum' => 1
                    ],
                    'tracking_number' => [
                        'type' => 'string',
                        'description' => 'Tracking number (optional if already set)'
                    ],
                    'tracking_url' => [
                        'type' => 'string',
                        'description' => 'Tracking URL (optional)'
                    ]
                ],
                'required' => ['shipment_id']
            ],
            [$this, 'mark_shipment_shipped']
        );

        // Mark delivered
        $this->server->register_tool(
            'mark_shipment_delivered',
            'Mark a shipment as delivered',
            [
                'type' => 'object',
                'properties' => [
                    'shipment_id' => [
                        'type' => 'integer',
                        'description' => 'Shipment ID (required)',
                        'minimum' => 1
                    ]
                ],
                'required' => ['shipment_id']
            ],
            [$this, 'mark_shipment_delivered']
        );

        // List pending shipments
        $this->server->register_tool(
            'list_pending_shipments',
            'List orders awaiting shipment',
            [
                'type' => 'object',
                'properties' => [
                    'status' => [
                        'type' => 'string',
                        'description' => 'Filter by shipment status',
                        'enum' => ['pending', 'label_created', 'all_unshipped'],
                        'default' => 'all_unshipped'
                    ],
                    'limit' => [
                        'type' => 'integer',
                        'description' => 'Maximum results',
                        'minimum' => 1,
                        'maximum' => 100,
                        'default' => 50
                    ]
                ]
            ],
            [$this, 'list_pending_shipments']
        );

        // Delete shipment
        $this->server->register_tool(
            'delete_shipment',
            'Delete a shipment',
            [
                'type' => 'object',
                'properties' => [
                    'shipment_id' => [
                        'type' => 'integer',
                        'description' => 'Shipment ID (required)',
                        'minimum' => 1
                    ]
                ],
                'required' => ['shipment_id']
            ],
            [$this, 'delete_shipment']
        );
    }

    /**
     * List available carriers
     */
    public function list_carriers($args) {
        $carriers = GGM_Commerce_Shipments::get_carriers();

        $result = [];
        foreach ($carriers as $slug => $name) {
            $result[] = [
                'slug' => $slug,
                'name' => $name
            ];
        }

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

    /**
     * List shipment statuses
     */
    public function list_shipment_statuses($args) {
        $statuses = GGM_Commerce_Shipments::get_statuses();

        $result = [];
        foreach ($statuses as $slug => $label) {
            $result[] = [
                'slug' => $slug,
                'label' => $label
            ];
        }

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

    /**
     * Create shipment
     */
    public function create_shipment($args) {
        if (empty($args['order_id'])) {
            return ['success' => false, 'error' => 'Order ID is required'];
        }

        // Verify order exists
        global $wpdb;
        $order = $wpdb->get_row($wpdb->prepare(
            "SELECT id, order_number, status FROM {$wpdb->prefix}ggmc_orders WHERE id = %d",
            (int) $args['order_id']
        ));

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

        $shipment_data = [
            'carrier' => sanitize_key($args['carrier'] ?? 'other'),
            'carrier_service' => sanitize_text_field($args['carrier_service'] ?? ''),
            'tracking_number' => sanitize_text_field($args['tracking_number'] ?? ''),
            'tracking_url' => esc_url_raw($args['tracking_url'] ?? ''),
            'weight' => isset($args['weight']) ? (float) $args['weight'] : null,
            'weight_unit' => sanitize_key($args['weight_unit'] ?? 'kg'),
            'shipping_cost' => isset($args['shipping_cost']) ? (float) $args['shipping_cost'] : 0.00
        ];

        $shipment_id = GGM_Commerce_Shipments::create_shipment((int) $args['order_id'], $shipment_data);

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

        $shipment = GGM_Commerce_Shipments::get_shipment($shipment_id);

        return [
            'success' => true,
            'shipment_id' => $shipment_id,
            'shipment_number' => $shipment->shipment_number,
            'order_id' => (int) $args['order_id'],
            'order_number' => $order->order_number,
            'message' => 'Shipment created successfully'
        ];
    }

    /**
     * Get shipment details
     */
    public function get_shipment($args) {
        if (empty($args['shipment_id'])) {
            return ['success' => false, 'error' => 'Shipment ID is required'];
        }

        $shipment = GGM_Commerce_Shipments::get_shipment((int) $args['shipment_id']);

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

        return [
            'success' => true,
            'shipment' => [
                'id' => (int) $shipment->id,
                'order_id' => (int) $shipment->order_id,
                'shipment_number' => $shipment->shipment_number,
                'carrier' => $shipment->carrier,
                'carrier_name' => GGM_Commerce_Shipments::get_carrier_name($shipment->carrier),
                'carrier_service' => $shipment->carrier_service,
                'tracking_number' => $shipment->tracking_number,
                'tracking_url' => $shipment->tracking_url,
                'status' => $shipment->status,
                'status_label' => GGM_Commerce_Shipments::get_status_label($shipment->status),
                'weight' => $shipment->weight ? (float) $shipment->weight : null,
                'weight_unit' => $shipment->weight_unit,
                'shipping_cost' => (float) $shipment->shipping_cost,
                'shipped_at' => $shipment->shipped_at,
                'estimated_delivery' => $shipment->estimated_delivery,
                'delivered_at' => $shipment->delivered_at,
                'created_at' => $shipment->created_at
            ]
        ];
    }

    /**
     * Get order shipments
     */
    public function get_order_shipments($args) {
        if (empty($args['order_id'])) {
            return ['success' => false, 'error' => 'Order ID is required'];
        }

        $shipments = GGM_Commerce_Shipments::get_order_shipments((int) $args['order_id']);

        $result = array_map(function($s) {
            return [
                'id' => (int) $s->id,
                'shipment_number' => $s->shipment_number,
                'carrier' => $s->carrier,
                'carrier_name' => GGM_Commerce_Shipments::get_carrier_name($s->carrier),
                'carrier_service' => $s->carrier_service,
                'tracking_number' => $s->tracking_number,
                'tracking_url' => $s->tracking_url,
                'status' => $s->status,
                'status_label' => GGM_Commerce_Shipments::get_status_label($s->status),
                'shipped_at' => $s->shipped_at,
                'delivered_at' => $s->delivered_at,
                'created_at' => $s->created_at
            ];
        }, $shipments);

        return [
            'success' => true,
            'order_id' => (int) $args['order_id'],
            'shipments' => $result,
            'count' => count($result)
        ];
    }

    /**
     * Update shipment tracking
     */
    public function update_shipment_tracking($args) {
        if (empty($args['shipment_id'])) {
            return ['success' => false, 'error' => 'Shipment ID is required'];
        }

        $data = [];

        if (isset($args['tracking_number'])) {
            $data['tracking_number'] = sanitize_text_field($args['tracking_number']);
        }
        if (isset($args['tracking_url'])) {
            $data['tracking_url'] = esc_url_raw($args['tracking_url']);
        }
        if (isset($args['carrier'])) {
            $data['carrier'] = sanitize_key($args['carrier']);
        }
        if (isset($args['carrier_service'])) {
            $data['carrier_service'] = sanitize_text_field($args['carrier_service']);
        }

        if (empty($data)) {
            return ['success' => false, 'error' => 'No tracking data provided'];
        }

        $result = GGM_Commerce_Shipments::update_shipment((int) $args['shipment_id'], $data);

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

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

    /**
     * Update shipment status
     */
    public function update_shipment_status($args) {
        if (empty($args['shipment_id']) || empty($args['status'])) {
            return ['success' => false, 'error' => 'Shipment ID and status are required'];
        }

        $valid_statuses = array_keys(GGM_Commerce_Shipments::get_statuses());
        if (!in_array($args['status'], $valid_statuses, true)) {
            return ['success' => false, 'error' => 'Invalid status'];
        }

        $result = GGM_Commerce_Shipments::update_shipment((int) $args['shipment_id'], [
            'status' => $args['status']
        ]);

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

        return [
            'success' => true,
            'new_status' => $args['status'],
            'status_label' => GGM_Commerce_Shipments::get_status_label($args['status']),
            'message' => 'Shipment status updated successfully'
        ];
    }

    /**
     * Mark shipment as shipped
     */
    public function mark_shipment_shipped($args) {
        if (empty($args['shipment_id'])) {
            return ['success' => false, 'error' => 'Shipment ID is required'];
        }

        $tracking_number = sanitize_text_field($args['tracking_number'] ?? '');
        $tracking_url = esc_url_raw($args['tracking_url'] ?? '');

        $result = GGM_Commerce_Shipments::mark_shipped(
            (int) $args['shipment_id'],
            $tracking_number,
            $tracking_url
        );

        if (!$result) {
            return ['success' => false, 'error' => 'Failed to mark shipment as shipped'];
        }

        return [
            'success' => true,
            'message' => 'Shipment marked as shipped'
        ];
    }

    /**
     * Mark shipment as delivered
     */
    public function mark_shipment_delivered($args) {
        if (empty($args['shipment_id'])) {
            return ['success' => false, 'error' => 'Shipment ID is required'];
        }

        $result = GGM_Commerce_Shipments::mark_delivered((int) $args['shipment_id']);

        if (!$result) {
            return ['success' => false, 'error' => 'Failed to mark shipment as delivered'];
        }

        return [
            'success' => true,
            'message' => 'Shipment marked as delivered'
        ];
    }

    /**
     * List pending/unshipped orders
     */
    public function list_pending_shipments($args) {
        global $wpdb;

        $limit = min(100, max(1, intval($args['limit'] ?? 50)));
        $status_filter = $args['status'] ?? 'all_unshipped';

        // Get orders that need shipping
        // Orders with status 'processing' or 'completed' that don't have any shipped shipments
        $sql = "
            SELECT o.id, o.order_number, o.customer_name, o.customer_email,
                   o.shipping_address_line_1, o.shipping_city, o.shipping_postcode, o.shipping_country,
                   o.total_amount, o.status, o.created_at,
                   s.id as shipment_id, s.shipment_number, s.status as shipment_status
            FROM {$wpdb->prefix}ggmc_orders o
            LEFT JOIN {$wpdb->prefix}ggmc_shipments s ON o.id = s.order_id
            WHERE o.status IN ('processing', 'completed')
        ";

        if ($status_filter === 'pending') {
            $sql .= " AND (s.status = 'pending' OR s.id IS NULL)";
        } elseif ($status_filter === 'label_created') {
            $sql .= " AND s.status = 'label_created'";
        } else {
            // all_unshipped - no shipment OR shipment not yet shipped
            $sql .= " AND (s.id IS NULL OR s.status IN ('pending', 'label_created'))";
        }

        $sql .= " ORDER BY o.created_at ASC LIMIT {$limit}";

        $results = $wpdb->get_results($sql);

        $orders = [];
        foreach ($results as $r) {
            $orders[] = [
                'order_id' => (int) $r->id,
                'order_number' => $r->order_number,
                'customer_name' => $r->customer_name,
                'customer_email' => $r->customer_email,
                'shipping_address' => trim(implode(', ', array_filter([
                    $r->shipping_address_line_1,
                    $r->shipping_city,
                    $r->shipping_postcode,
                    $r->shipping_country
                ]))),
                'total_amount' => (float) $r->total_amount,
                'order_status' => $r->status,
                'order_date' => $r->created_at,
                'shipment_id' => $r->shipment_id ? (int) $r->shipment_id : null,
                'shipment_number' => $r->shipment_number,
                'shipment_status' => $r->shipment_status
            ];
        }

        return [
            'success' => true,
            'filter' => $status_filter,
            'orders' => $orders,
            'count' => count($orders)
        ];
    }

    /**
     * Delete shipment
     */
    public function delete_shipment($args) {
        if (empty($args['shipment_id'])) {
            return ['success' => false, 'error' => 'Shipment ID is required'];
        }

        $result = GGM_Commerce_Shipments::delete_shipment((int) $args['shipment_id']);

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

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