<?php
/**
 * AJAX — WooCommerce product categories (inventory › categories).
 */

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

/**
 * Verify nonce and capability for category management.
 */
function zerti_ajax_product_categories_guard(): void
{
    check_ajax_referer('zerti_product_categories', 'nonce');

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

    if (!zerti_product_categories_available()) {
        wp_send_json_error(['message' => 'taxonomy_missing'], 400);
    }
}

/**
 * @param array<string, mixed> $source
 * @return array{search:string}
 */
function zerti_ajax_product_categories_list_input_from_array(array $source): array
{
    $search = isset($source['search']) ? sanitize_text_field(wp_unslash((string) $source['search'])) : '';

    return [
        'search' => $search,
    ];
}

/**
 * @return array{search:string}
 */
/**
 * @param array<string, mixed> $source
 * @return array{id:int}
 */
function zerti_ajax_product_category_delete_input_from_array(array $source): array
{
    $id = isset($source['id']) ? absint(wp_unslash((string) $source['id'])) : 0;

    return [
        'id' => $id,
    ];
}

/**
 * @return array{id:int}
 */
/**
 * @param array<string, mixed> $source
 * @return list<array{id:int,order:int,parent:?int}>
 */
function zerti_ajax_product_categories_reorder_input_from_array(array $source): array
{
    $raw = isset($source['reorder']) ? wp_unslash($source['reorder']) : '';
    if (is_array($raw)) {
        $decoded = $raw;
    } else {
        $decoded = json_decode((string) $raw, true);
    }

    if (!is_array($decoded)) {
        return [];
    }

    $rows = [];
    foreach ($decoded as $row) {
        if (!is_array($row)) {
            continue;
        }
        $rows[] = [
            'id' => isset($row['id']) ? absint($row['id']) : 0,
            'order' => isset($row['order']) ? (int) $row['order'] : 0,
            'parent' => isset($row['parent']) ? absint($row['parent']) : null,
        ];
    }

    return $rows;
}

/**
 * @return list<array{id:int,order:int,parent:?int}>
 */
/**
 * List categories (flat + tree).
 */
function zerti_ajax_product_categories_list(): void
{
    zerti_ajax_product_categories_guard();

    $post = zerti_unslash_post_array();
    // phpcs:ignore WordPress.Security.NonceVerification.Missing -- verified in zerti_ajax_product_categories_guard().
    $input = zerti_ajax_product_categories_list_input_from_array($post);
    $search = $input['search'];
    $flat = zerti_product_categories_flat_list();

    if ($search !== '') {
        $needle = mb_strtolower($search, 'UTF-8');
        $match_ids = [];
        foreach ($flat as $row) {
            $name = mb_strtolower((string) ($row['name'] ?? ''), 'UTF-8');
            $slug = mb_strtolower((string) ($row['slug'] ?? ''), 'UTF-8');
            if (zerti_str_contains($name, $needle) || zerti_str_contains($slug, $needle)) {
                $match_ids[(int) $row['id']] = true;
            }
        }
        if ($match_ids !== []) {
            $by_id = [];
            foreach ($flat as $row) {
                $by_id[(int) $row['id']] = $row;
            }
            $keep = $match_ids;
            foreach (array_keys($match_ids) as $mid) {
                $parent = (int) ($by_id[$mid]['parent'] ?? 0);
                while ($parent > 0 && !isset($keep[$parent])) {
                    $keep[$parent] = true;
                    $parent = (int) ($by_id[$parent]['parent'] ?? 0);
                }
            }
            $flat = array_values(array_filter(
                $flat,
                static function (array $row) use ($keep): bool {
                    return isset($keep[(int) ($row['id'] ?? 0)]);
                }
            ));
        } else {
            $flat = [];
        }
    }

    wp_send_json_success([
        'flat' => $flat,
        'tree' => zerti_product_categories_build_tree($flat),
        'parent_options' => zerti_product_category_parent_options(),
        'display_types' => zerti_product_category_display_type_choices(),
        'total' => count($flat),
    ]);
}

/**
 * Create or update one category.
 */
function zerti_ajax_product_category_save(): void
{
    zerti_ajax_product_categories_guard();

    $post = zerti_unslash_post_array();
    // phpcs:ignore WordPress.Security.NonceVerification.Missing -- verified in zerti_ajax_product_categories_guard().
    $payload = zerti_product_category_payload_from_array($post);
    $result = zerti_product_category_save($payload);

    if (empty($result['ok'])) {
        $code = isset($result['code']) ? (string) $result['code'] : 'save_failed';
        $msg = zerti_product_category_error_message(
            $code,
            isset($result['message']) ? (string) $result['message'] : ''
        );
        wp_send_json_error(['message' => $msg, 'code' => $code], 400);
    }

    wp_send_json_success([
        'item' => $result['item'] ?? null,
        'flat' => zerti_product_categories_flat_list(),
        'tree' => zerti_product_categories_build_tree(zerti_product_categories_flat_list()),
        'parent_options' => zerti_product_category_parent_options((int) ($result['item']['id'] ?? 0)),
    ]);
}

/**
 * Delete one category.
 */
function zerti_ajax_product_category_delete(): void
{
    zerti_ajax_product_categories_guard();

    $post = zerti_unslash_post_array();
    // phpcs:ignore WordPress.Security.NonceVerification.Missing -- verified in zerti_ajax_product_categories_guard().
    $input = zerti_ajax_product_category_delete_input_from_array($post);
    $id = $input['id'];
    $result = zerti_product_category_delete($id);

    if (empty($result['ok'])) {
        $code = isset($result['code']) ? (string) $result['code'] : 'delete_failed';
        $msg = zerti_product_category_error_message(
            $code,
            isset($result['message']) ? (string) $result['message'] : ''
        );
        wp_send_json_error(['message' => $msg, 'code' => $code], 400);
    }

    wp_send_json_success([
        'flat' => zerti_product_categories_flat_list(),
        'tree' => zerti_product_categories_build_tree(zerti_product_categories_flat_list()),
        'parent_options' => zerti_product_category_parent_options(),
    ]);
}

/**
 * Bulk reorder (JSON array in POST reorder).
 */
function zerti_ajax_product_categories_reorder(): void
{
    zerti_ajax_product_categories_guard();

    $post = zerti_unslash_post_array();
    // phpcs:ignore WordPress.Security.NonceVerification.Missing -- verified in zerti_ajax_product_categories_guard().
    $rows = zerti_ajax_product_categories_reorder_input_from_array($post);
    if ($rows === []) {
        wp_send_json_error(['message' => 'invalid'], 400);
    }

    $result = zerti_product_categories_apply_reorder($rows);
    if (empty($result['ok'])) {
        wp_send_json_error(['message' => $result['message'] ?? 'reorder_failed'], 400);
    }

    wp_send_json_success([
        'flat' => zerti_product_categories_flat_list(),
        'tree' => zerti_product_categories_build_tree(zerti_product_categories_flat_list()),
    ]);
}

