<?php
/**
 * ZERTI component templates and AJAX fragment loader.
 */

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

/**
 * Filesystem path to a tab component template (PHP partial).
 */
function zerti_component_template_path(string $slug): string
{
    $default = plugin_dir_path(ZERTI_PLUGIN_FILE) . 'includes/components/' . $slug . '.php';

    return (string) apply_filters('zerti_component_template_path', $default, $slug);
}

/**
 * Plugin roots allowed for filtered component templates (e.g. zerti-pro).
 *
 * @return list<string>
 */
function zerti_component_template_allowed_roots(): array
{
    $roots = [plugin_dir_path(ZERTI_PLUGIN_FILE)];

    if (defined('ZERTI_PRO_PATH')) {
        $roots[] = ZERTI_PRO_PATH;
    }

    return (array) apply_filters('zerti_component_template_allowed_roots', $roots);
}

/**
 * Whether a resolved template path is under an allowed plugin root.
 */
function zerti_component_template_path_is_allowed(string $path): bool
{
    $real_path = realpath($path);
    if ($real_path === false || !is_readable($real_path)) {
        return false;
    }

    $normalized_path = str_replace('\\', '/', $real_path);
    foreach (zerti_component_template_allowed_roots() as $root) {
        $real_root = realpath($root);
        if ($real_root === false) {
            continue;
        }

        $normalized_root = rtrim(str_replace('\\', '/', $real_root), '/');
        if ($normalized_path === $normalized_root || strpos($normalized_path, $normalized_root . '/') === 0) {
            return true;
        }
    }

    return false;
}

/**
 * Resolve a component template path (free includes/components/ or filter, e.g. zerti-pro).
 */
function zerti_resolve_component_template_path(string $slug): string
{
    $components_dir = plugin_dir_path(ZERTI_PLUGIN_FILE) . 'includes/components/';
    $fallback = $components_dir . $slug . '.php';
    $path = zerti_component_template_path($slug);

    if (zerti_component_template_path_is_allowed($path)) {
        $real_path = realpath($path);

        return $real_path !== false ? $real_path : $path;
    }

    if (zerti_component_template_path_is_allowed($fallback)) {
        $real_fallback = realpath($fallback);

        return $real_fallback !== false ? $real_fallback : $fallback;
    }

    return $path;
}

/**
 * Echo inner HTML for one tab (used by SSR and AJAX).
 */
function zerti_render_component_inner(string $slug): void
{
    if (!zerti_is_valid_component_slug($slug)) {
        return;
    }

    $path = zerti_resolve_component_template_path($slug);
    if (is_readable($path)) {
        include $path;
    }
}

/**
 * One panel body slot: SSR for the active tab only; other tabs load via AJAX on first open.
 */
function zerti_render_component_slot(string $slug, string $current_tab): void
{
    $loaded = $slug === $current_tab;
    ?>
    <div class="zerti-panel-slot<?php echo $loaded ? '' : ' zerti-panel-slot--pending'; ?>"
         data-zerti-slot="<?php echo esc_attr($slug); ?>"
         data-zerti-loaded="<?php echo $loaded ? '1' : '0'; ?>"
         data-zerti-fetching="0"
         data-zerti-fetch-gen="">
        <?php if ($loaded) : ?>
            <?php zerti_render_component_inner($slug); ?>
        <?php endif; ?>
    </div>
    <?php
}

/**
 * @param array<string, mixed> $source
 * @return array{
 *     slug:string,
 *     partial:bool,
 *     inventory_product_id:int,
 *     has_inventory_product_id:bool,
 *     customer_id:int,
 *     shop_order_id:int,
 *     shop_order_create:bool,
 *     has_shop_order_id:bool,
 *     shop_order_view:string
 * }
 */
function zerti_ajax_load_component_input_from_array(array $source): array
{
    $slug = isset($source['slug']) ? sanitize_key(wp_unslash((string) $source['slug'])) : '';
    $partial = !empty($source['partial']);
    $inventory_product_id = isset($source['inventory_product_id'])
        ? absint(wp_unslash((string) $source['inventory_product_id']))
        : 0;
    $customer_id = isset($source['customer_id']) ? absint(wp_unslash((string) $source['customer_id'])) : 0;
    $shop_order_id = isset($source['shop_order_id']) ? absint(wp_unslash((string) $source['shop_order_id'])) : 0;
    $shop_order_create = !empty($source['shop_order_create']);
    $shop_order_view = isset($source['shop_order_view'])
        ? sanitize_key(wp_unslash((string) $source['shop_order_view']))
        : 'detail';

    return [
        'slug' => $slug,
        'partial' => $partial,
        'inventory_product_id' => $inventory_product_id,
        'has_inventory_product_id' => array_key_exists('inventory_product_id', $source),
        'customer_id' => $customer_id,
        'shop_order_id' => $shop_order_id,
        'shop_order_create' => $shop_order_create,
        'has_shop_order_id' => isset($source['shop_order_id']),
        'shop_order_view' => $shop_order_view,
    ];
}

/**
 * @return array{
 *     slug:string,
 *     partial:bool,
 *     inventory_product_id:int,
 *     has_inventory_product_id:bool,
 *     customer_id:int,
 *     shop_order_id:int,
 *     shop_order_create:bool,
 *     has_shop_order_id:bool,
 *     shop_order_view:string
 * }
 */
/**
 * AJAX: return HTML fragment for one component.
 */
function zerti_ajax_load_component(): void
{
    check_ajax_referer('zerti_component', 'nonce');

    if (!zerti_user_can_access_admin()) {
        wp_send_json_error(['message' => 'forbidden'], 403);
    }

    $post = zerti_unslash_post_array();
    // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Nonce verified above; fields sanitized in zerti_ajax_load_component_input_from_array().
    $input = zerti_ajax_load_component_input_from_array($post);
    $slug = $input['slug'];
    if (!zerti_is_valid_component_slug($slug)) {
        wp_send_json_error(['message' => 'invalid'], 400);
    }

    if (!zerti_user_can_access_tab($slug)) {
        wp_send_json_error(['message' => 'forbidden'], 403);
    }

    $partial = $input['partial'];
    if ($slug === 'inventory' && $partial) {
        ob_start();
        if ($input['has_inventory_product_id'] && function_exists('zerti_render_inventory_product_edit')) {
            zerti_render_inventory_product_edit($input['inventory_product_id']);
        } else {
            zerti_render_inventory_sub_component(null);
        }
        $html = ob_get_clean();
        wp_send_json_success(['html' => $html]);

        return;
    }

    if ($slug === 'financial' && $partial) {
        ob_start();
        zerti_render_financial_sub_component(null);
        $html = ob_get_clean();
        wp_send_json_success(['html' => $html]);

        return;
    }

    if ($slug === 'customers' && $partial) {
        $cust_uid = $input['customer_id'];
        if ($cust_uid < 1) {
            wp_send_json_error(['message' => 'invalid'], 400);
        }
        ob_start();
        zerti_render_customer_detail($cust_uid);
        $html = ob_get_clean();
        wp_send_json_success(['html' => $html]);

        return;
    }

    if ($slug === 'shop' && $partial) {
        $shop_oid = $input['shop_order_id'];
        $shop_create = $input['shop_order_create'] || $shop_oid === 0 && $input['has_shop_order_id'];
        if ($shop_create && function_exists('zerti_render_shop_order_create')) {
            ob_start();
            zerti_render_shop_order_create();
            $html = ob_get_clean();
            wp_send_json_success(['html' => $html]);

            return;
        }
        if ($shop_oid < 1) {
            wp_send_json_error(['message' => 'invalid'], 400);
        }
        $shop_view = $input['shop_order_view'];
        if ($shop_view === 'invoice' && function_exists('wc_get_order')) {
            $order_for_view = wc_get_order($shop_oid);
            if (
                !is_a($order_for_view, 'WC_Order')
                || !(function_exists('zerti_shop_order_can_open_invoice')
                    ? zerti_shop_order_can_open_invoice($order_for_view)
                    : in_array($order_for_view->get_status(), ['completed', 'processing', 'pending'], true))
            ) {
                $shop_view = 'detail';
            }
        }
        ob_start();
        if ($shop_view === 'invoice') {
            zerti_render_shop_order_invoice($shop_oid);
        } else {
            zerti_render_shop_order_detail($shop_oid);
        }
        $html = ob_get_clean();
        wp_send_json_success(['html' => $html]);

        return;
    }

    ob_start();
    zerti_render_component_inner($slug);
    $html = ob_get_clean();

    wp_send_json_success(['html' => $html]);
}

