<?php
namespace EncypherProvenance;

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

/**
 * Serves the .well-known HTTP file challenge used by the Encypher API to
 * verify host control during the connect flow.
 *
 * The plugin stores a challenge token in the plugin settings and serves it at
 *   /.well-known/encypher-provenance/<token>
 * The Encypher API fetches that URL; a 200 response whose body contains the
 * token proves the organization controls this EXACT host. Proving one host
 * never grants another host (no eTLD+1 collapse) — the API enforces exact-host
 * matching; this class only serves the token for the host it runs on.
 */
class WellKnown
{
    const PATH_PREFIX = '/.well-known/encypher-provenance/';
    const SETTINGS_KEY = 'well_known_token';

    public function register_hooks(): void
    {
        // Early on init so the token file is served before WP routes to a 404.
        add_action('init', [$this, 'maybe_serve_challenge'], 1);
        add_action('rest_api_init', [$this, 'register_routes']);
    }

    /**
     * Detect a request for the well-known challenge path and serve the token.
     *
     * Mirrors how Plugin::handle_c2pa_verify_page() parses REQUEST_URI directly
     * so the route works regardless of permalink configuration.
     */
    public function maybe_serve_challenge(): void
    {
        $request_uri = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field(wp_unslash($_SERVER['REQUEST_URI'])) : '';
        if ('' === $request_uri) {
            return;
        }

        $path = (string) wp_parse_url($request_uri, PHP_URL_PATH);
        $prefix = self::PATH_PREFIX;
        if (strncmp($path, $prefix, strlen($prefix)) !== 0) {
            return;
        }

        $requested = rawurldecode(substr($path, strlen($prefix)));
        $requested = trim($requested, '/');
        if ('' === $requested) {
            return;
        }

        $token = $this->get_stored_token();
        if ('' === $token || ! hash_equals($token, $requested)) {
            status_header(404);
            nocache_headers();
            header('Content-Type: text/plain; charset=utf-8');
            echo 'not found';
            exit;
        }

        status_header(200);
        nocache_headers();
        header('Content-Type: text/plain; charset=utf-8');
        // Body is the token itself; the API matches on substring presence.
        echo esc_html($token);
        exit;
    }

    public function register_routes(): void
    {
        register_rest_route('encypher-provenance/v1', '/well-known/challenge', [
            [
                'methods' => \WP_REST_Server::READABLE,
                'permission_callback' => function () {
                    return current_user_can('manage_options');
                },
                'callback' => [$this, 'handle_report'],
            ],
            [
                'methods' => \WP_REST_Server::CREATABLE,
                'permission_callback' => function () {
                    return current_user_can('manage_options');
                },
                'callback' => [$this, 'handle_set'],
                'args' => [
                    'token' => [
                        'type' => 'string',
                        'required' => true,
                    ],
                ],
            ],
        ]);
    }

    /**
     * Report the current challenge token state, the served path and the exact
     * host/URL the Encypher API will fetch.
     */
    public function handle_report(\WP_REST_Request $request)
    {
        $token = $this->get_stored_token();
        $site_url = home_url('/');
        $host = (string) wp_parse_url($site_url, PHP_URL_HOST);

        return new \WP_REST_Response([
            'host' => $host,
            'has_token' => ('' !== $token),
            'path' => '' !== $token ? self::PATH_PREFIX . $token : null,
            'challenge_url' => '' !== $token ? 'https://' . $host . self::PATH_PREFIX . $token : null,
        ]);
    }

    /**
     * Store a challenge token issued by the Encypher API so the plugin can
     * serve it for host-control verification.
     */
    public function handle_set(\WP_REST_Request $request)
    {
        $token = trim(sanitize_text_field((string) $request->get_param('token')));
        if ('' === $token || ! preg_match('/^[A-Za-z0-9_\-]+$/', $token)) {
            return new \WP_Error('invalid_token', __('Invalid challenge token.', 'encypher-provenance'), ['status' => 400]);
        }

        $settings = get_option('encypher_provenance_settings', []);
        if (! is_array($settings)) {
            $settings = [];
        }
        $settings[self::SETTINGS_KEY] = $token;
        update_option('encypher_provenance_settings', $settings);

        $site_url = home_url('/');
        $host = (string) wp_parse_url($site_url, PHP_URL_HOST);

        return new \WP_REST_Response([
            'success' => true,
            'host' => $host,
            'challenge_url' => 'https://' . $host . self::PATH_PREFIX . $token,
        ]);
    }

    private function get_stored_token(): string
    {
        $settings = get_option('encypher_provenance_settings', []);
        if (! is_array($settings)) {
            return '';
        }

        return isset($settings[self::SETTINGS_KEY]) ? trim((string) $settings[self::SETTINGS_KEY]) : '';
    }
}
