<?php
/**
 * Monetizacao nativa por download valido.
 *
 * O Art Track identifica a titularidade, o Programa de Parceria controla o
 * acesso e a carteira 1MZ e a unica origem financeira. O fluxo antigo baseado
 * em URL/CPT claim permanece apenas como fonte de migracao ate ser limpo.
 */

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

if ( ! defined( 'RMBZ_DM_SCHEMA' ) ) define( 'RMBZ_DM_SCHEMA', '1.0.0' );

function rmbz_dm_tables() {
    global $wpdb;
    return [
        'enrollments'     => $wpdb->prefix . 'rmbz_download_monetization',
        'events'          => $wpdb->prefix . 'rmbz_download_earnings',
        'rates'           => $wpdb->prefix . 'rmbz_download_rates',
        'settlements'     => $wpdb->prefix . 'rmbz_download_settlements',
        'legacy_balances' => $wpdb->prefix . 'rmbz_download_legacy_balances',
        'audit'           => $wpdb->prefix . 'rmbz_download_audit',
    ];
}

function rmbz_dm_native_ready() {
    global $wpdb;
    $t = rmbz_dm_tables();
    return $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $t['enrollments'] ) ) === $t['enrollments'];
}

function rmbz_dm_legacy_disabled() {
    return true;
}

function rmbz_dm_install() {
    global $wpdb;
    if ( ! function_exists( 'dbDelta' ) ) require_once ABSPATH . 'wp-admin/includes/upgrade.php';
    $t = rmbz_dm_tables();
    $ch = $wpdb->get_charset_collate();

    dbDelta( "CREATE TABLE {$t['enrollments']} (
        id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
        art_track_id bigint(20) unsigned NOT NULL,
        music_id bigint(20) unsigned NOT NULL,
        account_phone varchar(32) NOT NULL DEFAULT '',
        status varchar(20) NOT NULL DEFAULT 'inactive',
        rate_override decimal(12,4) DEFAULT NULL,
        rights_confirmed tinyint(1) unsigned NOT NULL DEFAULT 0,
        terms_accepted tinyint(1) unsigned NOT NULL DEFAULT 0,
        activated_by bigint(20) unsigned NOT NULL DEFAULT 0,
        activated_at datetime DEFAULT NULL,
        reviewed_by bigint(20) unsigned NOT NULL DEFAULT 0,
        decision_reason text NULL,
        legacy_snapshot longtext NULL,
        created_at datetime NOT NULL,
        updated_at datetime NOT NULL,
        PRIMARY KEY  (id),
        UNIQUE KEY music_id (music_id),
        KEY art_track_id (art_track_id),
        KEY account_phone (account_phone),
        KEY status (status)
    ) $ch;" );

    dbDelta( "CREATE TABLE {$t['events']} (
        id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
        event_key varchar(64) NOT NULL,
        enrollment_id bigint(20) unsigned NOT NULL,
        settlement_id bigint(20) unsigned NOT NULL DEFAULT 0,
        art_track_id bigint(20) unsigned NOT NULL,
        music_id bigint(20) unsigned NOT NULL,
        account_phone varchar(32) NOT NULL DEFAULT '',
        download_source varchar(20) NOT NULL DEFAULT 'free',
        visitor_hash varchar(64) NOT NULL DEFAULT '',
        ip_hash varchar(64) NOT NULL DEFAULT '',
        user_agent_hash varchar(64) NOT NULL DEFAULT '',
        country varchar(12) NOT NULL DEFAULT '',
        rate_snapshot decimal(12,4) NOT NULL DEFAULT 0.0000,
        amount decimal(12,4) NOT NULL DEFAULT 0.0000,
        status varchar(20) NOT NULL DEFAULT 'pending',
        rejection_reason varchar(120) NOT NULL DEFAULT '',
        occurred_at datetime NOT NULL,
        available_at datetime DEFAULT NULL,
        settled_at datetime DEFAULT NULL,
        wallet_transaction_id bigint(20) unsigned NOT NULL DEFAULT 0,
        context_json longtext NULL,
        PRIMARY KEY  (id),
        UNIQUE KEY event_key (event_key),
        KEY enrollment_id (enrollment_id),
        KEY settlement_id (settlement_id),
        KEY music_status (music_id,status),
        KEY phone_status (account_phone,status),
        KEY visitor_music (visitor_hash,music_id),
        KEY occurred_at (occurred_at),
        KEY available_at (available_at)
    ) $ch;" );

    dbDelta( "CREATE TABLE {$t['rates']} (
        id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
        rate decimal(12,4) NOT NULL DEFAULT 0.5000,
        effective_from datetime NOT NULL,
        effective_to datetime DEFAULT NULL,
        status varchar(20) NOT NULL DEFAULT 'active',
        set_by bigint(20) unsigned NOT NULL DEFAULT 0,
        note varchar(255) NOT NULL DEFAULT '',
        created_at datetime NOT NULL,
        PRIMARY KEY  (id),
        KEY status_effective (status,effective_from),
        KEY effective_to (effective_to)
    ) $ch;" );

    dbDelta( "CREATE TABLE {$t['settlements']} (
        id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
        batch_key varchar(64) NOT NULL,
        account_phone varchar(32) NOT NULL DEFAULT '',
        event_count int unsigned NOT NULL DEFAULT 0,
        amount decimal(12,2) NOT NULL DEFAULT 0.00,
        status varchar(20) NOT NULL DEFAULT 'processing',
        wallet_transaction_id bigint(20) unsigned NOT NULL DEFAULT 0,
        error_message text NULL,
        created_by bigint(20) unsigned NOT NULL DEFAULT 0,
        created_at datetime NOT NULL,
        paid_at datetime DEFAULT NULL,
        PRIMARY KEY  (id),
        UNIQUE KEY batch_key (batch_key),
        KEY phone_status (account_phone,status),
        KEY created_at (created_at)
    ) $ch;" );

    dbDelta( "CREATE TABLE {$t['legacy_balances']} (
        id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
        wp_user_id bigint(20) unsigned NOT NULL,
        account_phone varchar(32) NOT NULL DEFAULT '',
        amount decimal(12,2) NOT NULL DEFAULT 0.00,
        status varchar(20) NOT NULL DEFAULT 'review',
        wallet_transaction_id bigint(20) unsigned NOT NULL DEFAULT 0,
        reviewed_by bigint(20) unsigned NOT NULL DEFAULT 0,
        note text NULL,
        created_at datetime NOT NULL,
        reviewed_at datetime DEFAULT NULL,
        PRIMARY KEY  (id),
        UNIQUE KEY wp_user_id (wp_user_id),
        KEY status (status),
        KEY account_phone (account_phone)
    ) $ch;" );

    dbDelta( "CREATE TABLE {$t['audit']} (
        id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
        actor_user_id bigint(20) unsigned NOT NULL DEFAULT 0,
        event_type varchar(80) NOT NULL,
        object_type varchar(40) NOT NULL DEFAULT '',
        object_id bigint(20) unsigned NOT NULL DEFAULT 0,
        from_status varchar(20) NOT NULL DEFAULT '',
        to_status varchar(20) NOT NULL DEFAULT '',
        note text NULL,
        context_json longtext NULL,
        ip_hash varchar(64) NOT NULL DEFAULT '',
        created_at datetime NOT NULL,
        PRIMARY KEY  (id),
        KEY event_type (event_type),
        KEY object_ref (object_type,object_id),
        KEY created_at (created_at)
    ) $ch;" );

    if ( ! $wpdb->get_var( "SELECT id FROM {$t['rates']} LIMIT 1" ) ) {
        $wpdb->insert( $t['rates'], [
            'rate'           => 0.50,
            'effective_from' => current_time( 'mysql' ),
            'status'         => 'active',
            'set_by'         => get_current_user_id(),
            'note'           => 'Tarifa inicial da monetizacao nativa.',
            'created_at'     => current_time( 'mysql' ),
        ] );
    }

    add_option( 'rmbz_dm_enabled', 1, '', false );
    add_option( 'rmbz_dm_hold_days', 7, '', false );
    add_option( 'rmbz_dm_repeat_days', 30, '', false );
    add_option( 'rmbz_dm_daily_music_limit', 0, '', false );
    add_option( 'rmbz_dm_monthly_fund', 0, '', false );
    update_option( 'rmbz_dm_schema', RMBZ_DM_SCHEMA, false );

    $role = get_role( 'administrator' );
    if ( $role ) $role->add_cap( 'rmbz_manage_download_monetization' );
}

function rmbz_dm_maybe_install() {
    if ( get_option( 'rmbz_dm_schema' ) !== RMBZ_DM_SCHEMA || ! rmbz_dm_native_ready() ) rmbz_dm_install();
    if ( ! get_option( 'rmbz_dm_legacy_migration_complete' ) ) rmbz_dm_migrate_legacy();
    if ( ! wp_next_scheduled( 'rmbz_dm_hourly_settlement' ) ) wp_schedule_event( time() + 300, 'hourly', 'rmbz_dm_hourly_settlement' );
}
add_action( 'admin_init', 'rmbz_dm_maybe_install', 2 );
if ( defined( 'RMBZ_PLUGIN_PATH' ) ) register_activation_hook( RMBZ_PLUGIN_PATH . '1mz-for-artists.php', 'rmbz_dm_install' );

function rmbz_dm_audit( $event, $object_type = '', $object_id = 0, $from = '', $to = '', $note = '', array $context = [] ) {
    global $wpdb;
    if ( ! rmbz_dm_native_ready() ) return false;
    $t = rmbz_dm_tables();
    $ip = function_exists( 'imz_get_user_ip' ) ? (string) imz_get_user_ip() : (string) ( $_SERVER['REMOTE_ADDR'] ?? '' );
    return (bool) $wpdb->insert( $t['audit'], [
        'actor_user_id' => get_current_user_id(),
        'event_type'    => sanitize_key( $event ),
        'object_type'   => sanitize_key( $object_type ),
        'object_id'     => absint( $object_id ),
        'from_status'   => sanitize_key( $from ),
        'to_status'     => sanitize_key( $to ),
        'note'          => sanitize_textarea_field( $note ),
        'context_json'  => wp_json_encode( $context, JSON_UNESCAPED_UNICODE ),
        'ip_hash'       => $ip !== '' ? hash_hmac( 'sha256', $ip, wp_salt( 'auth' ) ) : '',
        'created_at'    => current_time( 'mysql' ),
    ] );
}

function rmbz_dm_current_rate( $at = '' ) {
    global $wpdb;
    if ( ! rmbz_dm_native_ready() ) return 0.50;
    $t = rmbz_dm_tables();
    $at = $at ?: current_time( 'mysql' );
    $rate = $wpdb->get_var( $wpdb->prepare(
        "SELECT rate FROM {$t['rates']} WHERE status='active' AND effective_from<=%s AND (effective_to IS NULL OR effective_to>%s) ORDER BY effective_from DESC,id DESC LIMIT 1",
        $at,
        $at
    ) );
    return $rate === null ? 0.50 : max( 0.01, (float) $rate );
}

function rmbz_dm_enrollment( $music_id ) {
    global $wpdb;
    if ( ! rmbz_dm_native_ready() ) return null;
    $t = rmbz_dm_tables();
    return $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$t['enrollments']} WHERE music_id=%d LIMIT 1", absint( $music_id ) ) );
}

function rmbz_dm_catalog_owner( $music_id ) {
    global $wpdb;
    if ( ! function_exists( 'rmbz_art_tracks_native_tables' ) || ! rmbz_art_tracks_native_ready() ) return null;
    $at = rmbz_art_tracks_native_tables();
    return $wpdb->get_row( $wpdb->prepare(
        "SELECT c.art_track_id,c.role,c.publication_status,t.account_phone,t.linked_user_id,t.status track_status,COALESCE(a.status,'none') partnership_status FROM {$at['catalog']} c JOIN {$at['tracks']} t ON t.id=c.art_track_id LEFT JOIN {$at['applications']} a ON a.art_track_id=t.id WHERE c.site_post_id=%d AND c.role='primary' AND c.publication_status='published' ORDER BY c.id LIMIT 1",
        absint( $music_id )
    ) );
}

function rmbz_dm_activation_check( $phone, $music_id, $admin_override = false ) {
    $music_id = absint( $music_id );
    $post = get_post( $music_id );
    if ( ! $post || $post->post_type !== 'post' || $post->post_status !== 'publish' ) return new WP_Error( 'invalid_music', 'A musica nao esta publicada.' );
    if ( function_exists( 'rmbz_site_publication_is_visible' ) && ! rmbz_site_publication_is_visible( $music_id ) ) return new WP_Error( 'hidden_music', 'A publicacao nao esta visivel no site.' );
    $owner = rmbz_dm_catalog_owner( $music_id );
    if ( ! $owner ) return new WP_Error( 'not_primary', 'A monetizacao esta disponivel apenas para a faixa principal do Art Track.' );
    if ( $owner->track_status !== 'active' ) return new WP_Error( 'track_inactive', 'O Art Track nao esta ativo.' );
    if ( $owner->partnership_status !== 'approved' ) return new WP_Error( 'partnership_required', 'O Programa de Parceria precisa estar aprovado.' );
    if ( ! $admin_override ) {
        $normal = function_exists( 'rmbz_artists_normalize_phone' ) ? rmbz_artists_normalize_phone( $phone ) : preg_replace( '/\D+/', '', (string) $phone );
        $owner_phone = function_exists( 'rmbz_artists_normalize_phone' ) ? rmbz_artists_normalize_phone( $owner->account_phone ) : preg_replace( '/\D+/', '', (string) $owner->account_phone );
        if ( $normal === '' || $normal !== $owner_phone ) return new WP_Error( 'not_owner', 'Esta musica nao pertence a tua conta.' );
    }
    if ( get_post_meta( $music_id, '_imz_enable_download', true ) !== 'yes' ) return new WP_Error( 'download_disabled', 'Ativa primeiro o download gratuito desta musica.' );
    return $owner;
}

function rmbz_dm_save_enrollment( $music_id, array $data ) {
    global $wpdb;
    $music_id = absint( $music_id );
    if ( ! $music_id || ! rmbz_dm_native_ready() ) return false;
    $t = rmbz_dm_tables();
    $current = rmbz_dm_enrollment( $music_id );
    $allowed_status = [ 'inactive', 'pending', 'active', 'suspended', 'archived' ];
    $out = [];
    foreach ( [ 'art_track_id', 'account_phone', 'status', 'rate_override', 'rights_confirmed', 'terms_accepted', 'activated_by', 'activated_at', 'reviewed_by', 'decision_reason', 'legacy_snapshot' ] as $key ) {
        if ( ! array_key_exists( $key, $data ) ) continue;
        $value = $data[ $key ];
        if ( in_array( $key, [ 'art_track_id', 'activated_by', 'reviewed_by' ], true ) ) $value = absint( $value );
        elseif ( in_array( $key, [ 'rights_confirmed', 'terms_accepted' ], true ) ) $value = empty( $value ) ? 0 : 1;
        elseif ( $key === 'account_phone' ) $value = sanitize_text_field( $value );
        elseif ( $key === 'status' ) $value = in_array( $value, $allowed_status, true ) ? $value : 'inactive';
        elseif ( $key === 'rate_override' ) $value = $value === '' || $value === null ? null : max( 0.01, (float) $value );
        elseif ( $key === 'decision_reason' ) $value = sanitize_textarea_field( $value );
        elseif ( $key === 'legacy_snapshot' && is_array( $value ) ) $value = wp_json_encode( $value, JSON_UNESCAPED_UNICODE );
        $out[ $key ] = $value;
    }
    $out['updated_at'] = current_time( 'mysql' );
    if ( $current ) return $wpdb->update( $t['enrollments'], $out, [ 'music_id' => $music_id ] ) !== false;
    $out['music_id'] = $music_id;
    $out['created_at'] = current_time( 'mysql' );
    return (bool) $wpdb->insert( $t['enrollments'], $out );
}

function rmbz_dm_music_summary( $music_id ) {
    global $wpdb;
    $enrollment = rmbz_dm_enrollment( $music_id );
    $rate = $enrollment && $enrollment->rate_override !== null ? (float) $enrollment->rate_override : rmbz_dm_current_rate();
    $base = [
        'status' => $enrollment ? (string) $enrollment->status : 'inactive',
        'rate' => $rate,
        'valid_downloads' => 0,
        'pending_downloads' => 0,
        'rejected_downloads' => 0,
        'pending_amount' => 0.0,
        'paid_amount' => 0.0,
        'enrollment' => $enrollment,
    ];
    if ( ! $enrollment || ! rmbz_dm_native_ready() ) return $base;
    $t = rmbz_dm_tables();
    $row = $wpdb->get_row( $wpdb->prepare(
        "SELECT SUM(CASE WHEN status IN ('pending','processing','paid') THEN 1 ELSE 0 END) valid_downloads,SUM(CASE WHEN status IN ('pending','processing') THEN 1 ELSE 0 END) pending_downloads,SUM(CASE WHEN status='rejected' THEN 1 ELSE 0 END) rejected_downloads,COALESCE(SUM(CASE WHEN status IN ('pending','processing') THEN amount ELSE 0 END),0) pending_amount,COALESCE(SUM(CASE WHEN status='paid' THEN amount ELSE 0 END),0) paid_amount FROM {$t['events']} WHERE enrollment_id=%d",
        $enrollment->id
    ) );
    if ( $row ) foreach ( [ 'valid_downloads', 'pending_downloads', 'rejected_downloads' ] as $key ) $base[ $key ] = (int) $row->$key;
    if ( $row ) foreach ( [ 'pending_amount', 'paid_amount' ] as $key ) $base[ $key ] = (float) $row->$key;
    return $base;
}

function rmbz_dm_artist_redirect( $notice ) {
    $url = function_exists( 'imz_rmbz_account_url' ) ? imz_rmbz_account_url( 'musicas' ) : add_query_arg( 'sect', 'musicas', home_url( '/minha-conta/' ) );
    wp_safe_redirect( add_query_arg( 'monet_notice', sanitize_key( $notice ), $url ) );
    exit;
}

function rmbz_dm_activate_music() {
    $music_id = absint( $_POST['music_id'] ?? 0 );
    if ( ! isset( $_POST['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), 'rmbz_dm_activate_' . $music_id ) ) rmbz_dm_artist_redirect( 'security_error' );
    if ( ! function_exists( 'rmbz_is_user_logged_in' ) || ! rmbz_is_user_logged_in() ) rmbz_dm_artist_redirect( 'login_required' );
    if ( empty( $_POST['rights_confirmed'] ) || empty( $_POST['terms_accepted'] ) ) rmbz_dm_artist_redirect( 'terms_required' );
    $phone = (string) rmbz_get_current_user_telemovel();
    $owner = rmbz_dm_activation_check( $phone, $music_id );
    if ( is_wp_error( $owner ) ) rmbz_dm_artist_redirect( $owner->get_error_code() );
    $current = rmbz_dm_enrollment( $music_id );
    if ( $current && in_array( $current->status, [ 'suspended', 'archived' ], true ) ) rmbz_dm_artist_redirect( $current->status );
    $ok = rmbz_dm_save_enrollment( $music_id, [
        'art_track_id'     => $owner->art_track_id,
        'account_phone'    => $owner->account_phone,
        'status'           => 'active',
        'rights_confirmed' => 1,
        'terms_accepted'   => 1,
        'activated_by'     => get_current_user_id(),
        'activated_at'     => current_time( 'mysql' ),
        'decision_reason'  => '',
    ] );
    if ( ! $ok ) rmbz_dm_artist_redirect( 'save_error' );
    $fresh = rmbz_dm_enrollment( $music_id );
    rmbz_dm_audit( 'artist_activated', 'enrollment', $fresh ? $fresh->id : 0, $current ? $current->status : 'inactive', 'active', 'Monetizacao ativada pelo titular.', [ 'music_id' => $music_id ] );
    rmbz_dm_artist_redirect( 'activated' );
}
add_action( 'admin_post_rmbz_dm_activate_music', 'rmbz_dm_activate_music' );

function rmbz_dm_request_ip() {
    return function_exists( 'imz_get_user_ip' ) ? (string) imz_get_user_ip() : sanitize_text_field( (string) ( $_SERVER['REMOTE_ADDR'] ?? '' ) );
}

function rmbz_dm_record_download( $music_id, $source = 'free' ) {
    global $wpdb;
    $music_id = absint( $music_id );
    $source = sanitize_key( $source );
    if ( ! $music_id || $source === 'paid' || ! get_option( 'rmbz_dm_enabled', 1 ) || ! rmbz_dm_native_ready() ) return;
    $enrollment = rmbz_dm_enrollment( $music_id );
    if ( ! $enrollment || $enrollment->status !== 'active' ) return;
    $owner = rmbz_dm_catalog_owner( $music_id );
    if ( ! $owner || $owner->partnership_status !== 'approved' || $owner->track_status !== 'active' ) return;

    $ip = rmbz_dm_request_ip();
    $ua = sanitize_text_field( (string) ( $_SERVER['HTTP_USER_AGENT'] ?? '' ) );
    $visitor_seed = $ip . '|' . $ua . '|' . sanitize_text_field( (string) ( $_COOKIE['imz_visitor_id'] ?? '' ) );
    $visitor_hash = hash_hmac( 'sha256', $visitor_seed, wp_salt( 'auth' ) );
    $ip_hash = $ip !== '' ? hash_hmac( 'sha256', $ip, wp_salt( 'auth' ) ) : '';
    $ua_hash = $ua !== '' ? hash( 'sha256', $ua ) : '';
    $token = sanitize_key( (string) ( $_GET['download_key'] ?? '' ) );
    $event_key = hash( 'sha256', $music_id . '|' . $visitor_hash . '|' . $token . '|' . gmdate( 'Y-m-d H:i:s' ) );
    $now = current_time( 'mysql' );
    $status = 'pending';
    $reason = '';

    if ( function_exists( 'rmbz_is_user_logged_in' ) && rmbz_is_user_logged_in() && function_exists( 'rmbz_get_current_user_telemovel' ) ) {
        $current_phone = function_exists( 'rmbz_artists_normalize_phone' ) ? rmbz_artists_normalize_phone( rmbz_get_current_user_telemovel() ) : preg_replace( '/\D+/', '', (string) rmbz_get_current_user_telemovel() );
        $owner_phone = function_exists( 'rmbz_artists_normalize_phone' ) ? rmbz_artists_normalize_phone( $enrollment->account_phone ) : preg_replace( '/\D+/', '', (string) $enrollment->account_phone );
        if ( $current_phone !== '' && $current_phone === $owner_phone ) { $status = 'rejected'; $reason = 'artist_self_download'; }
    }

    $t = rmbz_dm_tables();
    $event_lock = 'rmbz_dm_event_' . $music_id;
    $locked = (int) $wpdb->get_var( $wpdb->prepare( 'SELECT GET_LOCK(%s,3)', $event_lock ) );
    if ( $locked !== 1 ) return;
    try {
    $repeat_days = max( 1, min( 365, absint( get_option( 'rmbz_dm_repeat_days', 30 ) ) ) );
    $cutoff = date( 'Y-m-d H:i:s', current_time( 'timestamp' ) - DAY_IN_SECONDS * $repeat_days );
    if ( $status === 'pending' ) {
        $duplicate = $wpdb->get_var( $wpdb->prepare(
            "SELECT id FROM {$t['events']} WHERE music_id=%d AND visitor_hash=%s AND status IN ('pending','processing','paid') AND occurred_at>=%s LIMIT 1",
            $music_id,
            $visitor_hash,
            $cutoff
        ) );
        if ( $duplicate ) { $status = 'rejected'; $reason = 'duplicate_visitor'; }
    }

    $daily_limit = absint( get_option( 'rmbz_dm_daily_music_limit', 0 ) );
    if ( $status === 'pending' && $daily_limit > 0 ) {
        $today_count = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$t['events']} WHERE music_id=%d AND status IN ('pending','processing','paid') AND DATE(occurred_at)=CURDATE()", $music_id ) );
        if ( $today_count >= $daily_limit ) { $status = 'rejected'; $reason = 'daily_music_limit'; }
    }

    $rate = $enrollment->rate_override !== null ? max( 0.01, (float) $enrollment->rate_override ) : rmbz_dm_current_rate( $now );
    $monthly_fund = max( 0, (float) get_option( 'rmbz_dm_monthly_fund', 0 ) );
    if ( $status === 'pending' && $monthly_fund > 0 ) {
        $month_start = date( 'Y-m-01 00:00:00', current_time( 'timestamp' ) );
        $committed = (float) $wpdb->get_var( $wpdb->prepare( "SELECT COALESCE(SUM(amount),0) FROM {$t['events']} WHERE status IN ('pending','processing','paid') AND occurred_at>=%s", $month_start ) );
        if ( $committed + $rate > $monthly_fund ) { $status = 'rejected'; $reason = 'monthly_fund_reached'; }
    }

    $hold_days = max( 0, min( 90, absint( get_option( 'rmbz_dm_hold_days', 7 ) ) ) );
    $available = date( 'Y-m-d H:i:s', current_time( 'timestamp' ) + DAY_IN_SECONDS * $hold_days );
    $wpdb->insert( $t['events'], [
        'event_key'          => $event_key,
        'enrollment_id'      => $enrollment->id,
        'art_track_id'       => $enrollment->art_track_id,
        'music_id'           => $music_id,
        'account_phone'      => $enrollment->account_phone,
        'download_source'    => $source ?: 'free',
        'visitor_hash'       => $visitor_hash,
        'ip_hash'            => $ip_hash,
        'user_agent_hash'    => $ua_hash,
        'country'            => sanitize_text_field( (string) ( $_SERVER['HTTP_CF_IPCOUNTRY'] ?? '' ) ),
        'rate_snapshot'      => $status === 'pending' ? $rate : 0,
        'amount'             => $status === 'pending' ? $rate : 0,
        'status'             => $status,
        'rejection_reason'   => $reason,
        'occurred_at'        => $now,
        'available_at'       => $status === 'pending' ? $available : null,
        'context_json'       => wp_json_encode( [ 'repeat_days' => $repeat_days, 'hold_days' => $hold_days ], JSON_UNESCAPED_UNICODE ),
    ] );
    } finally {
        $wpdb->get_var( $wpdb->prepare( 'SELECT RELEASE_LOCK(%s)', $event_lock ) );
    }
}
add_action( 'imz_download_completed', 'rmbz_dm_record_download', 20, 2 );

function rmbz_dm_settle_available( $created_by = 0 ) {
    global $wpdb;
    if ( ! rmbz_dm_native_ready() || ! function_exists( 'rmbz_update_wallet_balance' ) ) return [ 'paid' => 0, 'failed' => 0, 'amount' => 0.0 ];
    $lock = (int) $wpdb->get_var( "SELECT GET_LOCK('rmbz_dm_settlement',5)" );
    if ( ! $lock ) return [ 'paid' => 0, 'failed' => 1, 'amount' => 0.0 ];
    $result = [ 'paid' => 0, 'failed' => 0, 'amount' => 0.0 ];
    $t = rmbz_dm_tables();
    try {
        $phones = $wpdb->get_col( "SELECT DISTINCT account_phone FROM {$t['events']} WHERE status='pending' AND available_at IS NOT NULL AND available_at<=NOW() AND account_phone<>'' LIMIT 250" );
        foreach ( $phones as $phone ) {
            $events = $wpdb->get_results( $wpdb->prepare( "SELECT id,amount FROM {$t['events']} WHERE account_phone=%s AND status='pending' AND available_at<=NOW() ORDER BY id LIMIT 5000", $phone ) );
            if ( ! $events ) continue;
            $ids = array_map( 'absint', wp_list_pluck( $events, 'id' ) );
            $amount = round( array_sum( array_map( static fn( $row ) => (float) $row->amount, $events ) ), 2 );
            if ( $amount <= 0 ) continue;
            $batch_key = hash( 'sha256', $phone . '|' . implode( ',', $ids ) );
            $wpdb->insert( $t['settlements'], [
                'batch_key'     => $batch_key,
                'account_phone' => $phone,
                'event_count'   => count( $ids ),
                'amount'        => $amount,
                'status'        => 'processing',
                'created_by'    => absint( $created_by ),
                'created_at'    => current_time( 'mysql' ),
            ] );
            $settlement_id = absint( $wpdb->insert_id );
            if ( ! $settlement_id ) {
                $settlement_id = absint( $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$t['settlements']} WHERE batch_key=%s", $batch_key ) ) );
            }
            if ( ! $settlement_id ) { $result['failed']++; continue; }
            $safe_ids = implode( ',', $ids );
            $wpdb->query( "UPDATE {$t['events']} SET status='processing',settlement_id={$settlement_id} WHERE id IN ({$safe_ids}) AND status='pending'" );

            $tx_table = $wpdb->prefix . 'rmbz_wallet_transactions';
            $tx_id = absint( $wpdb->get_var( $wpdb->prepare( "SELECT transaction_id FROM {$tx_table} WHERE user_telemovel=%s AND type='download_monetization' AND project_id=%d ORDER BY transaction_id DESC LIMIT 1", $phone, $settlement_id ) ) );
            $wallet = $tx_id ? [ 'success' => true ] : rmbz_update_wallet_balance( $phone, $amount, 'download_monetization', $settlement_id, sprintf( 'Monetizacao de %d download(s) valido(s) [DM:%d]', count( $ids ), $settlement_id ) );
            if ( ! empty( $wallet['success'] ) ) {
                if ( ! $tx_id ) $tx_id = absint( $wpdb->get_var( $wpdb->prepare( "SELECT transaction_id FROM {$tx_table} WHERE user_telemovel=%s AND type='download_monetization' AND project_id=%d ORDER BY transaction_id DESC LIMIT 1", $phone, $settlement_id ) ) );
                $wpdb->update( $t['settlements'], [ 'status' => 'paid', 'wallet_transaction_id' => $tx_id, 'paid_at' => current_time( 'mysql' ), 'error_message' => null ], [ 'id' => $settlement_id ] );
                $wpdb->query( "UPDATE {$t['events']} SET status='paid',wallet_transaction_id={$tx_id},settled_at=NOW() WHERE settlement_id={$settlement_id} AND status='processing'" );
                $result['paid']++;
                $result['amount'] += $amount;
                rmbz_dm_audit( 'settlement_paid', 'settlement', $settlement_id, 'processing', 'paid', 'Ganhos creditados na carteira oficial.', [ 'events' => count( $ids ), 'amount' => $amount, 'phone' => $phone ] );
                if ( function_exists( 'rmbz_notify_create' ) ) {
                    rmbz_notify_create( [
                        'type'             => 'download_monetization_paid',
                        'severity'         => 'success',
                        'title'            => 'Ganhos de downloads creditados',
                        'body'             => sprintf( '%s MT de %d download(s) valido(s) ja estao disponiveis na tua carteira.', number_format_i18n( $amount, 2 ), count( $ids ) ),
                        'action_url'       => add_query_arg( 'sect', 'financas', home_url( '/minha-conta/' ) ),
                        'action_label'     => 'Ver carteira',
                        'target_telemovel' => $phone,
                        'dedup_key'        => 'download_settlement_' . $settlement_id,
                        'metadata'         => [ 'settlement_id' => $settlement_id, 'event_count' => count( $ids ), 'amount' => $amount ],
                        'created_by'       => 'download_monetization',
                    ] );
                }
            } else {
                $error = sanitize_text_field( (string) ( $wallet['error'] ?? 'Falha na carteira.' ) );
                $wpdb->update( $t['settlements'], [ 'status' => 'failed', 'error_message' => $error ], [ 'id' => $settlement_id ] );
                $wpdb->query( "UPDATE {$t['events']} SET status='pending',settlement_id=0 WHERE settlement_id={$settlement_id} AND status='processing'" );
                $result['failed']++;
            }
        }
    } finally {
        $wpdb->query( "SELECT RELEASE_LOCK('rmbz_dm_settlement')" );
    }
    $result['amount'] = round( $result['amount'], 2 );
    return $result;
}

add_action( 'rmbz_dm_hourly_settlement', 'rmbz_dm_settle_available' );

function rmbz_dm_migrate_legacy() {
    global $wpdb;
    if ( ! rmbz_dm_native_ready() || ! function_exists( 'rmbz_art_tracks_native_tables' ) || ! rmbz_art_tracks_native_ready() ) return [ 'migrated' => 0, 'skipped' => 0, 'balances' => 0 ];
    $ids = get_posts( [ 'post_type' => 'post', 'post_status' => 'any', 'posts_per_page' => -1, 'fields' => 'ids', 'meta_key' => '_is_claimed', 'meta_value' => 'yes', 'no_found_rows' => true ] );
    $result = [ 'migrated' => 0, 'skipped' => 0, 'balances' => 0 ];
    foreach ( $ids as $music_id ) {
        $owner = rmbz_dm_catalog_owner( $music_id );
        if ( ! $owner ) { $result['skipped']++; continue; }
        $current = rmbz_dm_enrollment( $music_id );
        if ( $current ) continue;
        $snapshot = [
            'is_claimed'        => 'yes',
            'artist_earnings'   => (float) get_post_meta( $music_id, '_artist_earnings', true ),
            'gross_earnings'    => (float) get_post_meta( $music_id, '_imz_total_earnings', true ),
            'migrated_at'       => current_time( 'mysql' ),
        ];
        $status = $owner->partnership_status === 'approved' ? 'active' : 'pending';
        if ( rmbz_dm_save_enrollment( $music_id, [
            'art_track_id'     => $owner->art_track_id,
            'account_phone'    => $owner->account_phone,
            'status'           => $status,
            'rights_confirmed' => 1,
            'terms_accepted'   => 1,
            'activated_by'     => absint( $owner->linked_user_id ),
            'activated_at'     => current_time( 'mysql' ),
            'decision_reason'  => $status === 'pending' ? 'A aguardar aprovacao do Programa de Parceria.' : 'Migrada do sistema anterior.',
            'legacy_snapshot'  => $snapshot,
        ] ) ) $result['migrated']++; else $result['skipped']++;
    }

    $t = rmbz_dm_tables();
    $legacy_balances = $wpdb->get_results( "SELECT user_id,meta_value FROM {$wpdb->usermeta} WHERE meta_key='_imz_engagement_balance' AND CAST(meta_value AS DECIMAL(12,2))>0" );
    $at = rmbz_art_tracks_native_tables();
    foreach ( $legacy_balances as $legacy ) {
        $phone = (string) $wpdb->get_var( $wpdb->prepare( "SELECT account_phone FROM {$at['tracks']} WHERE linked_user_id=%d ORDER BY id LIMIT 1", $legacy->user_id ) );
        $inserted = $wpdb->query( $wpdb->prepare(
            "INSERT IGNORE INTO {$t['legacy_balances']} (wp_user_id,account_phone,amount,status,created_at) VALUES (%d,%s,%f,'review',%s)",
            $legacy->user_id,
            $phone,
            (float) $legacy->meta_value,
            current_time( 'mysql' )
        ) );
        if ( $inserted ) $result['balances']++;
    }
    update_option( 'rmbz_dm_legacy_migration_complete', [ 'at' => current_time( 'mysql' ), 'result' => $result ], false );
    rmbz_dm_audit( 'legacy_migrated', 'system', 0, '', 'complete', 'Migração do sistema de monetizacao anterior.', $result );
    return $result;
}

function rmbz_dm_admin_can_manage() {
    return current_user_can( 'manage_options' ) || current_user_can( 'rmbz_manage_download_monetization' );
}

function rmbz_dm_admin_menu() {
    $parent = function_exists( 'imz_admin_parent_slug' ) ? imz_admin_parent_slug() : 'tools.php';
    add_submenu_page( $parent, 'Monetizacao e Downloads', 'Monetizacao e Downloads', 'manage_options', 'rmbz-download-monetization', 'rmbz_dm_admin_page' );
}
add_action( 'admin_menu', 'rmbz_dm_admin_menu', 37 );

function rmbz_dm_admin_url( array $args = [] ) {
    return add_query_arg( array_merge( [ 'post_type' => 'impulsionamento', 'page' => 'rmbz-download-monetization' ], $args ), admin_url( 'edit.php' ) );
}

function rmbz_dm_admin_notice_redirect( $notice, array $extra = [] ) {
    wp_safe_redirect( rmbz_dm_admin_url( array_merge( [ 'dm_notice' => sanitize_key( $notice ) ], $extra ) ) );
    exit;
}

function rmbz_dm_save_settings() {
    if ( ! rmbz_dm_admin_can_manage() ) wp_die( 'Sem permissao.' );
    check_admin_referer( 'rmbz_dm_save_settings' );
    global $wpdb;
    $t = rmbz_dm_tables();
    update_option( 'rmbz_dm_enabled', empty( $_POST['enabled'] ) ? 0 : 1, false );
    update_option( 'rmbz_dm_hold_days', max( 0, min( 90, absint( $_POST['hold_days'] ?? 7 ) ) ), false );
    update_option( 'rmbz_dm_repeat_days', max( 1, min( 365, absint( $_POST['repeat_days'] ?? 30 ) ) ), false );
    update_option( 'rmbz_dm_daily_music_limit', max( 0, absint( $_POST['daily_music_limit'] ?? 0 ) ), false );
    update_option( 'rmbz_dm_monthly_fund', max( 0, (float) ( $_POST['monthly_fund'] ?? 0 ) ), false );
    $new_rate = max( 0.01, min( 1000, (float) ( $_POST['rate'] ?? 0.50 ) ) );
    $current_rate = rmbz_dm_current_rate();
    if ( abs( $new_rate - $current_rate ) > 0.00001 ) {
        $now = current_time( 'mysql' );
        $wpdb->query( $wpdb->prepare( "UPDATE {$t['rates']} SET status='expired',effective_to=%s WHERE status='active' AND effective_to IS NULL", $now ) );
        $wpdb->insert( $t['rates'], [ 'rate' => $new_rate, 'effective_from' => $now, 'status' => 'active', 'set_by' => get_current_user_id(), 'note' => sanitize_text_field( wp_unslash( $_POST['rate_note'] ?? '' ) ), 'created_at' => $now ] );
        rmbz_dm_audit( 'rate_changed', 'rate', $wpdb->insert_id, '', 'active', 'Tarifa por download atualizada.', [ 'old_rate' => $current_rate, 'new_rate' => $new_rate ] );
    }
    rmbz_dm_admin_notice_redirect( 'settings_saved' );
}
add_action( 'admin_post_rmbz_dm_save_settings', 'rmbz_dm_save_settings' );

function rmbz_dm_admin_enrollment_action() {
    if ( ! rmbz_dm_admin_can_manage() ) wp_die( 'Sem permissao.' );
    $music_id = absint( $_POST['music_id'] ?? 0 );
    check_admin_referer( 'rmbz_dm_enrollment_' . $music_id );
    $status = sanitize_key( $_POST['monet_status'] ?? 'inactive' );
    if ( ! in_array( $status, [ 'inactive', 'active', 'suspended', 'archived' ], true ) ) $status = 'inactive';
    $owner = rmbz_dm_activation_check( '', $music_id, true );
    if ( is_wp_error( $owner ) && $status === 'active' ) rmbz_dm_admin_notice_redirect( $owner->get_error_code() );
    if ( is_wp_error( $owner ) ) $owner = rmbz_dm_catalog_owner( $music_id );
    if ( ! $owner ) rmbz_dm_admin_notice_redirect( 'invalid_music' );
    $current = rmbz_dm_enrollment( $music_id );
    $override_raw = trim( (string) wp_unslash( $_POST['rate_override'] ?? '' ) );
    $ok = rmbz_dm_save_enrollment( $music_id, [
        'art_track_id'     => $owner->art_track_id,
        'account_phone'    => $owner->account_phone,
        'status'           => $status,
        'rate_override'    => $override_raw === '' ? null : max( 0.01, (float) $override_raw ),
        'rights_confirmed' => $current ? $current->rights_confirmed : 1,
        'terms_accepted'   => $current ? $current->terms_accepted : 1,
        'activated_by'     => $current ? $current->activated_by : get_current_user_id(),
        'activated_at'     => $status === 'active' ? current_time( 'mysql' ) : ( $current->activated_at ?? null ),
        'reviewed_by'      => get_current_user_id(),
        'decision_reason'  => sanitize_textarea_field( wp_unslash( $_POST['decision_reason'] ?? '' ) ),
    ] );
    if ( ! $ok ) rmbz_dm_admin_notice_redirect( 'save_error' );
    $fresh = rmbz_dm_enrollment( $music_id );
    $rejected_pending = 0;
    if ( $fresh && ! empty( $_POST['reject_pending'] ) && in_array( $status, [ 'inactive', 'suspended', 'archived' ], true ) ) {
        global $wpdb;
        $tables = rmbz_dm_tables();
        $rejected_pending = (int) $wpdb->query( $wpdb->prepare(
            "UPDATE {$tables['events']} SET status='rejected',amount=0,available_at=NULL,rejection_reason='admin_review' WHERE enrollment_id=%d AND status='pending'",
            $fresh->id
        ) );
    }
    rmbz_dm_audit( 'enrollment_reviewed', 'enrollment', $fresh ? $fresh->id : 0, $current ? $current->status : 'inactive', $status, (string) ( $fresh->decision_reason ?? '' ), [ 'music_id' => $music_id, 'rate_override' => $override_raw ] );
    if ( $rejected_pending ) {
        rmbz_dm_audit( 'pending_events_rejected', 'enrollment', $fresh->id, 'pending', 'rejected', 'Ganhos pendentes rejeitados por decisao administrativa.', [ 'music_id' => $music_id, 'events' => $rejected_pending ] );
    }
    rmbz_dm_admin_notice_redirect( 'music_updated' );
}
add_action( 'admin_post_rmbz_dm_enrollment_action', 'rmbz_dm_admin_enrollment_action' );

function rmbz_dm_manual_settle() {
    if ( ! rmbz_dm_admin_can_manage() ) wp_die( 'Sem permissao.' );
    check_admin_referer( 'rmbz_dm_manual_settle' );
    $result = rmbz_dm_settle_available( get_current_user_id() );
    rmbz_dm_admin_notice_redirect( 'settled', [ 'paid' => $result['paid'], 'failed' => $result['failed'], 'amount' => $result['amount'] ] );
}
add_action( 'admin_post_rmbz_dm_manual_settle', 'rmbz_dm_manual_settle' );

function rmbz_dm_run_migration_action() {
    if ( ! rmbz_dm_admin_can_manage() ) wp_die( 'Sem permissao.' );
    check_admin_referer( 'rmbz_dm_run_migration' );
    delete_option( 'rmbz_dm_legacy_migration_complete' );
    $result = rmbz_dm_migrate_legacy();
    rmbz_dm_admin_notice_redirect( 'migrated', $result );
}
add_action( 'admin_post_rmbz_dm_run_migration', 'rmbz_dm_run_migration_action' );

function rmbz_dm_legacy_balance_action() {
    if ( ! rmbz_dm_admin_can_manage() ) wp_die( 'Sem permissao.' );
    $id = absint( $_POST['legacy_id'] ?? 0 );
    check_admin_referer( 'rmbz_dm_legacy_balance_' . $id );
    global $wpdb;
    $t = rmbz_dm_tables();
    $row = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$t['legacy_balances']} WHERE id=%d", $id ) );
    if ( ! $row || $row->status !== 'review' ) rmbz_dm_admin_notice_redirect( 'legacy_invalid' );
    $decision = sanitize_key( $_POST['legacy_decision'] ?? '' );
    if ( $decision === 'ignore' ) {
        $wpdb->update( $t['legacy_balances'], [ 'status' => 'ignored', 'reviewed_by' => get_current_user_id(), 'reviewed_at' => current_time( 'mysql' ), 'note' => sanitize_textarea_field( wp_unslash( $_POST['note'] ?? '' ) ) ], [ 'id' => $id ] );
        rmbz_dm_audit( 'legacy_balance_ignored', 'legacy_balance', $id, 'review', 'ignored', 'Saldo legado marcado como ja tratado.' );
        rmbz_dm_admin_notice_redirect( 'legacy_updated' );
    }
    if ( $decision !== 'credit' || $row->account_phone === '' || (float) $row->amount <= 0 ) rmbz_dm_admin_notice_redirect( 'legacy_phone_missing' );
    $tx_table = $wpdb->prefix . 'rmbz_wallet_transactions';
    $tx_id = absint( $wpdb->get_var( $wpdb->prepare( "SELECT transaction_id FROM {$tx_table} WHERE user_telemovel=%s AND type='download_monetization_legacy' AND project_id=%d LIMIT 1", $row->account_phone, $id ) ) );
    $result = $tx_id ? [ 'success' => true ] : rmbz_update_wallet_balance( $row->account_phone, (float) $row->amount, 'download_monetization_legacy', $id, 'Saldo migrado da monetizacao antiga [DM-LEGACY:' . $id . ']' );
    if ( empty( $result['success'] ) ) rmbz_dm_admin_notice_redirect( 'wallet_error' );
    if ( ! $tx_id ) $tx_id = absint( $wpdb->get_var( $wpdb->prepare( "SELECT transaction_id FROM {$tx_table} WHERE user_telemovel=%s AND type='download_monetization_legacy' AND project_id=%d ORDER BY transaction_id DESC LIMIT 1", $row->account_phone, $id ) ) );
    $wpdb->update( $t['legacy_balances'], [ 'status' => 'credited', 'wallet_transaction_id' => $tx_id, 'reviewed_by' => get_current_user_id(), 'reviewed_at' => current_time( 'mysql' ), 'note' => sanitize_textarea_field( wp_unslash( $_POST['note'] ?? '' ) ) ], [ 'id' => $id ] );
    rmbz_dm_audit( 'legacy_balance_credited', 'legacy_balance', $id, 'review', 'credited', 'Saldo legado creditado na carteira.', [ 'amount' => (float) $row->amount, 'phone' => $row->account_phone ] );
    rmbz_dm_admin_notice_redirect( 'legacy_updated' );
}
add_action( 'admin_post_rmbz_dm_legacy_balance_action', 'rmbz_dm_legacy_balance_action' );

function rmbz_dm_legacy_counts() {
    global $wpdb;
    $counts = [];
    foreach ( [ 'imz_engagements', 'imz_engagement_monthly' ] as $suffix ) {
        $table = $wpdb->prefix . $suffix;
        $exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ) === $table;
        $counts[ $suffix ] = $exists ? (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$table}" ) : 0;
    }
    $counts['claim_posts'] = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type='claim'" );
    $counts['claim_postmeta'] = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->postmeta} WHERE meta_key IN ('_is_claimed','_imz_total_earnings','_artist_earnings')" );
    $counts['legacy_usermeta'] = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$wpdb->usermeta} WHERE meta_key IN ('_imz_engagement_balance','_fraudulent_claim_strikes')" );
    return $counts;
}

function rmbz_dm_cleanup_legacy() {
    if ( ! rmbz_dm_admin_can_manage() ) wp_die( 'Sem permissao.' );
    check_admin_referer( 'rmbz_dm_cleanup_legacy' );
    $confirmation = trim( (string) wp_unslash( $_POST['confirmation'] ?? '' ) );
    if ( $confirmation !== 'APAGAR MONETIZACAO ANTIGA' || empty( $_POST['acknowledge'] ) ) rmbz_dm_admin_notice_redirect( 'cleanup_confirmation' );
    if ( ! get_option( 'rmbz_dm_legacy_migration_complete' ) ) rmbz_dm_admin_notice_redirect( 'migration_required' );
    global $wpdb;
    $before = rmbz_dm_legacy_counts();
    update_option( 'rmbz_dm_legacy_cleanup_snapshot', [ 'at' => current_time( 'mysql' ), 'counts' => $before, 'actor' => get_current_user_id() ], false );
    foreach ( [ $wpdb->prefix . 'imz_engagements', $wpdb->prefix . 'imz_engagement_monthly' ] as $table ) {
        if ( preg_match( '/^[A-Za-z0-9_]+$/', $table ) ) $wpdb->query( "DROP TABLE IF EXISTS `{$table}`" );
    }
    $claim_ids = array_map( 'absint', $wpdb->get_col( "SELECT ID FROM {$wpdb->posts} WHERE post_type='claim'" ) );
    if ( $claim_ids ) {
        $safe = implode( ',', $claim_ids );
        $wpdb->query( "DELETE FROM {$wpdb->postmeta} WHERE post_id IN ({$safe})" );
        $wpdb->query( "DELETE FROM {$wpdb->posts} WHERE ID IN ({$safe})" );
    }
    $wpdb->query( "DELETE FROM {$wpdb->postmeta} WHERE meta_key IN ('_is_claimed','_imz_total_earnings','_artist_earnings')" );
    $wpdb->query( "DELETE FROM {$wpdb->usermeta} WHERE meta_key IN ('_imz_engagement_balance','_fraudulent_claim_strikes')" );
    foreach ( [ 'imz_engagement_enabled', 'imz_engagement_rate_free', 'imz_engagement_rate_pro', 'imz_engagement_monthly_fund', 'imz_engagement_like_rate_limit', 'imz_engagement_min_wait_seconds', 'imz_engagement_last_calculation' ] as $option ) delete_option( $option );
    update_option( 'rmbz_dm_legacy_cleaned_at', current_time( 'mysql' ), false );
    rmbz_dm_audit( 'legacy_storage_deleted', 'system', 0, 'migrated', 'deleted', 'Armazenamento antigo removido pela administracao.', $before );
    rmbz_dm_admin_notice_redirect( 'cleanup_complete' );
}
add_action( 'admin_post_rmbz_dm_cleanup_legacy', 'rmbz_dm_cleanup_legacy' );

function rmbz_dm_admin_page() {
    if ( ! rmbz_dm_admin_can_manage() ) wp_die( 'Sem permissao.' );
    global $wpdb;
    rmbz_dm_maybe_install();
    $t = rmbz_dm_tables();
    $at = rmbz_art_tracks_native_tables();
    $notice = sanitize_key( wp_unslash( $_GET['dm_notice'] ?? '' ) );
    $search = sanitize_text_field( wp_unslash( $_GET['s'] ?? '' ) );
    $filter = sanitize_key( wp_unslash( $_GET['monet_status'] ?? 'all' ) );
    if ( ! in_array( $filter, [ 'all', 'inactive', 'pending', 'active', 'suspended', 'archived' ], true ) ) $filter = 'all';
    $where = "c.role='primary' AND c.publication_status='published'";
    $params = [];
    if ( $filter !== 'all' ) { $where .= " AND COALESCE(e.status,'inactive')=%s"; $params[] = $filter; }
    if ( $search !== '' ) { $like = '%' . $wpdb->esc_like( $search ) . '%'; $where .= ' AND (c.title_snapshot LIKE %s OR t.artist_name LIKE %s OR t.account_phone LIKE %s)'; array_push( $params, $like, $like, $like ); }
    $sql = "SELECT c.site_post_id music_id,c.art_track_id,c.title_snapshot,t.artist_name,t.account_phone,COALESCE(a.status,'none') partnership_status,e.id enrollment_id,COALESCE(e.status,'inactive') monet_status,e.rate_override,e.decision_reason FROM {$at['catalog']} c JOIN {$at['tracks']} t ON t.id=c.art_track_id LEFT JOIN {$at['applications']} a ON a.art_track_id=t.id LEFT JOIN {$t['enrollments']} e ON e.music_id=c.site_post_id WHERE {$where} ORDER BY FIELD(COALESCE(e.status,'inactive'),'pending','suspended','active','inactive','archived'),c.updated_at DESC LIMIT 300";
    $music_rows = $params ? $wpdb->get_results( $wpdb->prepare( $sql, $params ) ) : $wpdb->get_results( $sql );
    $events = $wpdb->get_results( "SELECT e.*,p.post_title FROM {$t['events']} e LEFT JOIN {$wpdb->posts} p ON p.ID=e.music_id ORDER BY e.id DESC LIMIT 40" );
    $settlements = $wpdb->get_results( "SELECT * FROM {$t['settlements']} ORDER BY id DESC LIMIT 20" );
    $legacy = $wpdb->get_results( "SELECT * FROM {$t['legacy_balances']} WHERE status='review' ORDER BY amount DESC,id ASC LIMIT 100" );
    $legacy_counts = rmbz_dm_legacy_counts();
    $summary = $wpdb->get_row( "SELECT COUNT(*) total,COALESCE(SUM(CASE WHEN status='active' THEN 1 ELSE 0 END),0) active FROM {$t['enrollments']}" );
    $money = $wpdb->get_row( "SELECT COALESCE(SUM(CASE WHEN status IN ('pending','processing') THEN amount ELSE 0 END),0) pending,COALESCE(SUM(CASE WHEN status='paid' THEN amount ELSE 0 END),0) paid,COALESCE(SUM(CASE WHEN status='rejected' THEN 1 ELSE 0 END),0) rejected FROM {$t['events']}" );
    $migration = get_option( 'rmbz_dm_legacy_migration_complete' );
    $cleaned = get_option( 'rmbz_dm_legacy_cleaned_at' );
    $notices = [
        'settings_saved' => 'Configuracoes guardadas. A nova tarifa aplica-se apenas a downloads futuros.',
        'music_updated' => 'Estado da musica atualizado e auditado.',
        'settled' => sprintf( 'Liquidacao concluida: %d carteira(s), %s MT, %d falha(s).', absint( $_GET['paid'] ?? 0 ), number_format_i18n( (float) ( $_GET['amount'] ?? 0 ), 2 ), absint( $_GET['failed'] ?? 0 ) ),
        'migrated' => sprintf( 'Migracao concluida: %d musica(s), %d saldo(s) preservado(s), %d ignorado(s).', absint( $_GET['migrated'] ?? 0 ), absint( $_GET['balances'] ?? 0 ), absint( $_GET['skipped'] ?? 0 ) ),
        'cleanup_complete' => 'As tabelas e referencias antigas foram removidas. O sistema nativo permanece intacto.',
        'cleanup_confirmation' => 'A frase de confirmacao ou a declaracao de seguranca esta incorreta.',
        'migration_required' => 'Executa a migracao antes de apagar os dados antigos.',
        'legacy_updated' => 'Saldo antigo analisado e registado.',
        'legacy_phone_missing' => 'Nao foi possivel creditar: falta associar uma carteira valida.',
        'wallet_error' => 'A carteira recusou o credito. Nenhum estado foi alterado.',
        'invalid_music' => 'A musica nao esta corretamente ligada ao Art Track.',
        'partnership_required' => 'A parceria precisa estar aprovada antes de ativar a monetizacao.',
        'download_disabled' => 'O download gratuito precisa estar ativo.',
        'save_error' => 'Nao foi possivel guardar a alteracao.',
    ];
    ?>
    <div class="wrap rmbz-dm-admin">
        <style>
            .rmbz-dm-admin{--dm-green:#0b6b50;--dm-ink:#18201d;--dm-soft:#eef5f1;max-width:1480px}.rmbz-dm-top{display:flex;justify-content:space-between;gap:20px;align-items:flex-start;margin:22px 0}.rmbz-dm-top h1{font-size:30px;margin:0;color:var(--dm-ink)}.rmbz-dm-top p{font-size:14px;color:#646970}.rmbz-dm-live{padding:9px 13px;border-radius:999px;background:#dff5eb;color:#086248;font-weight:750}.rmbz-dm-notice{padding:13px 16px;border-left:4px solid var(--dm-green);background:#fff;border-radius:10px;margin:12px 0}.rmbz-dm-stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px}.rmbz-dm-card,.rmbz-dm-panel{background:#fff;border:1px solid #dcdcde;border-radius:18px;box-shadow:0 4px 18px rgba(0,0,0,.035)}.rmbz-dm-card{padding:18px}.rmbz-dm-card small{font-size:11px;font-weight:800;color:#6b746f}.rmbz-dm-card strong{display:block;margin-top:8px;font-size:25px;color:var(--dm-ink)}.rmbz-dm-grid{display:grid;grid-template-columns:minmax(0,1.45fr) minmax(340px,.75fr);gap:16px;margin-top:16px}.rmbz-dm-panel{padding:20px}.rmbz-dm-panel h2{margin:0 0 5px;font-size:19px}.rmbz-dm-panel>p{color:#646970}.rmbz-dm-settings{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px}.rmbz-dm-field{display:grid;gap:6px}.rmbz-dm-field span{font-size:12px;font-weight:700}.rmbz-dm-field input,.rmbz-dm-field select,.rmbz-dm-field textarea,.rmbz-dm-search input{min-height:42px;border:1px solid #c9cfcc;border-radius:11px;padding:8px 11px}.rmbz-dm-actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}.rmbz-dm-btn{display:inline-flex;align-items:center;justify-content:center;min-height:40px;padding:0 15px;border:0;border-radius:999px;background:#e9eeeb;color:#17211d;font-weight:750;cursor:pointer;text-decoration:none}.rmbz-dm-btn.primary{background:var(--dm-green);color:#fff}.rmbz-dm-btn.danger{background:#ffe8e8;color:#a4262c}.rmbz-dm-toolbar{display:flex;gap:9px;margin:18px 0}.rmbz-dm-search{flex:1}.rmbz-dm-search input{width:100%}.rmbz-dm-tabs{display:flex;gap:6px;flex-wrap:wrap}.rmbz-dm-tabs a{padding:9px 12px;border-radius:999px;background:#fff;border:1px solid #dcdcde;text-decoration:none;color:#2c3338}.rmbz-dm-tabs a.on{background:#1d342c;color:#fff}.rmbz-dm-list{display:grid;gap:9px}.rmbz-dm-row{display:grid;grid-template-columns:minmax(220px,1.2fr) minmax(160px,.7fr) minmax(390px,1.5fr);gap:14px;align-items:center;padding:13px;border:1px solid #e0e3e1;border-radius:14px;background:#fafbfa}.rmbz-dm-title{font-size:14px;font-weight:800}.rmbz-dm-meta{margin-top:4px;color:#6b746f;font-size:11px}.rmbz-dm-state{display:inline-flex;padding:6px 9px;border-radius:999px;background:#ecefed;font-size:11px;font-weight:750}.rmbz-dm-state.active,.rmbz-dm-state.paid{background:#dff5eb;color:#086248}.rmbz-dm-state.pending,.rmbz-dm-state.processing{background:#fff2cc;color:#735700}.rmbz-dm-state.suspended,.rmbz-dm-state.rejected,.rmbz-dm-state.failed{background:#ffe8e8;color:#a4262c}.rmbz-dm-row form{display:grid;grid-template-columns:120px 110px minmax(150px,1fr) auto auto;gap:7px;align-items:center}.rmbz-dm-reject{display:flex;gap:6px;align-items:center;font-size:11px;font-weight:700;white-space:nowrap}.rmbz-dm-row form select,.rmbz-dm-row form input{min-height:38px;border-radius:9px}.rmbz-dm-table{width:100%;border-collapse:collapse}.rmbz-dm-table th,.rmbz-dm-table td{text-align:left;padding:11px 8px;border-bottom:1px solid #e3e5e4;font-size:12px}.rmbz-dm-danger{border-color:#efb5b5;background:#fffafa}.rmbz-dm-confirm{width:100%;max-width:420px;text-transform:uppercase}.rmbz-dm-help{padding:12px;border-radius:12px;background:var(--dm-soft);font-size:12px;line-height:1.6}@media(max-width:1100px){.rmbz-dm-stats{grid-template-columns:1fr 1fr}.rmbz-dm-grid{grid-template-columns:1fr}.rmbz-dm-row{grid-template-columns:1fr}.rmbz-dm-row form{grid-template-columns:1fr 1fr}.rmbz-dm-settings{grid-template-columns:1fr 1fr}}@media(max-width:650px){.rmbz-dm-stats,.rmbz-dm-settings,.rmbz-dm-row form{grid-template-columns:1fr}.rmbz-dm-top,.rmbz-dm-toolbar{display:grid}}
        </style>
        <header class="rmbz-dm-top"><div><h1>Monetizacao e Downloads</h1><p>Tarifas, musicas, antifraude, ganhos pendentes e pagamentos na carteira oficial.</p></div><span class="rmbz-dm-live"><?php echo get_option( 'rmbz_dm_enabled', 1 ) ? 'Sistema ativo' : 'Sistema pausado'; ?></span></header>
        <?php if ( isset( $notices[ $notice ] ) ): ?><div class="rmbz-dm-notice"><?php echo esc_html( $notices[ $notice ] ); ?></div><?php endif; ?>
        <section class="rmbz-dm-stats"><article class="rmbz-dm-card"><small>MUSICAS ATIVAS</small><strong><?php echo (int) $summary->active; ?></strong></article><article class="rmbz-dm-card"><small>GANHOS PENDENTES</small><strong><?php echo esc_html( number_format_i18n( (float) $money->pending, 2 ) ); ?> MT</strong></article><article class="rmbz-dm-card"><small>PAGO NAS CARTEIRAS</small><strong><?php echo esc_html( number_format_i18n( (float) $money->paid, 2 ) ); ?> MT</strong></article><article class="rmbz-dm-card"><small>EVENTOS REJEITADOS</small><strong><?php echo (int) $money->rejected; ?></strong></article></section>

        <div class="rmbz-dm-grid">
            <section class="rmbz-dm-panel"><h2>Politica de pagamento</h2><p>A tarifa fica congelada no momento de cada download. Alteracoes nao afetam ganhos anteriores.</p><form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>"><input type="hidden" name="action" value="rmbz_dm_save_settings"><?php wp_nonce_field( 'rmbz_dm_save_settings' ); ?><div class="rmbz-dm-settings"><label class="rmbz-dm-field"><span>Valor por download valido (MT)</span><input type="number" min="0.01" max="1000" step="0.01" name="rate" value="<?php echo esc_attr( rmbz_dm_current_rate() ); ?>" required></label><label class="rmbz-dm-field"><span>Retencao antifraude (dias)</span><input type="number" min="0" max="90" name="hold_days" value="<?php echo absint( get_option( 'rmbz_dm_hold_days', 7 ) ); ?>"></label><label class="rmbz-dm-field"><span>Repeticao por visitante (dias)</span><input type="number" min="1" max="365" name="repeat_days" value="<?php echo absint( get_option( 'rmbz_dm_repeat_days', 30 ) ); ?>"></label><label class="rmbz-dm-field"><span>Limite diario por musica</span><input type="number" min="0" name="daily_music_limit" value="<?php echo absint( get_option( 'rmbz_dm_daily_music_limit', 0 ) ); ?>"><small>0 significa sem limite adicional.</small></label><label class="rmbz-dm-field"><span>Fundo mensal maximo (MT)</span><input type="number" min="0" step="0.01" name="monthly_fund" value="<?php echo esc_attr( (float) get_option( 'rmbz_dm_monthly_fund', 0 ) ); ?>"><small>0 significa sem teto mensal.</small></label><label class="rmbz-dm-field"><span>Nota da nova tarifa</span><input type="text" name="rate_note" placeholder="Ex.: reajuste de agosto"></label></div><div class="rmbz-dm-actions"><label><input type="checkbox" name="enabled" value="1" <?php checked( get_option( 'rmbz_dm_enabled', 1 ) ); ?>> Monetizacao ativa</label><button class="rmbz-dm-btn primary">Guardar configuracoes</button></div></form></section>
            <section class="rmbz-dm-panel"><h2>Liquidacao</h2><p>Credita em lote apenas eventos que terminaram a retencao antifraude.</p><div class="rmbz-dm-help"><strong>Fluxo financeiro</strong><br>Pendente &rarr; disponivel para liquidar &rarr; carteira 1MZ. Cada lote possui chave idempotente e transacao auditavel.</div><form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="rmbz-dm-actions"><input type="hidden" name="action" value="rmbz_dm_manual_settle"><?php wp_nonce_field( 'rmbz_dm_manual_settle' ); ?><button class="rmbz-dm-btn primary">Liquidar ganhos disponiveis</button></form></section>
        </div>

        <section class="rmbz-dm-panel" style="margin-top:16px"><h2>Catalogo monetizavel</h2><div class="rmbz-dm-toolbar"><form class="rmbz-dm-search" method="get"><input type="hidden" name="post_type" value="impulsionamento"><input type="hidden" name="page" value="rmbz-download-monetization"><input type="hidden" name="monet_status" value="<?php echo esc_attr( $filter ); ?>"><input type="search" name="s" value="<?php echo esc_attr( $search ); ?>" placeholder="Pesquisar musica, artista ou telefone"></form><nav class="rmbz-dm-tabs"><?php foreach ( [ 'all' => 'Todas', 'active' => 'Ativas', 'pending' => 'Pendentes', 'inactive' => 'Inativas', 'suspended' => 'Suspensas' ] as $key => $label ): ?><a class="<?php echo $filter === $key ? 'on' : ''; ?>" href="<?php echo esc_url( rmbz_dm_admin_url( [ 'monet_status' => $key, 's' => $search ] ) ); ?>"><?php echo esc_html( $label ); ?></a><?php endforeach; ?></nav></div><div class="rmbz-dm-list"><?php if ( ! $music_rows ): ?><p>Nenhuma musica encontrada.</p><?php endif; ?><?php foreach ( $music_rows as $row ): ?><article class="rmbz-dm-row"><div><div class="rmbz-dm-title"><?php echo esc_html( $row->title_snapshot ?: get_the_title( $row->music_id ) ); ?></div><div class="rmbz-dm-meta"><?php echo esc_html( $row->artist_name ); ?> · Art Track #<?php echo (int) $row->art_track_id; ?> · <?php echo esc_html( $row->account_phone ); ?></div></div><div><span class="rmbz-dm-state <?php echo esc_attr( $row->monet_status ); ?>"><?php echo esc_html( ucfirst( $row->monet_status ) ); ?></span><div class="rmbz-dm-meta">Parceria: <?php echo esc_html( $row->partnership_status ); ?></div></div><form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>"><input type="hidden" name="action" value="rmbz_dm_enrollment_action"><input type="hidden" name="music_id" value="<?php echo (int) $row->music_id; ?>"><?php wp_nonce_field( 'rmbz_dm_enrollment_' . $row->music_id ); ?><select name="monet_status"><option value="inactive" <?php selected( $row->monet_status, 'inactive' ); ?>>Inativa</option><option value="active" <?php selected( $row->monet_status, 'active' ); ?>>Ativa</option><option value="suspended" <?php selected( $row->monet_status, 'suspended' ); ?>>Suspensa</option><option value="archived" <?php selected( $row->monet_status, 'archived' ); ?>>Arquivada</option></select><input type="number" min="0.01" step="0.01" name="rate_override" value="<?php echo $row->rate_override !== null ? esc_attr( $row->rate_override ) : ''; ?>" placeholder="Tarifa propria"><input type="text" name="decision_reason" value="<?php echo esc_attr( (string) $row->decision_reason ); ?>" placeholder="Motivo ou nota"><label class="rmbz-dm-reject"><input type="checkbox" name="reject_pending" value="1"> Rejeitar pendentes</label><button class="rmbz-dm-btn primary">Guardar</button></form></article><?php endforeach; ?></div></section>

        <div class="rmbz-dm-grid"><section class="rmbz-dm-panel"><h2>Eventos recentes</h2><table class="rmbz-dm-table"><thead><tr><th>Data</th><th>Musica</th><th>Estado</th><th>Tarifa</th><th>Motivo</th></tr></thead><tbody><?php foreach ( $events as $event ): ?><tr><td><?php echo esc_html( date_i18n( 'd/m/Y H:i', strtotime( $event->occurred_at ) ) ); ?></td><td><?php echo esc_html( $event->post_title ?: '#' . $event->music_id ); ?></td><td><span class="rmbz-dm-state <?php echo esc_attr( $event->status ); ?>"><?php echo esc_html( $event->status ); ?></span></td><td><?php echo esc_html( number_format_i18n( (float) $event->amount, 2 ) ); ?> MT</td><td><?php echo esc_html( $event->rejection_reason ?: 'Download valido' ); ?></td></tr><?php endforeach; ?></tbody></table></section><section class="rmbz-dm-panel"><h2>Ultimas liquidacoes</h2><table class="rmbz-dm-table"><thead><tr><th>Lote</th><th>Eventos</th><th>Valor</th><th>Estado</th></tr></thead><tbody><?php foreach ( $settlements as $settlement ): ?><tr><td>#<?php echo (int) $settlement->id; ?><div class="rmbz-dm-meta"><?php echo esc_html( $settlement->account_phone ); ?></div></td><td><?php echo (int) $settlement->event_count; ?></td><td><?php echo esc_html( number_format_i18n( (float) $settlement->amount, 2 ) ); ?> MT</td><td><span class="rmbz-dm-state <?php echo esc_attr( $settlement->status ); ?>"><?php echo esc_html( $settlement->status ); ?></span></td></tr><?php endforeach; ?></tbody></table></section></div>

        <section class="rmbz-dm-panel" style="margin-top:16px"><h2>Saldos preservados do sistema antigo</h2><p>Estes valores nao sao creditados automaticamente para evitar pagamento duplicado. Analisa cada registo.</p><?php if ( ! $legacy ): ?><div class="rmbz-dm-help">Nao existem saldos antigos por analisar.</div><?php else: ?><table class="rmbz-dm-table"><thead><tr><th>Utilizador</th><th>Carteira</th><th>Valor</th><th>Decisao</th></tr></thead><tbody><?php foreach ( $legacy as $balance ): ?><tr><td>#<?php echo (int) $balance->wp_user_id; ?></td><td><?php echo esc_html( $balance->account_phone ?: 'Por associar' ); ?></td><td><strong><?php echo esc_html( number_format_i18n( (float) $balance->amount, 2 ) ); ?> MT</strong></td><td><form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" style="display:flex;gap:7px;flex-wrap:wrap"><input type="hidden" name="action" value="rmbz_dm_legacy_balance_action"><input type="hidden" name="legacy_id" value="<?php echo (int) $balance->id; ?>"><?php wp_nonce_field( 'rmbz_dm_legacy_balance_' . $balance->id ); ?><input type="text" name="note" placeholder="Nota da analise"><button class="rmbz-dm-btn primary" name="legacy_decision" value="credit">Creditar carteira</button><button class="rmbz-dm-btn" name="legacy_decision" value="ignore">Ja tratado</button></form></td></tr><?php endforeach; ?></tbody></table><?php endif; ?></section>

        <section class="rmbz-dm-panel rmbz-dm-danger" style="margin-top:16px"><h2>Desativacao e limpeza do sistema antigo</h2><p>O pedido por link, o CPT de reivindicacoes e a monetizacao por gostos foram desativados. A limpeza abaixo remove apenas esse armazenamento legado; analytics, reproducoes, vendas e relatorios continuam intactos.</p><div class="rmbz-dm-help"><strong>Inventario atual</strong><br>Engajamentos: <?php echo (int) $legacy_counts['imz_engagements']; ?> · Resumos mensais: <?php echo (int) $legacy_counts['imz_engagement_monthly']; ?> · Pedidos por link: <?php echo (int) $legacy_counts['claim_posts']; ?> · Metadados: <?php echo (int) $legacy_counts['claim_postmeta']; ?> · Saldos antigos: <?php echo (int) $legacy_counts['legacy_usermeta']; ?><br>Migracao: <?php echo esc_html( is_array( $migration ) ? ( $migration['at'] ?? 'concluida' ) : 'pendente' ); ?> · Limpeza: <?php echo esc_html( $cleaned ?: 'nao executada' ); ?></div><div class="rmbz-dm-actions"><form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>"><input type="hidden" name="action" value="rmbz_dm_run_migration"><?php wp_nonce_field( 'rmbz_dm_run_migration' ); ?><button class="rmbz-dm-btn">Executar migracao novamente</button></form></div><form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" style="margin-top:16px"><input type="hidden" name="action" value="rmbz_dm_cleanup_legacy"><?php wp_nonce_field( 'rmbz_dm_cleanup_legacy' ); ?><label class="rmbz-dm-field"><span>Escreve APAGAR MONETIZACAO ANTIGA</span><input class="rmbz-dm-confirm" type="text" name="confirmation" autocomplete="off"></label><p><label><input type="checkbox" name="acknowledge" value="1"> Confirmo que a migracao foi revista e compreendo que a eliminacao e definitiva.</label></p><button class="rmbz-dm-btn danger" onclick="return confirm('Apagar definitivamente a base antiga de monetizacao?');">Apagar base antiga</button></form></section>
    </div>
    <?php
}

