<?php
/**
 * includes/distribution/distribution-release-workflow.php
 *
 * Workflow de aprovação em 3 passos (Aprovar → Entregar → Ao Vivo) +
 * gestão híbrida de links de DSP (Spotify, Apple Music, etc.).
 *
 * Resolve o bug de produto em que o botão "Aprovar" saltava directamente
 * de `pendente` para `live`, quando o tracker visual do artista já estava
 * preparado para 5 passos distintos.
 *
 * Novos estados (que já existiam no tracker mas não tinham handlers):
 *   - approved   (passo 3: admin aprovou, UPC/ISRCs gerados, à espera de
 *                 ser entregue aos agregadores)
 *   - delivered  (passo 4: release foi empurrado para a ferramenta que
 *                 distribui aos DSPs; a caminho das lojas)
 *   - live       (passo 5: já está nas lojas; admin cola/revê links)
 *
 * Novas tabelas:
 *   - {prefix}rmbz_distro_release_links
 *     Um registo por (release_id, dsp_slug) — guarda o URL exacto quando
 *     o admin o cola manualmente. Se não houver registo, o tracker usa
 *     um URL de pesquisa gerado a partir do título + artista (modo
 *     "híbrido" pedido pelo cliente).
 *
 * Novos handlers admin (admin-post):
 *   - rmbz_release_mark_approved   (pendente → approved)
 *   - rmbz_release_mark_delivered  (approved → delivered)
 *   - rmbz_release_mark_live       (delivered → live)
 *   - rmbz_release_save_dsp_links  (guardar links exactos)
 *
 * Todos os handlers passam por `rmbz_distro_change_status` quando possível,
 * ou disparam o hook `rmbz_distro_status_changed` com 3 argumentos (como
 * os outros handlers existentes) para manter compatibilidade.
 */

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


/* ============================================================================
 * SCHEMA — tabela de links DSP por release
 * ============================================================================ */

function rmbz_release_links_maybe_install() {
    $stored = get_option('rmbz_release_links_schema_v', '0');
    if ( version_compare( $stored, '1.0', '<' ) ) {
        global $wpdb;
        $charset_collate = $wpdb->get_charset_collate();
        $table = $wpdb->prefix . 'rmbz_distro_release_links';

        $sql = "CREATE TABLE $table (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            release_id bigint(20) NOT NULL,
            dsp_slug varchar(40) NOT NULL,
            url varchar(500) DEFAULT NULL,
            auto_generated tinyint(1) DEFAULT 0 NOT NULL,
            updated_by varchar(60) DEFAULT NULL,
            created_at datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
            updated_at datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
            PRIMARY KEY  (id),
            UNIQUE KEY uniq_release_dsp (release_id, dsp_slug),
            KEY idx_release (release_id)
        ) ENGINE=InnoDB $charset_collate;";

        require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
        dbDelta( $sql );
        update_option('rmbz_release_links_schema_v', '1.0');
    }
}
add_action('admin_init', 'rmbz_release_links_maybe_install', 7);


/* ============================================================================
 * CATÁLOGO DE DSPs — usa o mesmo que o tracker já tem + padrões de URL
 * ============================================================================
 *
 * Cada entrada tem:
 *   - label       : nome visível
 *   - color       : cor de marca (para o chip no tracker)
 *   - initial     : primeira letra (fallback visual se não houver ícone)
 *   - search_url  : padrão para URL de pesquisa — placeholders {title} e
 *                   {artist} são substituídos por versões urlencoded.
 */
function rmbz_release_links_dsp_catalog() {
    return [
        'spotify' => [
            'label'      => 'Spotify',
            'color'      => '#1DB954',
            'initial'    => 'S',
            'search_url' => 'https://open.spotify.com/search/{title}%20{artist}',
        ],
        'apple_music' => [
            'label'      => 'Apple Music',
            'color'      => '#FC3C44',
            'initial'    => 'A',
            'search_url' => 'https://music.apple.com/search?term={title}%20{artist}',
        ],
        'youtube' => [
            'label'      => 'YouTube Music',
            'color'      => '#FF0000',
            'initial'    => 'Y',
            'search_url' => 'https://music.youtube.com/search?q={title}%20{artist}',
        ],
        'amazon' => [
            'label'      => 'Amazon Music',
            'color'      => '#00A8E1',
            'initial'    => 'a',
            'search_url' => 'https://music.amazon.com/search/{title}+{artist}',
        ],
        'tidal' => [
            'label'      => 'Tidal',
            'color'      => '#000000',
            'initial'    => 'T',
            'search_url' => 'https://tidal.com/search?q={title}%20{artist}',
        ],
        'deezer' => [
            'label'      => 'Deezer',
            'color'      => '#A238FF',
            'initial'    => 'D',
            'search_url' => 'https://www.deezer.com/search/{title}%20{artist}',
        ],
        'boomplay' => [
            'label'      => 'Boomplay',
            'color'      => '#00B46A',
            'initial'    => 'B',
            'search_url' => 'https://www.boomplay.com/search/default/{title}%20{artist}',
        ],
        'audiomack' => [
            'label'      => 'Audiomack',
            'color'      => '#FFA500',
            'initial'    => 'AM',
            'search_url' => 'https://audiomack.com/search?q={title}%20{artist}',
        ],
    ];
}

/**
 * Gera URL de pesquisa com fallback — quando o admin ainda não colou o
 * URL exacto, o artista vê uma pesquisa que acaba quase sempre por trazer
 * o resultado certo nos primeiros 2–3 itens.
 */
function rmbz_release_build_search_url( $dsp_slug, $release_title, $artist_name ) {
    $catalog = rmbz_release_links_dsp_catalog();
    if ( ! isset($catalog[$dsp_slug]) ) return '';
    $pattern = $catalog[$dsp_slug]['search_url'];
    $title   = rawurlencode( trim( (string) $release_title ) );
    $artist  = rawurlencode( trim( (string) $artist_name ) );
    return str_replace( ['{title}', '{artist}'], [$title, $artist], $pattern );
}


/* ============================================================================
 * API PÚBLICA — ler links para um release (usado pelo tracker do artista)
 * ============================================================================
 *
 * Retorna array [dsp_slug => ['url' => ..., 'is_exact' => bool]]
 * `is_exact = true` quando o admin colou URL. `false` quando é pesquisa.
 */
function rmbz_release_get_links_for_tracker( $release ) {
    if ( ! $release || empty($release->id) ) return [];

    global $wpdb;
    $table = $wpdb->prefix . 'rmbz_distro_release_links';

    // Nome do artista — usa o do perfil se disponível, senão o telemóvel
    $artist_name = '';
    if ( function_exists('rmbz_get_artist_nome_by_telemovel') && ! empty($release->artist_telemovel) ) {
        $artist_name = rmbz_get_artist_nome_by_telemovel( $release->artist_telemovel ) ?: '';
    }
    if ( empty($artist_name) ) {
        $wallet_t = $wpdb->prefix . 'rmbz_wallets';
        $artist_name = $wpdb->get_var( $wpdb->prepare(
            "SELECT user_nome FROM $wallet_t WHERE user_telemovel = %s",
            $release->artist_telemovel ?? ''
        ) ) ?: '';
    }

    $exact_rows = [];
    if ( $wpdb->get_var("SHOW TABLES LIKE '$table'") === $table ) {
        $rows = $wpdb->get_results( $wpdb->prepare(
            "SELECT dsp_slug, url FROM $table WHERE release_id = %d",
            $release->id
        ) ) ?: [];
        foreach ( $rows as $r ) {
            if ( ! empty($r->url) ) $exact_rows[ $r->dsp_slug ] = $r->url;
        }
    }

    $out = [];
    foreach ( rmbz_release_links_dsp_catalog() as $slug => $dsp ) {
        if ( isset($exact_rows[$slug]) ) {
            $out[$slug] = [
                'url'      => $exact_rows[$slug],
                'is_exact' => true,
            ];
        } else {
            $out[$slug] = [
                'url'      => rmbz_release_build_search_url( $slug, $release->title, $artist_name ),
                'is_exact' => false,
            ];
        }
    }
    return $out;
}


/* ============================================================================
 * HELPER INTERNO — transição de status com audit log
 * ============================================================================ */
function rmbz_release_workflow_transition( $release_id, $new_status, $note = '' ) {
    global $wpdb;
    $t = $wpdb->prefix . 'rmbz_distro_releases';
    $current = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $t WHERE id = %d", $release_id) );
    if ( ! $current ) return false;

    $update = [ 'status' => $new_status ];
    $fmt    = [ '%s' ];

    // Quando vai para "live", marcar o timestamp
    if ( $new_status === 'live' ) {
        $update['live_at'] = current_time('mysql');
        $fmt[] = '%s';
    }

    $wpdb->update( $t, $update, ['id' => $release_id], $fmt, ['%d'] );

    // Log na tabela de histórico (usa o helper existente se houver)
    if ( function_exists('rmbz_admin_log_status_change') ) {
        rmbz_admin_log_status_change( $release_id, $current->status, $new_status, $note );
    } else {
        // fallback directo
        $h = $wpdb->prefix . 'rmbz_distro_status_history';
        if ( $wpdb->get_var("SHOW TABLES LIKE '$h'") === $h ) {
            $wpdb->insert( $h, [
                'release_id'  => $release_id,
                'from_status' => $current->status,
                'to_status'   => $new_status,
                'reason_text' => $note,
                'changed_by'  => 'admin',
            ] );
        }
    }

    // Disparar o hook com 3 args (formato compatível com os outros disparos)
    do_action('rmbz_distro_status_changed', $release_id, $current->status, $new_status);

    return true;
}


/* ============================================================================
 * HELPER ADMIN — UPC + ISRCs (movido do approve handler antigo)
 * ============================================================================ */
function rmbz_release_workflow_assign_codes( $release_id ) {
    global $wpdb;
    $t = $wpdb->prefix . 'rmbz_distro_releases';
    $t_tracks = $wpdb->prefix . 'rmbz_distro_tracks';

    // UPC
    $current_upc = $wpdb->get_var( $wpdb->prepare("SELECT upc_code FROM $t WHERE id = %d", $release_id) );
    if ( empty($current_upc) && function_exists('rmbz_admin_generate_upc') ) {
        $upc = rmbz_admin_generate_upc();
        $wpdb->update( $t, ['upc_code' => $upc], ['id' => $release_id], ['%s'], ['%d'] );
    }

    // ISRCs
    if ( function_exists('rmbz_admin_generate_isrc') ) {
        $tracks_without_isrc = $wpdb->get_results( $wpdb->prepare(
            "SELECT id FROM $t_tracks WHERE release_id = %d AND (isrc_code IS NULL OR isrc_code = '')",
            $release_id
        ) );
        foreach ( $tracks_without_isrc as $track ) {
            $isrc = rmbz_admin_generate_isrc();
            $wpdb->update( $t_tracks, ['isrc_code' => $isrc], ['id' => $track->id], ['%s'], ['%d'] );
        }
    }
}


/* ============================================================================
 * HANDLER ADMIN #1 — pendente → approved
 * ============================================================================ */
function rmbz_admin_release_mark_approved_handler() {
    if ( ! current_user_can('manage_options') ) wp_die('Sem permissão.');
    $release_id = (int) ($_POST['release_id'] ?? 0);
    if ( ! $release_id ) wp_die('ID inválido.');
    check_admin_referer('rmbz_release_workflow_' . $release_id);

    global $wpdb;
    $t = $wpdb->prefix . 'rmbz_distro_releases';
    $current = $wpdb->get_row( $wpdb->prepare("SELECT status FROM $t WHERE id = %d", $release_id) );

    if ( ! $current ) wp_die('Lançamento não encontrado.');
    if ( ! in_array( $current->status, ['pendente','pending','submitted','returned'], true ) ) {
        wp_die('Este lançamento não pode ser aprovado no estado actual: ' . esc_html($current->status));
    }

    rmbz_release_workflow_assign_codes( $release_id );
    rmbz_release_workflow_transition( $release_id, 'approved', 'Aprovado pelo admin' );

    $return = $_POST['return_to'] ?? '';
    $url    = ($return === 'approval')
        ? admin_url('admin.php?page=rmbz-admin-distribution&tab=approval&msg=approved')
        : admin_url('admin.php?page=rmbz-admin-distribution&tab=releases&view=detail&id=' . $release_id . '&msg=approved');
    wp_safe_redirect( $url );
    exit;
}
add_action('admin_post_rmbz_release_mark_approved', 'rmbz_admin_release_mark_approved_handler');


/* ============================================================================
 * HANDLER ADMIN #2 — approved → delivered
 * ============================================================================ */
function rmbz_admin_release_mark_delivered_handler() {
    if ( ! current_user_can('manage_options') ) wp_die('Sem permissão.');
    $release_id = (int) ($_POST['release_id'] ?? 0);
    if ( ! $release_id ) wp_die('ID inválido.');
    check_admin_referer('rmbz_release_workflow_' . $release_id);

    global $wpdb;
    $t = $wpdb->prefix . 'rmbz_distro_releases';
    $current = $wpdb->get_row( $wpdb->prepare("SELECT status FROM $t WHERE id = %d", $release_id) );

    if ( ! $current ) wp_die('Lançamento não encontrado.');
    if ( $current->status !== 'approved' ) {
        wp_die('Só se pode marcar como entregue um release já aprovado. Estado actual: ' . esc_html($current->status));
    }

    rmbz_release_workflow_transition( $release_id, 'delivered', 'Entregue aos DSPs pelo admin' );

    wp_safe_redirect( admin_url('admin.php?page=rmbz-admin-distribution&tab=releases&view=detail&id=' . $release_id . '&msg=delivered') );
    exit;
}
add_action('admin_post_rmbz_release_mark_delivered', 'rmbz_admin_release_mark_delivered_handler');


/* ============================================================================
 * HANDLER ADMIN #3 — delivered → live
 * ============================================================================ */
function rmbz_admin_release_mark_live_handler() {
    if ( ! current_user_can('manage_options') ) wp_die('Sem permissão.');
    $release_id = (int) ($_POST['release_id'] ?? 0);
    if ( ! $release_id ) wp_die('ID inválido.');
    check_admin_referer('rmbz_release_workflow_' . $release_id);

    global $wpdb;
    $t = $wpdb->prefix . 'rmbz_distro_releases';
    $current = $wpdb->get_row( $wpdb->prepare("SELECT status FROM $t WHERE id = %d", $release_id) );

    if ( ! $current ) wp_die('Lançamento não encontrado.');
    if ( $current->status !== 'delivered' ) {
        wp_die('Só se pode marcar como ao vivo um release já entregue. Estado actual: ' . esc_html($current->status));
    }

    rmbz_release_workflow_transition( $release_id, 'live', 'Publicado nas lojas pelo admin' );

    wp_safe_redirect( admin_url('admin.php?page=rmbz-admin-distribution&tab=releases&view=detail&id=' . $release_id . '&msg=live') );
    exit;
}
add_action('admin_post_rmbz_release_mark_live', 'rmbz_admin_release_mark_live_handler');


/* ============================================================================
 * HANDLER ADMIN #4 — guardar links DSP
 * ============================================================================ */
function rmbz_admin_release_save_dsp_links_handler() {
    if ( ! current_user_can('manage_options') ) wp_die('Sem permissão.');
    $release_id = (int) ($_POST['release_id'] ?? 0);
    if ( ! $release_id ) wp_die('ID inválido.');
    check_admin_referer('rmbz_release_workflow_' . $release_id);

    global $wpdb;
    $table = $wpdb->prefix . 'rmbz_distro_release_links';
    $catalog = rmbz_release_links_dsp_catalog();
    $user = wp_get_current_user();
    $updated_by = $user ? $user->user_login : 'admin';

    $links = is_array($_POST['dsp_link'] ?? null) ? $_POST['dsp_link'] : [];
    $saved = 0;

    foreach ( $catalog as $slug => $dsp ) {
        $raw = sanitize_text_field( $links[$slug] ?? '' );
        $url = $raw !== '' ? esc_url_raw( $raw ) : '';

        // Se o admin limpou o campo — apagamos o registo (volta a mostrar pesquisa)
        if ( $url === '' ) {
            $wpdb->delete( $table, [
                'release_id' => $release_id,
                'dsp_slug'   => $slug,
            ], [ '%d', '%s' ] );
            continue;
        }

        // Upsert manual (a tabela tem UNIQUE (release_id, dsp_slug))
        $existing = $wpdb->get_var( $wpdb->prepare(
            "SELECT id FROM $table WHERE release_id = %d AND dsp_slug = %s",
            $release_id, $slug
        ) );

        if ( $existing ) {
            $wpdb->update( $table,
                [
                    'url'            => $url,
                    'auto_generated' => 0,
                    'updated_by'     => $updated_by,
                    'updated_at'     => current_time('mysql'),
                ],
                [ 'id' => (int) $existing ],
                [ '%s', '%d', '%s', '%s' ],
                [ '%d' ]
            );
        } else {
            $wpdb->insert( $table, [
                'release_id'     => $release_id,
                'dsp_slug'       => $slug,
                'url'            => $url,
                'auto_generated' => 0,
                'updated_by'     => $updated_by,
            ], [ '%d', '%s', '%s', '%d', '%s' ] );
        }
        $saved++;
    }

    wp_safe_redirect( admin_url('admin.php?page=rmbz-admin-distribution&tab=releases&view=detail&id=' . $release_id . '&msg=links_saved&n=' . $saved) );
    exit;
}
add_action('admin_post_rmbz_release_save_dsp_links', 'rmbz_admin_release_save_dsp_links_handler');


/* ============================================================================
 * UI ADMIN — renderiza os botões de workflow conforme o estado
 * ----------------------------------------------------------------------------
 * Usada no detail view do admin. Substitui o antigo botão "Aprovar e
 * marcar LIVE" por uma sequência que reflecte o estado real do release.
 * ============================================================================ */
function rmbz_admin_render_workflow_buttons( $release ) {
    if ( ! $release || empty($release->id) ) return;
    $rid     = (int) $release->id;
    $status  = $release->status;
    $nonce_action = 'rmbz_release_workflow_' . $rid;
    ?>
    <div class="rmbz-workflow-buttons" style="display:flex; flex-direction:column; gap:10px;">

        <?php
        // PASSO 1 → APPROVED
        $can_approve = in_array( $status, ['pendente','pending','submitted','returned'], true );
        if ( $can_approve ):
        ?>
            <form method="post" action="<?php echo esc_url( admin_url('admin-post.php') ); ?>" style="margin:0;">
                <?php wp_nonce_field( $nonce_action ); ?>
                <input type="hidden" name="action" value="rmbz_release_mark_approved">
                <input type="hidden" name="release_id" value="<?php echo $rid; ?>">
                <button type="submit" class="button button-primary" style="width:100%;"
                        onclick="return confirm('Aprovar este lançamento?&#10;&#10;O próximo passo será marcá-lo como Entregue aos DSPs.');">
                    ✓ 1 · Aprovar
                </button>
                <small style="display:block; text-align:center; color:#666; margin-top:4px;">
                    Gera UPC/ISRCs, notifica o artista e avança para o passo "Aprovado".
                </small>
            </form>
        <?php endif; ?>

        <?php
        // PASSO 2 → DELIVERED
        if ( $status === 'approved' ):
        ?>
            <form method="post" action="<?php echo esc_url( admin_url('admin-post.php') ); ?>" style="margin:0;">
                <?php wp_nonce_field( $nonce_action ); ?>
                <input type="hidden" name="action" value="rmbz_release_mark_delivered">
                <input type="hidden" name="release_id" value="<?php echo $rid; ?>">
                <button type="submit" class="button button-primary" style="width:100%; background:#3498db; border-color:#2980b9;"
                        onclick="return confirm('Confirmar: este release foi enviado aos agregadores/DSPs?');">
                    🚀 2 · Marcar como Entregue aos DSPs
                </button>
                <small style="display:block; text-align:center; color:#666; margin-top:4px;">
                    Usa isto quando o release foi empurrado para o agregador (Believe, DistroKid, etc.).
                </small>
            </form>
        <?php endif; ?>

        <?php
        // PASSO 3 → LIVE
        if ( $status === 'delivered' ):
        ?>
            <form method="post" action="<?php echo esc_url( admin_url('admin-post.php') ); ?>" style="margin:0;">
                <?php wp_nonce_field( $nonce_action ); ?>
                <input type="hidden" name="action" value="rmbz_release_mark_live">
                <input type="hidden" name="release_id" value="<?php echo $rid; ?>">
                <button type="submit" class="button button-primary" style="width:100%; background:#2ecc71; border-color:#27ae60;"
                        onclick="return confirm('Marcar como AO VIVO? Verifica primeiro se já está disponível em pelo menos uma loja.');">
                    🎉 3 · Marcar como Ao Vivo
                </button>
                <small style="display:block; text-align:center; color:#666; margin-top:4px;">
                    Depois podes colar os links exactos de cada loja no bloco abaixo.
                </small>
            </form>
        <?php endif; ?>

        <?php
        // Estado actual (quando não há acção seguinte)
        if ( ! $can_approve && ! in_array($status, ['approved','delivered'], true) ):
            $labels = [
                'live'               => ['🎉', 'Ao vivo nas lojas', '#2ecc71'],
                'distribuido'        => ['🎉', 'Ao vivo nas lojas', '#2ecc71'],
                'rejected'           => ['✗',  'Rejeitado',          '#e74c3c'],
                'rejeitado'          => ['✗',  'Rejeitado',          '#e74c3c'],
                'takedown_requested' => ['🗑', 'Takedown solicitado','#888'],
                'taken_down'         => ['🗑', 'Removido das lojas', '#888'],
                'incomplete'         => ['…',  'Ainda em rascunho pelo artista', '#999'],
            ];
            $info = $labels[$status] ?? ['•', ucfirst($status), '#999'];
            ?>
            <div style="padding:12px; background:#f6f7f7; border-left:3px solid <?php echo esc_attr($info[2]); ?>; border-radius:4px;">
                <strong style="color:<?php echo esc_attr($info[2]); ?>;"><?php echo esc_html($info[0]); ?> <?php echo esc_html($info[1]); ?></strong>
                <br>
                <small style="color:#666;">Estado actual do release. Sem acção de workflow disponível.</small>
            </div>
        <?php endif; ?>

    </div>
    <?php
}


/* ============================================================================
 * UI ADMIN — editor de links DSP (aparece a partir de `delivered`)
 * ============================================================================ */
function rmbz_admin_render_dsp_links_editor( $release ) {
    if ( ! $release || empty($release->id) ) return;
    if ( ! in_array($release->status, ['delivered', 'live', 'distribuido'], true) ) {
        // Só faz sentido colar links quando já está entregue ou ao vivo
        return;
    }

    global $wpdb;
    $table = $wpdb->prefix . 'rmbz_distro_release_links';
    $existing = [];
    if ( $wpdb->get_var("SHOW TABLES LIKE '$table'") === $table ) {
        $rows = $wpdb->get_results( $wpdb->prepare(
            "SELECT dsp_slug, url FROM $table WHERE release_id = %d",
            $release->id
        ) ) ?: [];
        foreach ( $rows as $r ) {
            $existing[ $r->dsp_slug ] = $r->url;
        }
    }

    $catalog = rmbz_release_links_dsp_catalog();
    $rid = (int) $release->id;
    ?>
    <div class="rmbz-dsp-links-editor" style="background:#fff; border:1px solid #ccd0d4; border-radius:4px; padding:16px; margin-top:16px;">
        <h3 style="margin:0 0 8px 0;">🔗 Links das lojas (DSPs)</h3>
        <p style="color:#666; font-size:13px; margin:0 0 12px 0;">
            Cola aqui o URL exacto de cada loja quando a música aparecer.
            Campos vazios → o artista vê um link de pesquisa automático (Spotify, Apple Music, etc.).
        </p>

        <?php /* [1.5.122] LAYOUT 100% CARDS — sem tabela, sem media query.
                Razão: a 1.5.121 mantinha a tabela em desktop e só mostrava
                cards ≤720px de viewport. Mas em desktop com sidebar
                estreito (~280-380px), a viewport continua 1920px e a
                regra não disparava — o input continuava esmagado.
                Agora os cards aparecem SEMPRE: em sidebar estreito ficam
                bem; em desktop full-width ficam ainda melhores (input
                generoso). Quando há espaço a partir de 600px fazemos
                grid de 2 colunas para aproveitar o espaço. */ ?>
        <style>
            .rmbz-dsp-cards-list {
                display:grid;
                grid-template-columns:1fr;
                gap:10px;
            }
            /* Layout 2 colunas só quando o container realmente tem espaço.
               Usar container query (nativo em browsers modernos) seria ideal,
               mas para máxima compatibilidade usamos breakpoint da viewport
               com valor alto — só a partir de 1100px (PC com sidebar+main
               já largo) aparecem 2 colunas. Em sidebar estreito mantém-se
               1 coluna independentemente da viewport. */
            @media (min-width: 1100px) {
                .rmbz-dsp-links-editor--wide .rmbz-dsp-cards-list {
                    grid-template-columns:1fr 1fr;
                }
            }
            .rmbz-dsp-card {
                background:#fafafa;
                border:1px solid #e0e0e0;
                border-radius:6px;
                padding:12px;
            }
            .rmbz-dsp-card-head {
                display:flex; align-items:center; justify-content:space-between;
                gap:8px; margin-bottom:8px; flex-wrap:wrap;
            }
            .rmbz-dsp-card-name {
                display:flex; align-items:center; gap:8px;
                font-size:14px; min-width:0;
            }
            .rmbz-dsp-card-name strong {
                white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
                min-width:0;
            }
            .rmbz-dsp-card-status {
                font-size:11px; padding:2px 8px; border-radius:10px;
                white-space:nowrap; flex-shrink:0;
            }
            .rmbz-dsp-card-status--exact { background:#e8f5e9; color:#2e7d32; font-weight:600; }
            .rmbz-dsp-card-status--search { background:#f5f5f5; color:#999; }
            .rmbz-dsp-card input[type=url] {
                width:100%; box-sizing:border-box;
                font-family:monospace; font-size:13px;
                padding:8px 10px;
                border:1px solid #ccc; border-radius:4px;
                background:#fff;
            }
            .rmbz-dsp-card input[type=url]:focus {
                border-color:#2271b1;
                outline:2px solid rgba(34,113,177,0.2);
                outline-offset:0;
            }
        </style>

        <form method="post" action="<?php echo esc_url( admin_url('admin-post.php') ); ?>">
            <?php wp_nonce_field('rmbz_release_workflow_' . $rid); ?>
            <input type="hidden" name="action" value="rmbz_release_save_dsp_links">
            <input type="hidden" name="release_id" value="<?php echo $rid; ?>">

            <div class="rmbz-dsp-cards-list">
                <?php foreach ( $catalog as $slug => $dsp ): $url = $existing[$slug] ?? ''; $has_exact = $url !== ''; ?>
                    <div class="rmbz-dsp-card">
                        <div class="rmbz-dsp-card-head">
                            <div class="rmbz-dsp-card-name">
                                <span style="display:inline-block; width:20px; height:20px; border-radius:50%; background:<?php echo esc_attr($dsp['color']); ?>; color:#fff; text-align:center; line-height:20px; font-size:11px; font-weight:700; flex-shrink:0;">
                                    <?php echo esc_html($dsp['initial']); ?>
                                </span>
                                <strong><?php echo esc_html($dsp['label']); ?></strong>
                            </div>
                            <?php if ( $has_exact ): ?>
                                <span class="rmbz-dsp-card-status rmbz-dsp-card-status--exact">✓ Exacto</span>
                            <?php else: ?>
                                <span class="rmbz-dsp-card-status rmbz-dsp-card-status--search">Pesquisa auto</span>
                            <?php endif; ?>
                        </div>
                        <input type="url" name="dsp_link[<?php echo esc_attr($slug); ?>]"
                               value="<?php echo esc_attr($url); ?>"
                               placeholder="<?php echo esc_attr( rmbz_release_build_search_url($slug, $release->title, '') ); ?>">
                    </div>
                <?php endforeach; ?>
            </div>

            <p style="margin-top:14px;">
                <button type="submit" class="button button-primary">💾 Guardar links</button>
                <span style="color:#888; font-size:12px; margin-left:10px;">
                    Podes guardar parcialmente e completar depois.
                </span>
            </p>
        </form>

        <?php /* [1.5.122] Detector de container largo: se o painel tem mais
                de 800px de largura real, aplica modificador --wide para
                activar grid de 2 colunas. Substituto do container query
                (que tem suporte limitado em alguns browsers). */ ?>
        <script>
        (function(){
            var panel = document.currentScript.closest('.rmbz-dsp-links-editor');
            if (!panel) return;
            function applyWideClass() {
                var w = panel.getBoundingClientRect().width;
                if (w >= 800) {
                    panel.classList.add('rmbz-dsp-links-editor--wide');
                } else {
                    panel.classList.remove('rmbz-dsp-links-editor--wide');
                }
            }
            applyWideClass();
            // Reaplica em resize (debounced)
            var t = null;
            window.addEventListener('resize', function(){
                if (t) clearTimeout(t);
                t = setTimeout(applyWideClass, 100);
            });
        })();
        </script>
    </div>
    <?php
}


/* ============================================================================
 * HANDLER ADMIN #5 — editar UPC do release
 * ----------------------------------------------------------------------------
 * Permite ao admin substituir o UPC gerado pela 1MZ por um UPC próprio do
 * produtor/selo (muitos têm prefixo GS1 registado e querem usar o deles).
 *
 * Três acções no mesmo endpoint consoante o campo 'upc_action':
 *   - 'set'      : guardar UPC manual (validado pela norma GTIN-12/13)
 *   - 'generate' : gerar automático (usa rmbz_admin_generate_upc)
 *   - 'clear'    : limpar (volta a ser "Pendente")
 *
 * Todas as mudanças ficam registadas no histórico (rmbz_distro_status_history).
 * Bloqueia edição quando o release já está em `live` ou `distribuido` — a
 * essa altura o UPC já foi enviado aos DSPs e mudá-lo partia tudo.
 * ============================================================================ */
function rmbz_admin_release_update_upc_handler() {
    if ( ! current_user_can('manage_options') ) wp_die('Sem permissão.');
    $release_id = (int) ($_POST['release_id'] ?? 0);
    if ( ! $release_id ) wp_die('ID inválido.');
    check_admin_referer('rmbz_release_upc_' . $release_id);

    global $wpdb;
    $t = $wpdb->prefix . 'rmbz_distro_releases';
    $current = $wpdb->get_row( $wpdb->prepare("SELECT id, status, upc_code FROM $t WHERE id = %d", $release_id) );
    if ( ! $current ) wp_die('Lançamento não encontrado.');

    // Bloquear se já está publicado — mudar UPC agora dessincroniza com DSPs
    if ( in_array( $current->status, ['live', 'distribuido'], true ) ) {
        wp_safe_redirect( admin_url('admin.php?page=rmbz-admin-distribution&tab=releases&view=detail&id=' . $release_id . '&msg=upc_locked') );
        exit;
    }

    $action    = sanitize_key( $_POST['upc_action'] ?? 'set' );
    $old_upc   = (string) ($current->upc_code ?? '');
    $new_upc   = '';
    $note      = '';

    switch ( $action ) {
        case 'generate':
            if ( ! function_exists('rmbz_admin_generate_upc') ) {
                wp_safe_redirect( admin_url('admin.php?page=rmbz-admin-distribution&tab=releases&view=detail&id=' . $release_id . '&msg=upc_error') );
                exit;
            }
            // Gerar até 5 tentativas para garantir unicidade
            for ( $i = 0; $i < 5; $i++ ) {
                $candidate = rmbz_admin_generate_upc();
                $exists = (int) $wpdb->get_var( $wpdb->prepare(
                    "SELECT COUNT(*) FROM $t WHERE upc_code = %s AND id != %d",
                    $candidate, $release_id
                ) );
                if ( ! $exists ) { $new_upc = $candidate; break; }
            }
            if ( $new_upc === '' ) {
                wp_safe_redirect( admin_url('admin.php?page=rmbz-admin-distribution&tab=releases&view=detail&id=' . $release_id . '&msg=upc_error') );
                exit;
            }
            $note = 'UPC regenerado automaticamente. Antes: ' . ( $old_upc ?: '(vazio)' ) . ' · Agora: ' . $new_upc;
            break;

        case 'clear':
            $new_upc = '';
            $note = 'UPC limpo. Antes: ' . ( $old_upc ?: '(vazio)' );
            break;

        case 'set':
        default:
            $raw = sanitize_text_field( $_POST['new_upc'] ?? '' );
            // Remover tudo o que não seja dígito
            $raw = preg_replace('/\D/', '', $raw);

            if ( $raw === '' ) {
                wp_safe_redirect( admin_url('admin.php?page=rmbz-admin-distribution&tab=releases&view=detail&id=' . $release_id . '&msg=upc_empty') );
                exit;
            }

            // Validar checksum EAN/UPC (12 ou 13 dígitos)
            if ( function_exists('rmbz_validate_upc') && ! rmbz_validate_upc( $raw ) ) {
                wp_safe_redirect( admin_url('admin.php?page=rmbz-admin-distribution&tab=releases&view=detail&id=' . $release_id . '&msg=upc_invalid') );
                exit;
            }

            // Anti-duplicado — não permitir reutilizar UPC de outro release
            $dup = $wpdb->get_var( $wpdb->prepare(
                "SELECT id FROM $t WHERE upc_code = %s AND id != %d LIMIT 1",
                $raw, $release_id
            ) );
            if ( $dup ) {
                wp_safe_redirect( admin_url('admin.php?page=rmbz-admin-distribution&tab=releases&view=detail&id=' . $release_id . '&msg=upc_dup&dup_id=' . (int) $dup) );
                exit;
            }

            $new_upc = $raw;
            $note = 'UPC alterado manualmente pelo admin. Antes: ' . ( $old_upc ?: '(vazio)' ) . ' · Agora: ' . $new_upc;
            break;
    }

    // Persistir
    $wpdb->update( $t,
        [ 'upc_code' => $new_upc ],
        [ 'id' => $release_id ],
        [ '%s' ], [ '%d' ]
    );

    // Audit log — usa o helper existente
    if ( function_exists('rmbz_admin_log_status_change') ) {
        rmbz_admin_log_status_change( $release_id, $current->status, $current->status, $note );
    }

    wp_safe_redirect( admin_url('admin.php?page=rmbz-admin-distribution&tab=releases&view=detail&id=' . $release_id . '&msg=upc_saved') );
    exit;
}
add_action('admin_post_rmbz_release_update_upc', 'rmbz_admin_release_update_upc_handler');


/* ============================================================================
 * UI — editor de UPC inline (substitui o <code>...</code> estático)
 * ----------------------------------------------------------------------------
 * Mostra o UPC actual + botão "✏️ Editar". Ao clicar, abre um pequeno bloco
 * com três acções: campo para colar UPC manual, botão "🎲 Gerar automático",
 * botão "🗑 Limpar". Bloqueado para releases já live/distribuido.
 * ============================================================================ */
function rmbz_admin_render_upc_editor( $release ) {
    if ( empty($release->id) ) return;
    $rid = (int) $release->id;
    $upc = (string) ($release->upc_code ?? '');
    $locked = in_array( $release->status, ['live', 'distribuido'], true );
    ?>
    <div class="rmbz-upc-cell">
        <?php if ( $upc !== '' ): ?>
            <code><?php echo esc_html( $upc ); ?></code>
        <?php else: ?>
            <em style="color:#aaa;">Pendente</em>
        <?php endif; ?>

        <?php if ( $locked ): ?>
            <small style="color:#888; margin-left:8px;">🔒 bloqueado (release publicado)</small>
        <?php else: ?>
            <button type="button" class="button button-small" style="margin-left:8px;"
                    onclick="document.getElementById('rmbz-upc-editor-<?php echo $rid; ?>').style.display='block'; this.style.display='none';">
                ✏️ Editar
            </button>

            <div id="rmbz-upc-editor-<?php echo $rid; ?>" style="display:none; margin-top:10px; padding:12px; background:#f6f7f7; border-left:3px solid #f0b90b; border-radius:4px;">
                <strong style="display:block; margin-bottom:6px;">Editar UPC / EAN</strong>
                <p style="color:#666; font-size:11px; margin:0 0 10px 0;">
                    Usa um UPC próprio do produtor/selo (deve ter 12 ou 13 dígitos válidos, checksum GS1).
                    Ou gera automaticamente com o prefixo da 1MZ.
                </p>

                <form method="post" action="<?php echo esc_url( admin_url('admin-post.php') ); ?>" style="display:flex; gap:6px; align-items:center; margin:0 0 6px 0; flex-wrap:wrap;">
                    <?php wp_nonce_field('rmbz_release_upc_' . $rid); ?>
                    <input type="hidden" name="action" value="rmbz_release_update_upc">
                    <input type="hidden" name="release_id" value="<?php echo $rid; ?>">
                    <input type="hidden" name="upc_action" value="set">
                    <input type="text"
                           name="new_upc"
                           value="<?php echo esc_attr( $upc ); ?>"
                           placeholder="Ex: 8585557656989"
                           pattern="[0-9\s\-]{12,20}"
                           maxlength="20"
                           style="font-family:monospace; font-size:13px; flex:1; min-width:200px;"
                           required>
                    <button type="submit" class="button button-primary button-small">💾 Salvar UPC manual</button>
                </form>

                <div style="display:flex; gap:6px; flex-wrap:wrap;">
                    <form method="post" action="<?php echo esc_url( admin_url('admin-post.php') ); ?>" style="margin:0;"
                          onsubmit="return confirm('Gerar um novo UPC automaticamente? O actual será substituído.');">
                        <?php wp_nonce_field('rmbz_release_upc_' . $rid); ?>
                        <input type="hidden" name="action" value="rmbz_release_update_upc">
                        <input type="hidden" name="release_id" value="<?php echo $rid; ?>">
                        <input type="hidden" name="upc_action" value="generate">
                        <button type="submit" class="button button-small">🎲 Gerar automático</button>
                    </form>

                    <?php if ( $upc !== '' ): ?>
                        <form method="post" action="<?php echo esc_url( admin_url('admin-post.php') ); ?>" style="margin:0;"
                              onsubmit="return confirm('Limpar o UPC? Vai ficar pendente (será gerado na próxima aprovação).');">
                            <?php wp_nonce_field('rmbz_release_upc_' . $rid); ?>
                            <input type="hidden" name="action" value="rmbz_release_update_upc">
                            <input type="hidden" name="release_id" value="<?php echo $rid; ?>">
                            <input type="hidden" name="upc_action" value="clear">
                            <button type="submit" class="button button-small" style="color:#c0392b;">🗑 Limpar</button>
                        </form>
                    <?php endif; ?>

                    <button type="button" class="button button-small"
                            onclick="document.getElementById('rmbz-upc-editor-<?php echo $rid; ?>').style.display='none'; document.querySelector('.rmbz-upc-cell button:first-of-type').style.display='inline-block';">
                        Cancelar
                    </button>
                </div>
            </div>
        <?php endif; ?>
    </div>
    <?php
}
