<?php
/**
 * includes/admin/import-isrc-mapping.php
 *
 * ============================================================================
 * MAPEAMENTOS MANUAIS DE ISRC — overrides persistentes
 * ============================================================================
 *
 * Quando um CSV de royalties traz um ISRC que não bate com nenhuma faixa na
 * BD (ex: distribuidora reescreve ISRCs, ou faixa foi registada com ISRC
 * diferente), o admin pode mapear manualmente esse ISRC do CSV para uma
 * faixa existente.
 *
 * Este mapeamento é PERSISTENTE — fica guardado e aplicado AUTOMATICAMENTE
 * em todos os imports futuros que tragam o mesmo ISRC do CSV.
 *
 * Tabela: wp_rmbz_distro_isrc_overrides
 *
 * AJAX endpoints expostos (admin only):
 *   - rmbz_search_tracks_for_mapping  → pesquisa faixas por título/artista
 *   - rmbz_save_isrc_mapping          → guarda override
 *   - rmbz_delete_isrc_mapping        → remove override
 *
 * INTEGRAÇÃO COM IMPORT PROCESSOR:
 * O `rmbz_match_track()` (em admin-distribution-controller.php ou similar)
 * deve verificar overrides antes de tentar match normal. Adicionamos um
 * filtro `rmbz_isrc_override_lookup` que devolve a faixa se houver override.
 */

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


/* ============================================================================
 * 1. SCHEMA — tabela de aliases (ISRC + UPC)
 * ============================================================================
 *
 * [DS 1.5.96] Esta tabela passou a ser MULTI-TIPO. Antes era só ISRC, agora
 * suporta também UPC. Mantemos o nome `rmbz_distro_isrc_overrides` por
 * compatibilidade (já tem dados) mas conceptualmente é "aliases de faixas".
 *
 * Estrutura nova:
 *   csv_value   → o ISRC ou UPC vindo do CSV (ex: "TCAHB2328707")
 *   alias_type  → 'isrc' | 'upc'
 *   track_id    → faixa interna a que está vinculado
 *   deleted_at  → soft delete (preserva auditoria)
 *   deleted_by  → quem apagou (auditoria)
 *
 * Migração automática:
 *   - Coluna antiga `csv_isrc` mantém-se (dados antigos lá)
 *   - Coluna nova `csv_value` é populada via script de migração no install
 *   - alias_type fica 'isrc' para todos os registos antigos
 *   - UNIQUE KEY antigo `uk_csv_isrc` torna-se obsoleto, criamos novo
 *     `uk_value_type` (csv_value + alias_type) para permitir um ISRC e um UPC
 *     com o mesmo valor (raro mas possível)
 */

function rmbz_track_aliases_install() {
    global $wpdb;
    $table = $wpdb->prefix . 'rmbz_distro_isrc_overrides';
    $charset = $wpdb->get_charset_collate();

    if ( ! function_exists('dbDelta') ) {
        require_once ABSPATH . 'wp-admin/includes/upgrade.php';
    }

    // Criar/actualizar com schema novo. dbDelta é idempotente — se a tabela
    // já existir, só adiciona colunas em falta. Os dados antigos (csv_isrc)
    // são preservados.
    dbDelta("CREATE TABLE $table (
        id bigint(20) NOT NULL AUTO_INCREMENT,
        csv_isrc varchar(50) DEFAULT NULL,
        csv_value varchar(50) NOT NULL DEFAULT '',
        alias_type varchar(10) NOT NULL DEFAULT 'isrc',
        track_id bigint(20) NOT NULL,
        notes text,
        created_at datetime DEFAULT CURRENT_TIMESTAMP,
        created_by varchar(60) DEFAULT NULL,
        deleted_at datetime DEFAULT NULL,
        deleted_by varchar(60) DEFAULT NULL,
        delete_reason text,
        PRIMARY KEY  (id),
        UNIQUE KEY uk_value_type (csv_value, alias_type),
        KEY idx_track (track_id),
        KEY idx_deleted (deleted_at)
    ) $charset;");

    // [DS 1.5.96] Migração — preencher csv_value a partir de csv_isrc para
    // registos antigos onde csv_value está vazio. Idempotente, defensiva.
    $cols = (array) $wpdb->get_col("SHOW COLUMNS FROM $table");
    if ( in_array('csv_isrc', $cols, true) && in_array('csv_value', $cols, true) ) {
        $wpdb->query(
            "UPDATE $table
             SET csv_value = csv_isrc,
                 alias_type = 'isrc'
             WHERE csv_value = '' AND csv_isrc IS NOT NULL AND csv_isrc != ''"
        );
    }
}

// [DS 1.5.96] Manter alias antigo para compatibilidade — algum código pode
// ainda chamar a função pelo nome antigo.
function rmbz_isrc_overrides_install() {
    rmbz_track_aliases_install();
}

add_filter( 'rmbz_schema_expected_tables_extra', function( $extras ) {
    $extras['rmbz_distro_isrc_overrides'] = [
        'description' => 'Aliases de faixas (ISRC e UPC alternativos para matching)',
        'installer'   => 'rmbz_track_aliases_install',
        'critical'    => false,
    ];
    return $extras;
});

// [DS 1.5.91] Install corre em `admin_init` em vez de `plugins_loaded` (que era
// muito cedo — WP ainda não tem ABSPATH/wp-admin totalmente carregado, e
// chamar dbDelta cedo de mais causa warnings "Deprecated: passing null"
// no WordPress core). admin_init garante que tudo está pronto.
add_action( 'admin_init', 'rmbz_track_aliases_install', 20 );


/* ============================================================================
 * 2. AJAX — pesquisar faixas por título/artista
 * ============================================================================ */

function rmbz_ajax_search_tracks_for_mapping() {
    if ( ! current_user_can('manage_options') ) wp_send_json_error(['msg' => 'Sem permissão.'], 403);
    check_ajax_referer( 'rmbz_search_tracks', '_nonce' );

    global $wpdb;
    $q = sanitize_text_field( $_POST['q'] ?? '' );
    if ( strlen($q) < 2 ) wp_send_json_success(['tracks' => []]);

    $like = '%' . $wpdb->esc_like($q) . '%';

    // Pesquisa em tracks: título, ISRC. Inner join releases para ter artista.
    $rows = $wpdb->get_results( $wpdb->prepare(
        "SELECT t.id, t.track_title AS title, t.isrc_code, r.artist_telemovel,
                w.user_nome AS artist_name
         FROM {$wpdb->prefix}rmbz_distro_tracks t
         JOIN {$wpdb->prefix}rmbz_distro_releases r ON r.id = t.release_id
         LEFT JOIN {$wpdb->prefix}rmbz_wallets w ON w.user_telemovel = r.artist_telemovel
         WHERE t.track_title LIKE %s OR t.isrc_code LIKE %s OR w.user_nome LIKE %s
         LIMIT 20",
        $like, $like, $like
    ) );

    wp_send_json_success([
        'tracks' => array_map(function($r) {
            return [
                'id'                => (int) $r->id,
                'title'             => $r->title,
                'isrc_code'         => $r->isrc_code,
                'artist_telemovel'  => $r->artist_telemovel,
                'artist_name'       => $r->artist_name,
            ];
        }, $rows ?: [])
    ]);
}
add_action('wp_ajax_rmbz_search_tracks_for_mapping', 'rmbz_ajax_search_tracks_for_mapping');


/* ============================================================================
 * 3. AJAX — guardar mapeamento
 * ============================================================================ */

function rmbz_ajax_save_isrc_mapping() {
    if ( ! current_user_can('manage_options') ) wp_send_json_error(['msg' => 'Sem permissão.'], 403);
    check_ajax_referer( 'rmbz_map_isrc', '_nonce' );

    global $wpdb;
    // [DS 1.5.96] Suporta agora ISRC ou UPC. POST aceita:
    //   - csv_isrc + alias_type (preferido), OU
    //   - csv_isrc sozinho (compat antigo, assume tipo 'isrc')
    $csv_value  = sanitize_text_field( $_POST['csv_isrc'] ?? '' ); // mantém nome para compat
    $alias_type = sanitize_key( $_POST['alias_type'] ?? 'isrc' );
    $track_id   = (int) ($_POST['track_id'] ?? 0);

    if ( ! in_array( $alias_type, ['isrc', 'upc'], true ) ) $alias_type = 'isrc';

    if ( empty($csv_value) || $track_id <= 0 ) {
        wp_send_json_error(['msg' => 'Dados inválidos.'], 400);
    }

    // Verificar que a faixa existe
    $exists = $wpdb->get_var( $wpdb->prepare(
        "SELECT id FROM {$wpdb->prefix}rmbz_distro_tracks WHERE id = %d",
        $track_id
    ) );
    if ( ! $exists ) wp_send_json_error(['msg' => 'Faixa não encontrada.'], 404);

    // [DS 1.5.96] UPSERT manual em vez de REPLACE INTO porque agora
    // queremos PRESERVAR auditoria (created_at, created_by) se o registo
    // já existir e estiver soft-deleted — apenas reactivamos.
    $table = $wpdb->prefix . 'rmbz_distro_isrc_overrides';
    $current_user = wp_get_current_user();
    $created_by   = $current_user ? $current_user->user_login : 'admin';
    $now          = current_time('mysql');

    $existing = $wpdb->get_row( $wpdb->prepare(
        "SELECT id, deleted_at FROM {$table}
         WHERE csv_value = %s AND alias_type = %s
         LIMIT 1",
        $csv_value, $alias_type
    ) );

    if ( $existing ) {
        // Já existe — actualiza track_id e (se estava deleted) reactiva
        $update_data = [
            'track_id'      => $track_id,
            'deleted_at'    => null,
            'deleted_by'    => null,
            'delete_reason' => null,
        ];
        $wpdb->update( $table, $update_data, [ 'id' => $existing->id ] );
    } else {
        $wpdb->insert( $table, [
            'csv_value'  => $csv_value,
            'csv_isrc'   => ($alias_type === 'isrc') ? $csv_value : null, // compat retro
            'alias_type' => $alias_type,
            'track_id'   => $track_id,
            'created_at' => $now,
            'created_by' => $created_by,
        ], [ '%s','%s','%s','%d','%s','%s' ] );
    }

    wp_send_json_success(['mapped' => true, 'alias_type' => $alias_type]);
}
add_action('wp_ajax_rmbz_save_isrc_mapping', 'rmbz_ajax_save_isrc_mapping');


/* ============================================================================
 * 3B. AJAX — listar aliases de uma faixa (para a UI da página de faixas)
 * ============================================================================ */
function rmbz_ajax_list_track_aliases() {
    if ( ! current_user_can('manage_options') ) wp_send_json_error(['msg' => 'Sem permissão.'], 403);
    check_ajax_referer( 'rmbz_list_aliases', '_nonce' );

    $track_id = (int) ($_POST['track_id'] ?? 0);
    if ( $track_id <= 0 ) wp_send_json_error(['msg' => 'Track ID inválido.'], 400);

    $aliases = function_exists('rmbz_get_track_aliases') ? rmbz_get_track_aliases( $track_id ) : [];

    // Formatar para o JS — adicionar created_at_human
    $out = array_map(function($a) {
        return [
            'id'              => (int) $a->id,
            'csv_value'       => $a->csv_value ?: $a->csv_isrc, // fallback registos antigos
            'alias_type'      => $a->alias_type ?: 'isrc',
            'created_at'      => $a->created_at,
            'created_at_human'=> date_i18n('d/m/Y H:i', strtotime($a->created_at)),
            'created_by'      => $a->created_by,
        ];
    }, $aliases);

    wp_send_json_success(['aliases' => $out]);
}
add_action('wp_ajax_rmbz_list_track_aliases', 'rmbz_ajax_list_track_aliases');


/* ============================================================================
 * 3C. AJAX — apagar alias com auditoria
 * ============================================================================ */
function rmbz_ajax_delete_track_alias() {
    if ( ! current_user_can('manage_options') ) wp_send_json_error(['msg' => 'Sem permissão.'], 403);
    check_ajax_referer( 'rmbz_delete_alias', '_nonce' );

    $alias_id = (int) ($_POST['alias_id'] ?? 0);
    $reason   = sanitize_textarea_field( $_POST['reason'] ?? '' );

    if ( $alias_id <= 0 ) wp_send_json_error(['msg' => 'Alias ID inválido.'], 400);

    $ok = function_exists('rmbz_delete_track_alias') && rmbz_delete_track_alias( $alias_id, $reason );

    if ( $ok ) {
        wp_send_json_success(['deleted' => true]);
    } else {
        wp_send_json_error(['msg' => 'Não foi possível apagar (já estava removido?).'], 500);
    }
}
add_action('wp_ajax_rmbz_delete_track_alias', 'rmbz_ajax_delete_track_alias');


/* ============================================================================
 * 4. LOOKUP — usado pelo importador para verificar aliases ANTES do match normal
 * ============================================================================
 *
 * [DS 1.5.96] Função genérica que procura aliases (ISRC ou UPC) e devolve
 * a faixa associada. Soft-deleted são ignorados.
 *
 * @param string $value  ISRC ou UPC vindo do CSV
 * @param string $type   'isrc' (default) ou 'upc'
 * @return object|null   Linha com track_id, release_id, artist_telemovel ou null
 */
function rmbz_lookup_track_alias( $value, $type = 'isrc' ) {
    global $wpdb;
    $value = trim( strtoupper( str_replace('-', '', (string) $value) ) );
    if ( empty($value) ) return null;
    if ( ! in_array( $type, ['isrc', 'upc'], true ) ) $type = 'isrc';

    // Procura primeiro pelo csv_value (coluna nova). Como fallback, também
    // procura pelo csv_isrc antigo (registos pre-1.5.96 que ainda não foram
    // migrados — não devia acontecer mas é defensivo).
    $row = $wpdb->get_row( $wpdb->prepare(
        "SELECT t.id AS track_id, t.release_id, r.artist_telemovel
         FROM {$wpdb->prefix}rmbz_distro_isrc_overrides o
         JOIN {$wpdb->prefix}rmbz_distro_tracks t ON t.id = o.track_id
         JOIN {$wpdb->prefix}rmbz_distro_releases r ON r.id = t.release_id
         WHERE o.deleted_at IS NULL
           AND o.alias_type = %s
           AND (
               UPPER(REPLACE(o.csv_value, '-', '')) = %s
               OR (o.alias_type = 'isrc' AND UPPER(REPLACE(COALESCE(o.csv_isrc, ''), '-', '')) = %s)
           )
         LIMIT 1",
        $type, $value, $value
    ) );

    return $row;
}

/**
 * Wrapper retro-compatível — código antigo continua a chamar pelo nome
 * antigo. Internamente delega no lookup novo.
 *
 * @deprecated 1.5.96 Use rmbz_lookup_track_alias() em vez disto.
 */
function rmbz_lookup_isrc_override( $csv_isrc ) {
    return rmbz_lookup_track_alias( $csv_isrc, 'isrc' );
}

/**
 * Helper específico para UPC.
 */
function rmbz_lookup_upc_alias( $csv_upc ) {
    return rmbz_lookup_track_alias( $csv_upc, 'upc' );
}


/* ============================================================================
 * 4B. HELPERS PÚBLICOS — para UI futura (página da faixa, etc)
 * ============================================================================ */

/**
 * Devolve todos os aliases activos (não soft-deleted) de uma faixa.
 *
 * @param int $track_id
 * @return array Lista de objectos com: id, csv_value, alias_type, created_at, created_by
 */
function rmbz_get_track_aliases( $track_id ) {
    global $wpdb;
    $track_id = (int) $track_id;
    if ( $track_id <= 0 ) return [];

    return (array) $wpdb->get_results( $wpdb->prepare(
        "SELECT id, csv_value, alias_type, created_at, created_by, notes
         FROM {$wpdb->prefix}rmbz_distro_isrc_overrides
         WHERE track_id = %d AND deleted_at IS NULL
         ORDER BY alias_type ASC, created_at DESC",
        $track_id
    ) );
}

/**
 * Conta aliases activos de uma faixa (ISRC + UPC). Útil para badges
 * tipo "3 alternativos" no admin.
 */
function rmbz_count_track_aliases( $track_id ) {
    global $wpdb;
    $track_id = (int) $track_id;
    if ( $track_id <= 0 ) return 0;

    return (int) $wpdb->get_var( $wpdb->prepare(
        "SELECT COUNT(*) FROM {$wpdb->prefix}rmbz_distro_isrc_overrides
         WHERE track_id = %d AND deleted_at IS NULL",
        $track_id
    ) );
}

/**
 * Soft-delete de um alias com auditoria.
 *
 * @param int    $alias_id
 * @param string $reason   Razão (opcional, para auditoria)
 * @return bool   true se apagou, false se não encontrou
 */
function rmbz_delete_track_alias( $alias_id, $reason = '' ) {
    global $wpdb;
    $alias_id = (int) $alias_id;
    if ( $alias_id <= 0 ) return false;

    $current_user = function_exists('wp_get_current_user') ? wp_get_current_user() : null;
    $deleted_by   = ($current_user && $current_user->user_login) ? $current_user->user_login : 'admin';

    $rows = $wpdb->update(
        $wpdb->prefix . 'rmbz_distro_isrc_overrides',
        [
            'deleted_at'    => current_time('mysql'),
            'deleted_by'    => $deleted_by,
            'delete_reason' => sanitize_textarea_field( $reason ),
        ],
        [ 'id' => $alias_id, 'deleted_at' => null ], // só apaga se ainda activo
        [ '%s', '%s', '%s' ],
        [ '%d', '%s' ]
    );

    return ( $rows !== false && $rows > 0 );
}


/* ============================================================================
 * 5. PÁGINA ADMIN — gerir mapeamentos existentes
 * ============================================================================ */

function rmbz_render_isrc_mappings_page() {
    if ( ! current_user_can('manage_options') ) wp_die('Sem permissão.');
    global $wpdb;
    $table = $wpdb->prefix . 'rmbz_distro_isrc_overrides';

    // Acção: apagar mapeamento
    if ( isset($_GET['delete_id']) && check_admin_referer('rmbz_delete_isrc_map') ) {
        // [DS 1.5.96] Soft-delete em vez de hard-delete (preserva auditoria)
        $reason = isset($_GET['reason']) ? sanitize_text_field($_GET['reason']) : '';
        $ok = function_exists('rmbz_delete_track_alias')
            ? rmbz_delete_track_alias( (int) $_GET['delete_id'], $reason )
            : false;
        if ( $ok ) {
            echo '<div class="notice notice-success is-dismissible"><p>✓ Alias removido. Se precisares, podes recriá-lo a partir do preview de import.</p></div>';
        } else {
            echo '<div class="notice notice-error is-dismissible"><p>Não foi possível remover (já estava removido?).</p></div>';
        }
    }

    // [DS 1.5.96] Mostra activos por padrão; mostra removidos se ?show_deleted=1
    $show_deleted = ! empty($_GET['show_deleted']);
    $where = $show_deleted ? "WHERE o.deleted_at IS NOT NULL" : "WHERE o.deleted_at IS NULL";

    $mappings = $wpdb->get_results(
        "SELECT o.*, t.track_title AS track_title, t.isrc_code AS track_isrc,
                r.artist_telemovel, w.user_nome AS artist_name
         FROM $table o
         LEFT JOIN {$wpdb->prefix}rmbz_distro_tracks t ON t.id = o.track_id
         LEFT JOIN {$wpdb->prefix}rmbz_distro_releases r ON r.id = t.release_id
         LEFT JOIN {$wpdb->prefix}rmbz_wallets w ON w.user_telemovel = r.artist_telemovel
         $where
         ORDER BY o.created_at DESC"
    );

    // Contadores para os filtros
    $count_active  = (int) $wpdb->get_var("SELECT COUNT(*) FROM $table WHERE deleted_at IS NULL");
    $count_deleted = (int) $wpdb->get_var("SELECT COUNT(*) FROM $table WHERE deleted_at IS NOT NULL");
    ?>
    <h2 style="margin-top:20px;">🔗 Aliases de faixas (ISRC + UPC)</h2>
    <p style="color:#666;">
        Quando o CSV de uma distribuidora traz um ISRC (ou UPC) diferente do que está registado na faixa,
        podes mapear manualmente esse identificador para a faixa correcta. Os mapeamentos aplicam-se
        automaticamente em todos os imports futuros.
    </p>

    <p>
        <a href="<?php echo esc_url( remove_query_arg('show_deleted') ); ?>" class="button <?php echo $show_deleted ? '' : 'button-primary'; ?>">
            ✓ Activos (<?php echo $count_active; ?>)
        </a>
        <?php if ( $count_deleted > 0 ): ?>
            <a href="<?php echo esc_url( add_query_arg('show_deleted', '1') ); ?>" class="button <?php echo $show_deleted ? 'button-primary' : ''; ?>">
                🗑 Removidos (<?php echo $count_deleted; ?>)
            </a>
        <?php endif; ?>
    </p>

    <table class="widefat striped" style="margin-top:12px;">
        <thead>
            <tr>
                <th>Tipo</th>
                <th>Valor (CSV)</th>
                <th>→ Faixa interna</th>
                <th>Artista</th>
                <th>ISRC oficial da faixa</th>
                <th>Criado em</th>
                <th>Por</th>
                <?php if ( $show_deleted ): ?>
                    <th>Removido em</th>
                    <th>Razão</th>
                <?php else: ?>
                    <th>Acções</th>
                <?php endif; ?>
            </tr>
        </thead>
        <tbody>
        <?php if ( empty($mappings) ): ?>
            <tr><td colspan="<?php echo $show_deleted ? 9 : 8; ?>" style="text-align:center; padding:30px; color:#888;">
                <?php echo $show_deleted ? 'Sem aliases removidos.' : 'Sem aliases. Cria-os a partir do preview de import.'; ?>
            </td></tr>
        <?php else:
            foreach ( $mappings as $m ):
                // Compat: se csv_value vazio (registo antigo não migrado), usar csv_isrc
                $display_value = ! empty($m->csv_value) ? $m->csv_value : $m->csv_isrc;
                $type = ! empty($m->alias_type) ? $m->alias_type : 'isrc';
                $type_badge_color = ($type === 'upc') ? '#0073aa' : '#9b59b6';
                $del_url = wp_nonce_url(
                    add_query_arg(['delete_id' => $m->id]),
                    'rmbz_delete_isrc_map'
                );
        ?>
            <tr <?php if ( $show_deleted ): ?>style="opacity:0.6;"<?php endif; ?>>
                <td>
                    <span style="background:<?php echo $type_badge_color; ?>; color:#fff; padding:3px 9px; border-radius:4px; font-size:11px; font-weight:600; text-transform:uppercase;">
                        <?php echo esc_html($type); ?>
                    </span>
                </td>
                <td><code><?php echo esc_html($display_value); ?></code></td>
                <td>
                    <?php if ( $m->track_title ): ?>
                        <strong><?php echo esc_html($m->track_title); ?></strong>
                    <?php else: ?>
                        <em style="color:#c00;">⚠ faixa apagada (#<?php echo (int)$m->track_id; ?>)</em>
                    <?php endif; ?>
                </td>
                <td><?php echo esc_html($m->artist_name ?: $m->artist_telemovel ?: '—'); ?></td>
                <td><code><?php echo esc_html($m->track_isrc ?: '—'); ?></code></td>
                <td><?php echo esc_html( date_i18n('d/m/Y H:i', strtotime($m->created_at)) ); ?></td>
                <td><?php echo esc_html($m->created_by ?: '—'); ?></td>
                <?php if ( $show_deleted ): ?>
                    <td><?php echo esc_html( $m->deleted_at ? date_i18n('d/m/Y H:i', strtotime($m->deleted_at)) : '—' ); ?>
                        <?php if ( $m->deleted_by ): ?>
                            <br><small style="color:#888;">por <?php echo esc_html($m->deleted_by); ?></small>
                        <?php endif; ?>
                    </td>
                    <td><small><?php echo esc_html($m->delete_reason ?: '—'); ?></small></td>
                <?php else: ?>
                <td>
                    <a href="<?php echo esc_url($del_url); ?>"
                       class="button button-link-delete"
                       onclick="var r=prompt('Razão para remover este alias (opcional):'); if (r===null) return false; if (r) this.href = this.href + '&reason=' + encodeURIComponent(r); return confirm('Apagar este alias? Futuros imports voltarão a tratar este valor como sem match.\n\nO registo é mantido em arquivo (auditoria).');">
                       🗑 Apagar
                    </a>
                </td>
                <?php endif; ?>
            </tr>
        <?php endforeach; endif; ?>
        </tbody>
    </table>
    <?php
}


/* ============================================================================
 * 6. REGISTO DE MENUS HIDDEN — páginas acessíveis via URL
 * ============================================================================
 * Estas páginas não aparecem no menu lateral mas são acessíveis via URL
 * (vinda da página de imports e do preview). É padrão WordPress comum
 * para sub-páginas que não precisam de entry point principal.
 *
 * [DS 1.5.93] Usamos '' (string vazia) em vez de null como parent_slug.
 * [1.5.167] FIX: o `''` como parent quebra em PHP 8.1+ com:
 *   "Deprecated: strip_tags(): Passing null to parameter #1 ($string)"
 * em /wp-admin/admin-header.php:41. O WP não consegue determinar o
 * $admin_title quando a página não tem parent.
 *
 * Solução (padrão WooCommerce + repetida em admin-withdrawal-guard.php):
 * registamos como sub-item de 'options.php' (que existe sempre) — assim
 * o admin_title resolve correctamente — e a seguir removemos do menu
 * visível com `remove_submenu_page` para a página parecer escondida.
 */
add_action( 'admin_menu', function() {
    add_submenu_page(
        'options.php',
        'Mapeamentos manuais ISRC',
        'Mapeamentos ISRC',
        'manage_options',
        'rmbz-isrc-mappings',
        'rmbz_render_isrc_mappings_page'
    );
    add_submenu_page(
        'options.php',
        'Erros de import',
        'Erros de import',
        'manage_options',
        'rmbz-import-errors',
        'rmbz_render_import_errors_page'
    );
}, 50);

// [1.5.167] Remover do menu visível (continua acessível por URL — é o que queremos).
add_action( 'admin_head', function () {
    remove_submenu_page( 'options.php', 'rmbz-isrc-mappings' );
    remove_submenu_page( 'options.php', 'rmbz-import-errors' );
}, 999 );
