<?php
/**
 * [1.5.399] GERADOR DE CONTRATO EM PDF — sem dependências externas.
 *
 * Gera o "Contrato de Produção de Videoclipe" (PDF/A4) pré-preenchido.
 * Os valores preenchidos (música, nível, valor, B.I., data, assinaturas)
 * são desenhados em Times-Italic — aspeto de escrita à mão sobre o texto
 * impresso (Helvetica). O admin revê/edita tudo num MODAL antes de gerar,
 * incluindo o N.º do B.I. e quem assina pela 1MZ (assinatura "manuscrita").
 */

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

/* ====================================================================== */
/* MOTOR PDF (cru) — suporta segmentos com fontes mistas                   */
/*   Fontes: N = Helvetica · B = Helvetica-Bold · H = Times-Italic (mão)   */
/* ====================================================================== */

function rmbz_cpdf_enc( $t ) {
    $s = @iconv( 'UTF-8', 'Windows-1252//TRANSLIT', (string) $t );
    if ( $s === false ) $s = preg_replace( '/[^\x20-\x7E]/', '?', (string) $t );
    return str_replace( [ '\\', '(', ')' ], [ '\\\\', '\\(', '\\)' ], $s );
}

function rmbz_cpdf_charw( $ch, $bold ) {
    if ( $ch === '—' || $ch === '–' ) return 1000; // travessões largos
    if ( strpos( "iíìîjl.,;:!|' ", $ch ) !== false ) return $bold ? 300 : 278;
    if ( strpos( 'ftr-()[]"', $ch ) !== false ) return $bold ? 390 : 333;
    if ( strpos( 'mwMW', $ch ) !== false ) return $bold ? 940 : 890;
    // Maiúsculas: usar a classe LARGA (G/O/D/H/N/U ~722-778) — subestimar
    // fazia as palavras seguintes colarem.
    if ( ctype_upper( $ch ) || strpos( 'ÁÀÃÂÉÊÍÓÕÔÚÇ', $ch ) !== false ) return $bold ? 778 : 730;
    if ( ctype_digit( $ch ) ) return 556;
    return $bold ? 585 : 560;
}

function rmbz_cpdf_textw( $t, $size, $font = 'N' ) {
    // H = Times-BoldItalic (manuscrito a negrito) → usa a tabela bold.
    $bold = $font === 'B' || $font === 'H';
    $w = 0;
    $chars = preg_split( '//u', (string) $t, -1, PREG_SPLIT_NO_EMPTY ) ?: [];
    foreach ( $chars as $ch ) $w += rmbz_cpdf_charw( $ch, $bold );
    return $w * $size / 1000.0;
}

/**
 * Constrói um PDF a partir de blocos:
 *   [ texto|segmentos, fonte N|B|H, tamanho, espaço-depois, align L|C ]
 * "segmentos" = lista de [string, fonte] para misturar impresso + manuscrito.
 * @return string bytes do PDF
 */
function rmbz_cpdf_render( array $blocks, $footer_text = '' ) {
    $PW = 595.28; $PH = 841.89;           // A4
    $ML = 56.0; $MR = 56.0; $MT = 64.0; $MB = 64.0;
    $maxw = $PW - $ML - $MR;

    $pages = []; $cur = ''; $y = $PH - $MT;
    $newpage = function () use ( &$pages, &$cur, &$y, $PH, $MT ) {
        if ( $cur !== '' ) $pages[] = $cur;
        $cur = ''; $y = $PH - $MT;
    };
    $fontRef = fn( $f ) => $f === 'B' ? 'F2' : ( $f === 'H' ? 'F3' : 'F1' );

    foreach ( $blocks as $blk ) {
        list( $text, $font, $size, $after, $align ) = array_pad( $blk, 5, 'L' );

        // Tokenizar (palavra + fonte) — aceita string simples ou segmentos.
        $tokens = [];
        $segs = is_array( $text ) ? $text : [ [ (string) $text, $font ] ];
        foreach ( $segs as $seg ) {
            $st = (string) $seg[0];
            $sf = isset( $seg[1] ) ? $seg[1] : $font;
            foreach ( preg_split( '/\s+/u', trim( $st ) ) as $w ) {
                if ( $w !== '' ) $tokens[] = [ $w, $sf ];
            }
        }
        if ( ! $tokens ) $tokens = [ [ '', $font ] ];

        $spaceW = fn( $f ) => rmbz_cpdf_textw( ' ', $size, $f );

        // Quebra de linha por largura acumulada.
        $lines = []; $lcur = []; $lw = 0;
        foreach ( $tokens as $tk ) {
            $w = rmbz_cpdf_textw( $tk[0], $size, $tk[1] );
            $add = $lcur ? $spaceW( end( $lcur )[1] ) + $w : $w;
            if ( $lcur && ( $lw + $add ) > $maxw ) {
                $lines[] = [ $lcur, $lw ];
                $lcur = [ $tk ]; $lw = $w;
            } else {
                $lw += $add; $lcur[] = $tk;
            }
        }
        if ( $lcur ) $lines[] = [ $lcur, $lw ];

        $lh = $size * 1.35;
        foreach ( $lines as $line ) {
            list( $ltokens, $lineW ) = $line;
            if ( $y - $lh < $MB ) $newpage();
            $x = $align === 'C' ? ( $PW - $lineW ) / 2 : $ML;
            foreach ( $ltokens as $tk ) {
                list( $word, $f ) = $tk;
                if ( $word !== '' ) {
                    // Manuscrito ligeiramente maior — parece caneta sobre a linha.
                    $sz = $f === 'H' ? $size * 1.08 : $size;
                    $cur .= sprintf(
                        "BT /%s %.2f Tf 1 0 0 1 %.2f %.2f Tm (%s) Tj ET\n",
                        $fontRef( $f ), $sz, $x, $y - $size, rmbz_cpdf_enc( $word )
                    );
                }
                $x += rmbz_cpdf_textw( $word, $size, $f ) + $spaceW( $f );
            }
            $y -= $lh;
        }
        $y -= (float) $after;
    }
    if ( $cur !== '' ) $pages[] = $cur;

    $n = count( $pages );
    if ( $footer_text !== '' ) {
        foreach ( $pages as $i => &$c ) {
            $foot = 'Página ' . ( $i + 1 ) . ' de ' . $n . ' — ' . $footer_text;
            $x = ( $PW - rmbz_cpdf_textw( $foot, 8 ) ) / 2;
            $c .= sprintf( "BT /F1 8 Tf 1 0 0 1 %.2f %.2f Tm (%s) Tj ET\n", $x, 34, rmbz_cpdf_enc( $foot ) );
        }
        unset( $c );
    }

    $objs = [];
    $objs[1] = '<< /Type /Catalog /Pages 2 0 R >>';
    $objs[3] = '<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica /Encoding /WinAnsiEncoding >>';
    $objs[4] = '<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding >>';
    $objs[5] = '<< /Type /Font /Subtype /Type1 /BaseFont /Times-BoldItalic /Encoding /WinAnsiEncoding >>';
    $kids = []; $objn = 6;
    foreach ( $pages as $content ) {
        $pid = $objn++; $cid = $objn++;
        $objs[ $pid ] = "<< /Type /Page /Parent 2 0 R /MediaBox [0 0 {$PW} {$PH}] /Resources << /Font << /F1 3 0 R /F2 4 0 R /F3 5 0 R >> >> /Contents {$cid} 0 R >>";
        $objs[ $cid ] = 'stream:' . $content;
        $kids[] = "{$pid} 0 R";
    }
    $objs[2] = '<< /Type /Pages /Kids [' . implode( ' ', $kids ) . '] /Count ' . count( $kids ) . ' >>';

    ksort( $objs );
    $pdf = "%PDF-1.4\n%\xE2\xE3\xCF\xD3\n";
    $offsets = [];
    foreach ( $objs as $num => $body ) {
        $offsets[ $num ] = strlen( $pdf );
        if ( strpos( $body, 'stream:' ) === 0 ) {
            $st = substr( $body, 7 );
            $pdf .= "{$num} 0 obj\n<< /Length " . strlen( $st ) . " >>\nstream\n{$st}endstream\nendobj\n";
        } else {
            $pdf .= "{$num} 0 obj\n{$body}\nendobj\n";
        }
    }
    $xref = strlen( $pdf );
    $max = max( array_keys( $objs ) );
    $pdf .= "xref\n0 " . ( $max + 1 ) . "\n0000000000 65535 f \n";
    for ( $i = 1; $i <= $max; $i++ ) {
        $pdf .= isset( $offsets[ $i ] ) ? sprintf( "%010d 00000 n \n", $offsets[ $i ] ) : "0000000000 65535 f \n";
    }
    $pdf .= "trailer\n<< /Size " . ( $max + 1 ) . " /Root 1 0 R >>\nstartxref\n{$xref}\n%%EOF\n";
    return $pdf;
}

/* ====================================================================== */
/* CONTRATO DE PRODUÇÃO DE VIDEOCLIPE                                      */
/* ====================================================================== */

/**
 * Constrói os bytes do contrato pré-preenchido.
 * $d: artist_name, artist_tel, music, level, value, feat, city,
 *     day, month_name, year, bi_number, signer_name
 * Vazios → linha em branco (underscores) para preencher à mão.
 */
function rmbz_contract_pdf_build( array $d ) {
    $d += [ 'bi_number' => '', 'signer_name' => '', 'feat' => '', 'city' => 'Maputo' ];
    $blank = fn( $n ) => str_repeat( '_', $n );
    // Valor manuscrito ou linha em branco.
    $hOr = fn( $v, $n ) => $v !== '' ? [ $v, 'H' ] : [ $blank( $n ), 'N' ];
    $site = 'Plataforma 1MZ For Artists — ' . preg_replace( '#^https?://#', '', home_url() );

    $b = [];
    $B = function ( $t, $f = 'N', $s = 10, $after = 6, $al = 'L' ) use ( &$b ) {
        $b[] = [ $t, $f, $s, $after, $al ];
    };

    $B( '1MZ RECORDS', 'B', 20, 2, 'C' );
    $B( $site, 'N', 9, 14, 'C' );
    $B( 'CONTRATO DE PRODUÇÃO DE VIDEOCLIPE', 'B', 14, 4, 'C' );
    $B( '(Serviço "Ganhar Vídeo")', 'N', 10, 16, 'C' );

    $B( 'ENTRE:', 'B', 10, 4 );
    $B( '1MZ RECORDS, editora e gestora de artistas, operadora da plataforma 1MZ For Artists, doravante designada "1MZ" ou "PRODUTORA";', 'N', 10, 8 );
    $B( 'E:', 'B', 10, 4 );
    $rmbz_entre = [
        [ strtoupper( $d['artist_name'] ) . ',', 'H' ],
        [ 'artista registado na plataforma 1MZ For Artists com a conta n.º', 'N' ],
    ];
    if ( $d['bi_number'] !== '' ) {
        $rmbz_entre[] = [ $d['artist_tel'] . ',', 'H' ];
        $rmbz_entre[] = [ 'portador do documento de identificação n.º', 'N' ];
        $rmbz_entre[] = [ $d['bi_number'] . ',', 'H' ];
    } else {
        $rmbz_entre[] = [ $d['artist_tel'] . ',', 'H' ];
    }
    $rmbz_entre[] = [ 'doravante designado "ARTISTA";', 'N' ];
    $B( $rmbz_entre, 'N', 10, 8 );
    $B( 'É celebrado o presente Contrato de Produção de Videoclipe, que se rege pelas cláusulas seguintes:', 'N', 10, 14 );

    $B( 'CLÁUSULA 1.ª — OBJETO', 'B', 10, 4 );
    $B( [
        [ '1.1. A 1MZ obriga-se a produzir um videoclipe para a música', 'N' ],
        $d['music'] !== '' ? [ '"' . $d['music'] . '"', 'H' ] : [ '"' . $blank( 32 ) . '"', 'N' ],
        [ 'do ARTISTA, no nível/cenário contratado', 'N' ],
        $d['level'] !== '' ? [ '"' . $d['level'] . '",', 'H' ] : [ '"' . $blank( 20 ) . '",', 'N' ],
        [ 'conforme a candidatura aprovada na plataforma 1MZ For Artists.', 'N' ],
    ], 'N', 10, 4 );
    $B( '1.2. O conceito criativo (Pitch da Produção), o orçamento e a localização das filmagens são os definidos e aceites na plataforma, que fazem parte integrante deste contrato.', 'N', 10, 10 );

    $B( 'CLÁUSULA 2.ª — VERIFICAÇÃO DE IDENTIDADE (KYC) E ASSINATURA', 'B', 10, 4 );
    $B( '2.1. O ARTISTA deve validar a sua identidade (documento oficial com fotografia) e assinar o contrato na plataforma.', 'N', 10, 4 );
    $B( '2.2. Este contrato só produz efeitos após a aprovação do KYC pela equipa 1MZ.', 'N', 10, 10 );

    $B( 'CLÁUSULA 3.ª — VALOR E PAGAMENTOS', 'B', 10, 4 );
    $B( [
        [ '3.1. O valor do cenário contratado é de', 'N' ],
        $hOr( $d['value'], 12 ),
        [ 'MT, pago através da carteira do ARTISTA na plataforma, no todo ou conforme o plano de itens do orçamento acordado.', 'N' ],
    ], 'N', 10, 4 );
    $B( '3.2. Itens do orçamento assumidos pelo ARTISTA fora da plataforma são da sua exclusiva responsabilidade.', 'N', 10, 10 );

    $B( 'CLÁUSULA 4.ª — SUBSCRIÇÃO ATIVA E MULTA POR ATRASO', 'B', 10, 4 );
    $B( '4.1. Durante toda a produção (desde a aprovação até à entrega), o ARTISTA deve manter uma subscrição VIP ativa que inclua o serviço "Ganhar Vídeo".', 'N', 10, 4 );
    $B( '4.2. Se a subscrição expirar com o projeto em produção, aplica-se automaticamente uma multa por atraso de 15 MT por hora, e a equipa suspende os trabalhos até à regularização (renovação do VIP e pagamento da multa acumulada).', 'N', 10, 4 );
    $B( '4.3. A multa não desaparece com a simples renovação do VIP — o valor acumulado permanece devido até ser pago.', 'N', 10, 10 );

    $B( 'CLÁUSULA 5.ª — PRAZOS E DATAS DE GRAVAÇÃO', 'B', 10, 4 );
    $B( '5.1. As datas de gravação são propostas pela equipa e confirmadas (ou contrapropostas) pelo ARTISTA na plataforma.', 'N', 10, 4 );
    $B( '5.2. A falta de confirmação dentro do prazo indicado pode levar ao cancelamento da candidatura por prazo, nos termos das regras da plataforma.', 'N', 10, 10 );

    $B( 'CLÁUSULA 6.ª — DECLARAÇÕES E DIREITOS', 'B', 10, 4 );
    $B( '6.1. O ARTISTA declara que é o autor/titular da música e que esta não possui videoclipe oficial.', 'N', 10, 4 );
    $B( '6.2. O ARTISTA autoriza a 1MZ a utilizar excertos do videoclipe e imagens da produção para fins promocionais da plataforma e do próprio ARTISTA.', 'N', 10, 4 );
    $B( '6.3. Os restantes direitos sobre o videoclipe seguem o acordado entre as partes na plataforma.', 'N', 10, 10 );

    $B( 'CLÁUSULA 7.ª — PARTICIPAÇÕES (FEAT)', 'B', 10, 4 );
    if ( $d['feat'] !== '' ) {
        $B( [
            [ '7.1. A música conta com a participação declarada de', 'N' ],
            [ $d['feat'] . ',', 'H' ],
            [ 'registada na candidatura apenas para efeitos de registo/acompanhamento — não altera pagamentos nem este contrato.', 'N' ],
        ], 'N', 10, 4 );
    } else {
        $B( '7.1. As participações de outros artistas declaradas na candidatura constam apenas para registo/acompanhamento e não alteram pagamentos nem este contrato.', 'N', 10, 4 );
    }
    $B( '7.2. É da responsabilidade do ARTISTA obter as autorizações necessárias dos participantes.', 'N', 10, 10 );

    $B( 'CLÁUSULA 8.ª — TRANSFERÊNCIA DO PROJETO', 'B', 10, 4 );
    $B( '8.1. Caso se verifique que a música pertence a outro artista, aplica-se o processo de transferência de projeto da plataforma (com aceitação do ARTISTA ou por decisão fundamentada da equipa).', 'N', 10, 4 );
    $B( '8.2. Concluída a transferência, este contrato e o KYC do ARTISTA são anulados, devendo o novo titular assinar novo contrato.', 'N', 10, 10 );

    $B( 'CLÁUSULA 9.ª — ENTREGA', 'B', 10, 4 );
    $B( '9.1. O vídeo final é disponibilizado ao ARTISTA através da plataforma, e a publicação segue o plano acordado (YouTube/redes da 1MZ e/ou do ARTISTA).', 'N', 10, 10 );

    $B( 'CLÁUSULA 10.ª — INCUMPRIMENTO E RESCISÃO', 'B', 10, 4 );
    $B( '10.1. O incumprimento grave de qualquer cláusula confere à parte lesada o direito de rescindir o contrato, sem prejuízo dos valores já devidos.', 'N', 10, 10 );

    $B( 'CLÁUSULA 11.ª — COMUNICAÇÕES', 'B', 10, 4 );
    $B( '11.1. As comunicações oficiais entre as partes fazem-se através da plataforma (chat do projeto e notificações), do email e do número de conta indicados.', 'N', 10, 10 );

    $B( 'CLÁUSULA 12.ª — LEI APLICÁVEL E FORO', 'B', 10, 4 );
    $B( [
        [ '12.1. Este contrato rege-se pela lei moçambicana. Para qualquer litígio é competente o foro da cidade de', 'N' ],
        [ $d['city'] . ',', 'H' ],
        [ 'com renúncia expressa a qualquer outro.', 'N' ],
    ], 'N', 10, 16 );

    $B( [
        [ 'Feito em dois exemplares de igual valor, em', 'N' ],
        [ $d['city'] . ',', 'H' ],
        [ 'aos', 'N' ],
        [ $d['day'], 'H' ],
        [ 'de', 'N' ],
        [ $d['month_name'], 'H' ],
        [ 'de', 'N' ],
        [ $d['year'] . '.', 'H' ],
    ], 'N', 10, 16 );

    // ── Assinatura 1MZ: nome "manuscrito" grande sobre a linha. ──
    $B( 'PELA 1MZ RECORDS:', 'B', 10, 10 );
    if ( $d['signer_name'] !== '' ) {
        $B( $d['signer_name'], 'H', 21, 0 );
        $B( str_repeat( '_', 41 ), 'N', 10, 3 );
        $B( [ [ 'Nome:', 'N' ], [ $d['signer_name'], 'H' ] ], 'N', 10, 12 );
    } else {
        $B( ' ', 'N', 16, 3 );
        $B( str_repeat( '_', 41 ), 'N', 10, 3 );
        $B( 'Nome: ' . str_repeat( '_', 36 ), 'N', 10, 12 );
    }

    $B( 'O ARTISTA:', 'B', 10, 16 );
    $B( str_repeat( '_', 41 ), 'N', 10, 4 );
    $B( [ [ strtoupper( $d['artist_name'] ) . ' — Conta: ' . $d['artist_tel'], 'H' ] ], 'N', 10, 4 );
    $B( [
        [ 'Documento de identificação n.º:', 'N' ],
        $hOr( $d['bi_number'], 23 ),
    ], 'N', 10, 0 );

    $footer = 'Contrato 1MZ Records · ' . $d['artist_name'] . ' (' . $d['artist_tel'] . ')';
    return rmbz_cpdf_render( $b, $footer );
}

/**
 * Gera o contrato para um projeto (com overrides do modal), grava em uploads
 * e anexa ao projeto (fluxo normal: flags limpas + email/push/sino ao artista).
 *
 * @return array [ 'success'=>bool, 'message'=>string, 'url'=>string ]
 */
function rmbz_contract_generate_for_project( $project_id, array $overrides = [] ) {
    global $wpdb;
    $p = $wpdb->get_row( $wpdb->prepare(
        "SELECT p.*, w.user_nome FROM {$wpdb->prefix}rmbz_artist_projects p
         LEFT JOIN {$wpdb->prefix}rmbz_wallets w ON w.user_telemovel = p.artist_telemovel
         WHERE p.id=%d",
        (int) $project_id
    ) );
    if ( ! $p ) return [ 'success' => false, 'message' => 'Projeto não encontrado.', 'url' => '' ];

    $extra = ! empty( $p->extra_data ) ? json_decode( $p->extra_data, true ) : [];
    if ( ! is_array( $extra ) ) $extra = [];

    $levels = [ 'basic' => 'BÁSICO', 'professional' => 'PROFISSIONAL', 'cinema' => 'CINEMA' ];
    $feat = '';
    if ( ! empty( $extra['feat']['name'] ) ) {
        $feat = $extra['feat']['name'];
        if ( ! empty( $extra['feat']['has_account'] ) && ! empty( $extra['feat']['tel'] ) ) {
            $feat .= ' (conta ' . $extra['feat']['tel'] . ')';
        }
    }
    $months = [ 1 => 'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro' ];
    $ts = current_time( 'timestamp' );

    $defaults = [
        'artist_name' => (string) ( $p->user_nome ?: ( $extra['artist_name'] ?? $p->artist_telemovel ) ),
        'artist_tel'  => (string) $p->artist_telemovel,
        'music'       => (string) $p->project_title,
        'level'       => $levels[ (string) $p->scenario_type ] ?? strtoupper( (string) $p->scenario_type ),
        'value'       => (float) $p->scenario_cost > 0 ? number_format( (float) $p->scenario_cost, 2, ',', '.' ) : '',
        'feat'        => $feat,
        'city'        => 'Maputo',
        'day'         => (string) (int) wp_date( 'j', $ts ),
        'month_name'  => $months[ (int) wp_date( 'n', $ts ) ],
        'year'        => (string) wp_date( 'Y', $ts ),
        'bi_number'   => '',
        'signer_name' => '',
    ];
    // Overrides do modal (só chaves conhecidas; strings saneadas).
    foreach ( [ 'artist_name', 'artist_tel', 'music', 'level', 'value', 'city', 'bi_number', 'signer_name' ] as $k ) {
        if ( isset( $overrides[ $k ] ) ) {
            $defaults[ $k ] = sanitize_text_field( (string) $overrides[ $k ] );
        }
    }

    $pdf = rmbz_contract_pdf_build( $defaults );

    // Gravar como RASCUNHO em uploads/rmbz-contracts/ — o artista NÃO é
    // notificado agora; o admin pré-visualiza e só envia se concordar.
    $up = wp_upload_dir();
    $dir = trailingslashit( $up['basedir'] ) . 'rmbz-contracts';
    if ( ! is_dir( $dir ) ) wp_mkdir_p( $dir );
    $fname = sprintf( 'rascunho-contrato-%d-%s.pdf', (int) $project_id, wp_date( 'Ymd-His', $ts ) );
    if ( false === file_put_contents( $dir . '/' . $fname, $pdf ) ) {
        return [ 'success' => false, 'message' => 'Falha a gravar o PDF no servidor.', 'url' => '' ];
    }
    $url = trailingslashit( $up['baseurl'] ) . 'rmbz-contracts/' . $fname;

    // [1.5.406] S3 ligado → o PDF vai para o bucket (URL do bucket/CDN).
    if ( function_exists( 'rmbz_s3_maybe_offload' ) ) {
        $s3_url = rmbz_s3_maybe_offload( $dir . '/' . $fname, 'application/pdf' );
        if ( $s3_url !== '' ) $url = $s3_url;
    }

    // Apagar rascunho anterior (se existir) e guardar o novo no extra_data.
    if ( ! empty( $extra['contract_draft']['url'] ) && function_exists( 'rmbz_destruir_ficheiro_fisico' ) ) {
        rmbz_destruir_ficheiro_fisico( $extra['contract_draft']['url'] );
    }
    $extra['contract_draft'] = [
        'url'        => $url,
        'created_at' => current_time( 'mysql' ),
    ];
    $wpdb->update( $wpdb->prefix . 'rmbz_artist_projects', [ 'extra_data' => wp_json_encode( $extra ) ], [ 'id' => (int) $project_id ] );

    if ( function_exists( 'rmbz_pchat_append_change_log' ) ) {
        $who = function_exists( 'rmbz_pchat_current_admin_who' ) ? rmbz_pchat_current_admin_who() : 'admin';
        rmbz_pchat_append_change_log( (int) $project_id, [
            'who'  => $who,
            'what' => '📄 Gerou um RASCUNHO do contrato (à espera de revisão)',
        ] );
    }

    return [ 'success' => true, 'message' => 'Rascunho gerado — revê a pré-visualização e envia só se concordares.', 'url' => $url ];
}

/* ====================================================================== */
/* Handler do botão/modal no admin (POST com campos editáveis)             */
/* ====================================================================== */

add_action( 'admin_post_rmbz_generate_project_contract', function () {
    if ( ! current_user_can( 'manage_options' ) ) wp_die( 'Sem permissão.' );
    $project_id = isset( $_POST['project_id'] ) ? (int) $_POST['project_id'] : 0;
    check_admin_referer( 'rmbz_generate_contract_' . $project_id );

    $overrides = [];
    foreach ( [ 'artist_name', 'artist_tel', 'music', 'level', 'value', 'city', 'bi_number', 'signer_name' ] as $k ) {
        if ( isset( $_POST[ 'c_' . $k ] ) ) {
            $overrides[ $k ] = wp_unslash( (string) $_POST[ 'c_' . $k ] );
        }
    }

    $res = rmbz_contract_generate_for_project( $project_id, $overrides );
    wp_redirect( add_query_arg( 'msg', rawurlencode( $res['message'] ),
        admin_url( 'admin.php?page=rmbz-projetos&action=edit&id=' . $project_id ) ) );
    exit;
} );

/**
 * [1.5.399] Ler o rascunho pendente do projeto (ou null).
 */
function rmbz_contract_draft_get( $project_id ) {
    global $wpdb;
    $extra = $wpdb->get_var( $wpdb->prepare(
        "SELECT extra_data FROM {$wpdb->prefix}rmbz_artist_projects WHERE id=%d", (int) $project_id
    ) );
    $extra = $extra ? json_decode( $extra, true ) : [];
    return ( is_array( $extra ) && ! empty( $extra['contract_draft']['url'] ) ) ? $extra['contract_draft'] : null;
}

/**
 * [1.5.402] ✅ CONCORDO — núcleo partilhado (WP admin + app admin): envia o
 * rascunho ao artista (anexa + email/push/sino, apaga contrato antigo).
 * @return array [ 'success'=>bool, 'message'=>string ]
 */
function rmbz_contract_draft_send_core( $project_id ) {
    $project_id = (int) $project_id;
    $draft = rmbz_contract_draft_get( $project_id );
    if ( ! $draft ) {
        return [ 'success' => false, 'message' => 'Não há rascunho para enviar — gera primeiro.' ];
    }

    global $wpdb;
    $extra_raw = $wpdb->get_var( $wpdb->prepare( "SELECT extra_data FROM {$wpdb->prefix}rmbz_artist_projects WHERE id=%d", $project_id ) );
    $extra = $extra_raw ? json_decode( $extra_raw, true ) : [];
    if ( ! is_array( $extra ) ) $extra = [];

    // Apagar o contrato anterior (poupar espaço) e limpar o rascunho.
    if ( ! empty( $extra['contract_url'] ) && function_exists( 'rmbz_destruir_ficheiro_fisico' ) ) {
        rmbz_destruir_ficheiro_fisico( $extra['contract_url'] );
    }
    unset( $extra['contract_draft'] );
    $wpdb->update( $wpdb->prefix . 'rmbz_artist_projects', [ 'extra_data' => wp_json_encode( $extra ) ], [ 'id' => $project_id ] );

    $msg = function_exists( 'rmbz_project_contract_attach_url' )
        ? rmbz_project_contract_attach_url( $project_id, (string) $draft['url'] )
        : 'Contrato anexado.';

    if ( function_exists( 'rmbz_pchat_append_change_log' ) ) {
        $who = function_exists( 'rmbz_pchat_current_admin_who' ) ? rmbz_pchat_current_admin_who() : 'admin';
        rmbz_pchat_append_change_log( $project_id, [
            'who'  => $who,
            'what' => '📄 Aprovou o rascunho e ENVIOU o contrato ao artista',
        ] );
    }
    return [ 'success' => true, 'message' => (string) $msg ];
}

/**
 * [1.5.402] ✗ REJEITAR — núcleo partilhado: apaga o rascunho (nada é enviado).
 * @return array [ 'success'=>bool, 'message'=>string ]
 */
function rmbz_contract_draft_discard_core( $project_id ) {
    $project_id = (int) $project_id;
    $draft = rmbz_contract_draft_get( $project_id );
    if ( $draft ) {
        if ( function_exists( 'rmbz_destruir_ficheiro_fisico' ) ) {
            rmbz_destruir_ficheiro_fisico( (string) $draft['url'] );
        }
        global $wpdb;
        $extra_raw = $wpdb->get_var( $wpdb->prepare( "SELECT extra_data FROM {$wpdb->prefix}rmbz_artist_projects WHERE id=%d", $project_id ) );
        $extra = $extra_raw ? json_decode( $extra_raw, true ) : [];
        if ( is_array( $extra ) ) {
            unset( $extra['contract_draft'] );
            $wpdb->update( $wpdb->prefix . 'rmbz_artist_projects', [ 'extra_data' => wp_json_encode( $extra ) ], [ 'id' => $project_id ] );
        }
    }
    return [ 'success' => true, 'message' => 'Rascunho rejeitado e apagado — nada foi enviado ao artista.' ];
}

// ✅ CONCORDO — envia o rascunho ao artista (anexa + email/push/sino).
add_action( 'admin_post_rmbz_contract_draft_send', function () {
    if ( ! current_user_can( 'manage_options' ) ) wp_die( 'Sem permissão.' );
    $project_id = isset( $_GET['project_id'] ) ? (int) $_GET['project_id'] : 0;
    check_admin_referer( 'rmbz_contract_draft_send_' . $project_id );
    $res = rmbz_contract_draft_send_core( $project_id );
    wp_redirect( add_query_arg( 'msg', rawurlencode( (string) $res['message'] ),
        admin_url( 'admin.php?page=rmbz-projetos&action=edit&id=' . $project_id ) ) ); exit;
} );

// ✗ REJEITAR — apaga o rascunho (nada é enviado ao artista).
add_action( 'admin_post_rmbz_contract_draft_discard', function () {
    if ( ! current_user_can( 'manage_options' ) ) wp_die( 'Sem permissão.' );
    $project_id = isset( $_GET['project_id'] ) ? (int) $_GET['project_id'] : 0;
    check_admin_referer( 'rmbz_contract_draft_discard_' . $project_id );
    $res = rmbz_contract_draft_discard_core( $project_id );
    wp_redirect( add_query_arg( 'msg', rawurlencode( (string) $res['message'] ),
        admin_url( 'admin.php?page=rmbz-projetos&action=edit&id=' . $project_id ) ) ); exit;
} );
