<?php
// includes/ajax-upload.php
//
// VERSÃO CORRIGIDA — auditoria 2026-04
// Mudanças:
//   [SEC-A1] rmbz_handle_async_audio_upload: adicionado check de sessão custom
//            (rmbz_is_user_logged_in) antes de processar upload. Sem isso,
//            qualquer visitante anónimo podia carregar ficheiros para o servidor.
//   [SEC-A2] Validação MIME passou a usar finfo_file (MIME real do conteúdo),
//            e exige que MIME real + extensão sejam ambos válidos (AND, não OR).
//            Antes bastava 1 dos 2 — ataque clássico ".php.mp3".
//   [SEC-A3] Rate limit por sessão (10 uploads/min) para mitigar enchimento de
//            disco. Reutiliza rmbz_rate_limit() de distribution-security.php.
//   [SEC-A4] Sanitização do nome do ficheiro antes de wp_handle_upload (gera
//            nome random) para evitar colisões e shell-meta no path.
//   [BUG-A5] $movefile['error'] podia gerar warning "Undefined index" no else.
//   [BUG-A6] sanitize_text_field aplicado antes de validar isset/empty causa
//            warning. Padronizado uso de wp_unslash + sanitize.
//   [BUG-A7] $_SESSION usado sem garantir que session foi iniciada
//            (defesa: testar session_status).

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

/**
 * 1. MOTOR AJAX DE UPLOAD ASSÍNCRONO (MÚSICA - MÁX 50MB)
 */
function rmbz_handle_async_audio_upload() {
    // [SEC-A1] Nonce + sessão antes de qualquer outra coisa.
    check_ajax_referer('rmbz_audio_upload_nonce', 'security');

    if ( ! function_exists('rmbz_is_user_logged_in') || ! rmbz_is_user_logged_in() ) {
        wp_send_json_error(['message' => 'Sessão expirada. Faça login antes de carregar a música.'], 401);
    }

    $telemovel = rmbz_get_current_user_telemovel();

    // [SEC-A3] Rate limit anti-DoS de disco.
    if ( function_exists('rmbz_rate_limit') && ! rmbz_rate_limit( 'audio_upload_' . $telemovel, 10 ) ) {
        wp_send_json_error(['message' => 'Demasiados uploads num curto período. Aguarde um minuto.'], 429);
    }

    if ( empty($_FILES['async_audio_file']) || ! isset($_FILES['async_audio_file']['tmp_name']) ) {
        wp_send_json_error(['message' => 'Nenhum ficheiro recebido.']);
    }

    $file = $_FILES['async_audio_file'];

    // Verificar erros do PHP no upload primeiro
    if ( ! empty($file['error']) && $file['error'] !== UPLOAD_ERR_OK ) {
        wp_send_json_error(['message' => 'Erro no upload (código ' . (int)$file['error'] . ').']);
    }

    if ( ! is_uploaded_file( $file['tmp_name'] ) ) {
        wp_send_json_error(['message' => 'Upload inválido.']);
    }

    // Validar Tamanho (50MB)
    if ( (int)$file['size'] > 50 * 1024 * 1024 ) {
        wp_send_json_error(['message' => 'A música excede o limite máximo de 50MB.']);
    }
    if ( (int)$file['size'] < 1024 ) {
        wp_send_json_error(['message' => 'Ficheiro demasiado pequeno ou corrompido.']);
    }

    // [SEC-A2] Validar Extensão E MIME real (AND, não OR).
    $ext = strtolower( pathinfo($file['name'], PATHINFO_EXTENSION) );
    $allowed_ext  = ['mp3', 'wav'];
    $allowed_mime = ['audio/mpeg', 'audio/mp3', 'audio/wav', 'audio/x-wav', 'audio/wave', 'audio/x-pn-wav'];

    if ( ! in_array( $ext, $allowed_ext, true ) ) {
        wp_send_json_error(['message' => 'Extensão inválida. Envie apenas MP3 ou WAV.']);
    }

    // MIME real via fileinfo (não confiar em $file['type'] que vem do browser).
    if ( function_exists('finfo_open') ) {
        $finfo = finfo_open( FILEINFO_MIME_TYPE );
        $real_mime = finfo_file( $finfo, $file['tmp_name'] );
        finfo_close( $finfo );

        if ( ! in_array( $real_mime, $allowed_mime, true ) ) {
            wp_send_json_error(['message' => 'Conteúdo do ficheiro não corresponde a áudio MP3/WAV (detectado: ' . esc_html($real_mime) . ').']);
        }
    }

    // [SEC-A4] Renomear o ficheiro para prevenir colisões e shell-meta.
    $safe_name = 'audio_' . preg_replace('/[^0-9a-z]/', '', strtolower($telemovel)) . '_'
                 . wp_generate_password(16, false, false) . '.' . $ext;
    $file['name'] = $safe_name;

    // Upload via API do WordPress (faz mais validações internas).
    require_once( ABSPATH . 'wp-admin/includes/file.php' );
    $upload_overrides = ['test_form' => false, 'mimes' => ['mp3' => 'audio/mpeg', 'wav' => 'audio/wav']];
    $movefile = wp_handle_upload($file, $upload_overrides);

    if ( $movefile && empty($movefile['error']) && ! empty($movefile['url']) ) {
        wp_send_json_success(['url' => esc_url_raw($movefile['url'])]);
    }

    // [BUG-A5] Mensagem segura mesmo quando 'error' não está definido.
    $err_msg = is_array($movefile) && isset($movefile['error'])
        ? (string) $movefile['error']
        : 'Falha desconhecida ao guardar o ficheiro.';
    error_log('[1MZ] async_audio_upload error: ' . $err_msg);
    wp_send_json_error(['message' => $err_msg]);
}
add_action('wp_ajax_rmbz_async_audio_upload',        'rmbz_handle_async_audio_upload');
add_action('wp_ajax_nopriv_rmbz_async_audio_upload', 'rmbz_handle_async_audio_upload');

/**
 * 2. PROCESSAR O ENVIO FINAL DO FORMULÁRIO (GUARDAR NA BASE DE DADOS)
 */
function rmbz_handle_artist_project_submission() {
    $url = wp_get_referer() ? wp_get_referer() : home_url('/minha-conta/');

    if ( ! function_exists('rmbz_is_user_logged_in') || ! rmbz_is_user_logged_in() ) wp_die('Não autorizado.');
    if ( ! isset( $_POST['_wpnonce'] ) || ! wp_verify_nonce( $_POST['_wpnonce'], 'rmbz_submit_project_nonce' ) ) {
        // [BUG-A7] Garantir sessão antes de escrever em $_SESSION.
        if ( session_status() === PHP_SESSION_NONE && ! headers_sent() ) { session_start(); }
        $_SESSION['rmbz_withdrawal_notice'] = ['error', 'Falha de segurança.'];
        if (function_exists('rmbz_safe_redirect')) { rmbz_safe_redirect($url); } else { wp_redirect($url); exit; }
    }

    if ( session_status() === PHP_SESSION_NONE && ! headers_sent() ) { session_start(); }

    $telemovel = rmbz_get_current_user_telemovel();
    $title    = isset($_POST['music_title'])   ? sanitize_text_field( wp_unslash($_POST['music_title']) )    : '';
    $genre    = isset($_POST['music_genre'])   ? sanitize_text_field( wp_unslash($_POST['music_genre']) )    : '';
    $scenario = isset($_POST['scenario_type']) ? sanitize_text_field( wp_unslash($_POST['scenario_type']) )  : '';
    $pitch    = isset($_POST['project_pitch']) ? sanitize_textarea_field( wp_unslash($_POST['project_pitch']) ) : '';

    // Lê a URL que foi gerada pelo AJAX!
    $audio_url = isset($_POST['music_file_url']) ? esc_url_raw( wp_unslash($_POST['music_file_url']) ) : '';

    // Verificação extra: a URL tem de pertencer ao próprio site (evita gravar URLs externas/maliciosas).
    if ( $audio_url ) {
        $home = wp_parse_url( home_url() );
        $up   = wp_parse_url( $audio_url );
        if ( empty($up['host']) || empty($home['host']) || strcasecmp($up['host'], $home['host']) !== 0 ) {
            $_SESSION['rmbz_withdrawal_notice'] = ['error', 'URL do ficheiro inválida.'];
            if (function_exists('rmbz_safe_redirect')) { rmbz_safe_redirect($url); } else { wp_redirect($url); exit; }
        }
    }

    if ( empty($title) || empty($audio_url) || empty($scenario) ) {
        $_SESSION['rmbz_withdrawal_notice'] = ['error', 'Preencha todos os campos obrigatórios e aguarde o upload da música.'];
        if (function_exists('rmbz_safe_redirect')) { rmbz_safe_redirect($url); } else { wp_redirect($url); exit; }
    }

    global $wpdb;

    // Insere a submissão inicial
    $submissions_table = $wpdb->prefix . 'rmbz_artist_submissions';
    $wpdb->insert(
        $submissions_table,
        [
            'artist_telemovel' => $telemovel,
            'music_title'      => $title,
            'music_file_url'   => $audio_url,
            'music_genre'      => $genre,
            'scenario_type'    => $scenario,
            'review_status'    => 'pendente',
            'submission_date'  => current_time('mysql')
        ],
        ['%s', '%s', '%s', '%s', '%s', '%s', '%s']
    );

    $submission_id = $wpdb->insert_id;

    if ( $submission_id ) {
        $projects_table = $wpdb->prefix . 'rmbz_artist_projects';
        $wpdb->insert(
            $projects_table,
            [
                'submission_id'      => $submission_id,
                'artist_telemovel'   => $telemovel,
                'project_title'      => $title,
                'project_pitch'      => $pitch,
                'demo_mp3_url'       => $audio_url,
                'scenario_type'      => $scenario,
                'production_status'  => 'pre-production',
                'contract_date'      => current_time('mysql')
            ],
            ['%d', '%s', '%s', '%s', '%s', '%s', '%s', '%s']
        );
        $_SESSION['rmbz_withdrawal_notice'] = ['success', 'Projeto submetido com sucesso! A nossa equipa vai analisar o seu som.'];
    } else {
        $_SESSION['rmbz_withdrawal_notice'] = ['error', 'Erro ao guardar o projeto. Tente novamente.'];
    }

    if (function_exists('rmbz_safe_redirect')) { rmbz_safe_redirect($url); } else { wp_redirect($url); exit; }
}
add_action('admin_post_rmbz_submit_project', 'rmbz_handle_artist_project_submission');
