<?php

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

class AIEO_Exchanger_Rest {

    public static function register() {
        add_action('rest_api_init', array(__CLASS__, 'register_routes'));
    }

    public static function register_routes() {
        register_rest_route('aieo/v1', '/exchanger/(?P<slug>[a-z0-9_-]+)/manifest', array(
            'methods'             => 'GET',
            'callback'            => array(__CLASS__, 'serve_manifest'),
            'permission_callback' => '__return_true', 
            'args'                => array('slug' => array('type' => 'string', 'required' => true)),
        ));

        register_rest_route('aieo/v1', '/exchanger/(?P<slug>[a-z0-9_-]+)/shards/(?P<n>\d+)', array(
            'methods'             => 'GET',
            'callback'            => array(__CLASS__, 'serve_shard'),
            'permission_callback' => '__return_true',
            'args'                => array(
                'slug' => array('type' => 'string', 'required' => true),
                'n'    => array('type' => 'integer', 'required' => true),
            ),
        ));

        register_rest_route('aieo/v1', '/exchanger/sync', array(
            'methods'             => 'POST',
            'callback'            => array(__CLASS__, 'receive_sync'),
            'permission_callback' => '__return_true',
        ));
    }

    
    private static function authenticate_feed(WP_REST_Request $request, $slug) {
        $feed = AIEO_Exchanger_Feeds::get_by_slug((string) $slug);
        if (!$feed || empty($feed['enabled'])) {
            return new WP_REST_Response(array('error' => 'feed_not_found'), 404);
        }
        $token = '';
        $auth_header = (string) $request->get_header('authorization');
        if ($auth_header !== '' && stripos($auth_header, 'bearer ') === 0) {
            $token = trim(substr($auth_header, 7));
        }
        if ($token === '' || !hash_equals((string) $feed['feed_token'], $token)) {
            return new WP_REST_Response(array('error' => 'unauthorized'), 401);
        }
        return $feed;
    }

    public static function serve_manifest(WP_REST_Request $request) {
        $slug = sanitize_key((string) $request->get_param('slug'));
        $auth = self::authenticate_feed($request, $slug);
        if ($auth instanceof WP_REST_Response) { return $auth; }
        $feed = $auth;

        $path = AIEO_Exchanger_Feeds::storage_path($feed) . '/manifest.json';
        if (!file_exists($path)) {
            return new WP_REST_Response(array('error' => 'manifest_missing', 'hint' => 'Build the feed first.'), 404);
        }
        $body = file_get_contents($path);
        $resp = new WP_REST_Response(json_decode($body, true), 200);
        $resp->header('Cache-Control', 'no-store');
        return $resp;
    }

    public static function serve_shard(WP_REST_Request $request) {
        $slug = sanitize_key((string) $request->get_param('slug'));
        $n    = max(1, (int) $request->get_param('n'));
        $auth = self::authenticate_feed($request, $slug);
        if ($auth instanceof WP_REST_Response) { return $auth; }
        $feed = $auth;

        $path = AIEO_Exchanger_Feeds::storage_path($feed) . '/shards/shard-' . $n . '.json';
        if (!file_exists($path)) {
            return new WP_REST_Response(array('error' => 'shard_missing', 'shard' => $n), 404);
        }
        $body = file_get_contents($path);
        $resp = new WP_REST_Response(json_decode($body, true), 200);
        $resp->header('Cache-Control', 'no-store');
        return $resp;
    }

    
    public static function receive_sync(WP_REST_Request $request) {
        $body = $request->get_json_params();
        if (!is_array($body)) { $body = array(); }
        $slug         = sanitize_key((string) ($body['import_slug']  ?? ''));
        $manifest_url = (string) ($body['manifest_url'] ?? '');
        $ts           = (int)    ($body['ts']           ?? 0);
        $sig          = (string) ($body['sig']          ?? '');

        if ($slug === '' || $manifest_url === '' || $ts <= 0 || $sig === '') {
            return new WP_REST_Response(array('error' => 'bad_payload'), 400);
        }
        if (abs(time() - $ts) > 600) {
            return new WP_REST_Response(array('error' => 'stale_timestamp'), 401);
        }

        $job = AIEO_Exchanger_Imports::get_by_slug($slug);
        if (!$job) { return new WP_REST_Response(array('error' => 'job_not_found'), 404); }

        $expected = hash_hmac('sha256', $manifest_url . '|' . $ts, (string) $job['feed_token']);
        if (!hash_equals($expected, $sig)) {
            return new WP_REST_Response(array('error' => 'bad_signature'), 401);
        }

        
        
        
        wp_schedule_single_event(time() + 30, 'aieo_exchanger_run_import_now', array((int) $job['id']));
        return new WP_REST_Response(array('ok' => true, 'queued' => true), 202);
    }

    
    public static function notify_targets(array $feed) {
        $targets = (array) ($feed['push_targets'] ?? array());
        if (empty($targets)) { return array('notified' => 0, 'errors' => 0); }
        $manifest_url = AIEO_Exchanger_Feeds::manifest_url($feed);
        $notified = 0;
        $errors = 0;
        foreach ($targets as $t) {
            if (!is_array($t) || empty($t['url']) || empty($t['secret'])) { continue; }
            $ts = time();
            $sig = hash_hmac('sha256', $manifest_url . '|' . $ts, (string) $t['secret']);
            $r = wp_remote_post(rtrim((string) $t['url'], '/'), array(
                'timeout' => 15,
                'headers' => array('Content-Type' => 'application/json'),
                'body'    => wp_json_encode(array(
                    'import_slug'  => sanitize_key((string) ($t['import_slug'] ?? $feed['slug'])),
                    'manifest_url' => $manifest_url,
                    'ts'           => $ts,
                    'sig'          => $sig,
                )),
            ));
            if (is_wp_error($r)) { $errors++; continue; }
            $code = (int) wp_remote_retrieve_response_code($r);
            if ($code >= 200 && $code < 300) { $notified++; } else { $errors++; }
        }
        return array('notified' => $notified, 'errors' => $errors);
    }
}
