<?php

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

class AIEO_MOI_REST_API {

    private static $instance = null;
    public static function instance() {
        if (self::$instance === null) { self::$instance = new self(); }
        return self::$instance;
    }

    private function __construct() {
        add_action('rest_api_init', array($this, 'register_routes'));
    }

    public function register_routes() {
        register_rest_route('moi/v1', '/webhook/(?P<vendor>[a-z0-9_-]+)', array(
            'methods'             => 'POST',
            'callback'            => array($this, 'handle_webhook'),
            
            'permission_callback' => '__return_true',
            'args' => array(
                'vendor' => array('type' => 'string', 'required' => true),
                'token'  => array('type' => 'string', 'required' => true),
            ),
        ));

        register_rest_route('moi/v1', '/orders/(?P<id>\d+)/(?P<action>accept|reject|voucher)', array(
            'methods'             => 'POST',
            'callback'            => array($this, 'handle_admin_action'),
            'permission_callback' => function () {
                return current_user_can('manage_woocommerce');
            },
            'args' => array(
                'id'     => array('type' => 'integer', 'required' => true),
                'action' => array('type' => 'string',  'required' => true),
            ),
        ));
    }

    
    public function handle_webhook(WP_REST_Request $request) {
        $vendor_slug = sanitize_key((string) $request->get_param('vendor'));
        $token       = (string) $request->get_param('token');

        $vendor = AIEO_MOI_Vendor_Manager::get_by_webhook_token($token);
        if (!$vendor || $vendor['slug'] !== $vendor_slug) {
            AIEO_MOI_Inbound_Log::record(array(
                'event_type' => 'webhook',
                'status'     => 'rejected_auth',
                'error_text' => 'Invalid token or vendor slug mismatch.',
            ));
            return new WP_REST_Response(array('error' => 'unauthorized'), 401);
        }

        $provider = AIEO_MOI_Provider_Registry::get((string) $vendor['provider']);
        if (!$provider) {
            AIEO_MOI_Inbound_Log::record(array(
                'vendor_id'  => (int) $vendor['id'],
                'event_type' => 'webhook',
                'status'     => 'failed',
                'error_text' => 'Provider not registered: ' . $vendor['provider'],
            ));
            return new WP_REST_Response(array('error' => 'provider_missing'), 500);
        }

        
        $verify = $provider->verify_webhook($request, $vendor);
        if (is_wp_error($verify) || $verify === false) {
            $msg = is_wp_error($verify) ? $verify->get_error_message() : 'Provider verify_webhook returned false';
            AIEO_MOI_Inbound_Log::record(array(
                'vendor_id'  => (int) $vendor['id'],
                'event_type' => 'webhook',
                'status'     => 'rejected_signature',
                'error_text' => $msg,
            ));
            return new WP_REST_Response(array('error' => 'verify_failed'), 401);
        }

        $body = $request->get_json_params();
        if (!is_array($body)) { $body = array(); }

        
        
        $raw_body     = $request->get_body();
        $payload_hash = hash('sha256', (string) $raw_body);
        if (AIEO_MOI_Inbound_Log::payload_already_processed($payload_hash)) {
            return new WP_REST_Response(array('ok' => true, 'duplicate' => true), 200);
        }

        
        $canonical = $provider->parse_webhook_payload($body);
        if (!is_array($canonical) || empty($canonical['remote_order_id'])) {
            AIEO_MOI_Inbound_Log::record(array(
                'vendor_id'    => (int) $vendor['id'],
                'event_type'   => 'webhook',
                'payload_hash' => $payload_hash,
                'status'       => 'parse_failed',
                'error_text'   => 'parse_webhook_payload returned malformed shape.',
            ));
            return new WP_REST_Response(array('error' => 'parse_failed'), 400);
        }

        $event = (string) ($canonical['event_type'] ?? 'order_updated');

        
        
        
        $result = AIEO_MOI_Order_Mapper::upsert_from_canonical($vendor, $canonical, 'webhook');
        if (isset($result['error'])) {
            $err = $result['error'];
            AIEO_MOI_Inbound_Log::record(array(
                'vendor_id'       => (int) $vendor['id'],
                'event_type'      => $event,
                'remote_order_id' => (string) $canonical['remote_order_id'],
                'payload_hash'    => $payload_hash,
                'status'          => 'failed',
                'error_text'      => is_wp_error($err) ? $err->get_error_message() : (string) $err,
            ));
            return new WP_REST_Response(array('error' => 'mapper_failed'), 500);
        }

        AIEO_MOI_Inbound_Log::record(array(
            'vendor_id'       => (int) $vendor['id'],
            'event_type'      => $event,
            'remote_order_id' => (string) $canonical['remote_order_id'],
            'payload_hash'    => $payload_hash,
            'status'          => 'processed',
            'wc_order_id'     => (int) $result['wc_order_id'],
        ));

        return new WP_REST_Response(array(
            'ok'          => true,
            'created'     => !empty($result['created']),
            'wc_order_id' => (int) $result['wc_order_id'],
        ), 200);
    }

    
    public function handle_admin_action(WP_REST_Request $request) {
        $wc_order_id = (int) $request->get_param('id');
        $action      = sanitize_key((string) $request->get_param('action'));

        $order = wc_get_order($wc_order_id);
        if (!$order) {
            return new WP_REST_Response(array('error' => 'order_not_found'), 404);
        }
        $vendor_id = (int) $order->get_meta('_aieo_moi_vendor_id');
        $remote_id = (string) $order->get_meta('_aieo_moi_remote_order_id');
        if ($vendor_id <= 0 || $remote_id === '') {
            return new WP_REST_Response(array('error' => 'not_a_marketplace_order'), 400);
        }
        $vendor = AIEO_MOI_Vendor_Manager::get($vendor_id);
        if (!$vendor) {
            return new WP_REST_Response(array('error' => 'vendor_missing'), 400);
        }
        $provider = AIEO_MOI_Provider_Registry::get((string) $vendor['provider']);
        if (!$provider) {
            return new WP_REST_Response(array('error' => 'provider_missing'), 500);
        }

        $params = $request->get_json_params();
        if (!is_array($params)) { $params = array(); }

        switch ($action) {
            case 'accept':
                
                
                
                
                
                
                
                
                
                
                if (empty($params['pickup_location']) || empty($params['pickup_window'])) {
                    $ao_raw = (string) $order->get_meta('_aieo_moi_accept_options');
                    if ($ao_raw !== '') {
                        $ao = json_decode($ao_raw, true);
                        if (is_array($ao)) {
                            if (empty($params['pickup_location']) && isset($ao['pickup_location'][0]['id'])) {
                                $params['pickup_location'] = (string) $ao['pickup_location'][0]['id'];
                            }
                            if (empty($params['pickup_window']) && isset($ao['pickup_window'][0]['id'])) {
                                $params['pickup_window'] = $ao['pickup_window'][0]['id'];
                            }
                        }
                    }
                    if (empty($params['number_of_parcels'])) {
                        $params['number_of_parcels'] = 1;
                    }
                }
                $result = $provider->accept_order($vendor, $remote_id, $params);
                if (!empty($result['ok'])) {
                    if (!empty($result['voucher_url'])) {
                        $order->update_meta_data('_aieo_moi_voucher_url', (string) $result['voucher_url']);
                    }
                    $order->update_meta_data('_aieo_moi_state', 'accepted');
                    $order->save();
                    AIEO_MOI_Inbound_Log::record(array(
                        'vendor_id'       => $vendor_id,
                        'event_type'      => 'admin_accept',
                        'remote_order_id' => $remote_id,
                        'status'          => 'accepted',
                        'wc_order_id'     => $wc_order_id,
                    ));
                }
                return new WP_REST_Response($result, !empty($result['ok']) ? 200 : 400);

            case 'reject':
                $reason = isset($params['reason']) ? sanitize_text_field((string) $params['reason']) : '';
                $result = $provider->reject_order($vendor, $remote_id, $reason);
                if (!empty($result['ok'])) {
                    $order->update_meta_data('_aieo_moi_state', 'rejected');
                    $order->update_status('cancelled', sprintf(
                        
                        __('Rejected on %s.', 'marketplace-order-importer'),
                        $vendor['label']
                    ));
                    AIEO_MOI_Inbound_Log::record(array(
                        'vendor_id'       => $vendor_id,
                        'event_type'      => 'admin_reject',
                        'remote_order_id' => $remote_id,
                        'status'          => 'rejected',
                        'wc_order_id'     => $wc_order_id,
                    ));
                }
                return new WP_REST_Response($result, !empty($result['ok']) ? 200 : 400);

            case 'voucher':
                $url = (string) $provider->fetch_voucher($vendor, $remote_id);
                if ($url !== '') {
                    $order->update_meta_data('_aieo_moi_voucher_url', $url);
                    $order->save();
                }
                return new WP_REST_Response(array('ok' => $url !== '', 'voucher_url' => $url), 200);
        }

        return new WP_REST_Response(array('error' => 'unknown_action'), 400);
    }
}
