<?php
/**
 * 1MZ For Artists — Licensing (SOMAS) Endpoints
 *
 * Expõe o sistema de licenciamento musical SOMAS via REST. Reutiliza
 * 100% da lógica em distribution-licensing.php — funções existentes:
 *
 *   - rmbz_licensing_is_enabled()
 *   - rmbz_licensing_get_artist_somas_registration($tel)
 *   - rmbz_licensing_artist_has_approved_somas($tel)
 *   - rmbz_licensing_get_release_license($release_id)
 *   - rmbz_licensing_get_registration_price()
 *   - rmbz_licensing_get_per_track_price()
 *   - rmbz_licensing_get_existing_member_price()
 *   - rmbz_licensing_count_release_tracks($release_id)
 *   - rmbz_licensing_validate_coupon(...)
 *   - rmbz_licensing_submit_somas_registration(...)
 *   - rmbz_licensing_submit_existing_member(...)
 *   - rmbz_licensing_submit_release_license(...)
 *
 * ENDPOINTS:
 *   GET  /licensing/status                    — estado SOMAS + preços + flags
 *   POST /uploads/somas-document              — upload BI ou cartão SOMAS
 *   POST /licensing/somas/register-new        — submeter registo (caminho A)
 *   POST /licensing/somas/register-existing   — submeter como já-membro (caminho B)
 *   POST /licensing/coupon/validate           — validar cupão (preview)
 *   GET  /releases/{id}/license               — licença actual da release (ou null)
 *   POST /releases/{id}/license               — pedir licenciamento da release
 *
 * @package 1MZ_For_Artists
 * @since 1.6.21
 */

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

if ( ! defined( 'RMBZ_API_LICENSING_VERSION' ) ) {
    define( 'RMBZ_API_LICENSING_VERSION', '1.6.21.1' );
}

add_action( 'rest_api_init', 'rmbz_api_register_licensing_routes' );

function rmbz_api_register_licensing_routes() {
    register_rest_route( RMBZ_API_NAMESPACE, '/licensing/status', [
        'methods'             => 'GET',
        'callback'            => 'rmbz_api_handle_licensing_status',
        'permission_callback' => 'rmbz_api_require_auth',
    ] );

    register_rest_route( RMBZ_API_NAMESPACE, '/uploads/somas-document', [
        'methods'             => 'POST',
        'callback'            => 'rmbz_api_handle_upload_somas_document',
        'permission_callback' => 'rmbz_api_require_auth',
    ] );

    register_rest_route( RMBZ_API_NAMESPACE, '/licensing/somas/register-new', [
        'methods'             => 'POST',
        'callback'            => 'rmbz_api_handle_register_somas_new',
        'permission_callback' => 'rmbz_api_require_auth',
    ] );

    register_rest_route( RMBZ_API_NAMESPACE, '/licensing/somas/register-existing', [
        'methods'             => 'POST',
        'callback'            => 'rmbz_api_handle_register_somas_existing',
        'permission_callback' => 'rmbz_api_require_auth',
    ] );

    register_rest_route( RMBZ_API_NAMESPACE, '/licensing/coupon/validate', [
        'methods'             => 'POST',
        'callback'            => 'rmbz_api_handle_validate_coupon',
        'permission_callback' => 'rmbz_api_require_auth',
    ] );

    register_rest_route( RMBZ_API_NAMESPACE, '/releases/(?P<id>\d+)/license', [
        [
            'methods'             => 'GET',
            'callback'            => 'rmbz_api_handle_get_release_license',
            'permission_callback' => 'rmbz_api_require_auth',
            'args' => [ 'id' => [ 'type' => 'integer', 'required' => true ] ],
        ],
        [
            'methods'             => 'POST',
            'callback'            => 'rmbz_api_handle_submit_release_license',
            'permission_callback' => 'rmbz_api_require_auth',
            'args' => [ 'id' => [ 'type' => 'integer', 'required' => true ] ],
        ],
    ] );
}


/* ============================================================================
 * HELPERS
 * ============================================================================ */

/**
 * Formata um registo SOMAS para a resposta REST (não devolve form_data
 * cru — campos sensíveis são re-expostos campo-a-campo conforme necessário).
 */
function rmbz_api_licensing_format_registration( $reg ) {
    if ( ! $reg ) return null;
    return [
        'id'              => (int) $reg->id,
        'status'          => (string) $reg->status,
        'submission_type' => (string) ( $reg->submission_type ?? 'new_registration' ),
        'somas_number'    => $reg->somas_number ?: null,
        'amount_charged'  => isset($reg->amount_charged) ? (float) $reg->amount_charged : 0.0,
        'admin_note'      => $reg->admin_note ?: null,
        'bi_file_url'     => $reg->bi_file_url ?: null,
        'created_at'      => $reg->created_at ? mysql_to_rfc3339( $reg->created_at ) : null,
        'updated_at'      => $reg->updated_at ? mysql_to_rfc3339( $reg->updated_at ) : null,
    ];
}

/**
 * Formata uma licença de release.
 */
function rmbz_api_licensing_format_license( $lic ) {
    if ( ! $lic ) return null;
    return [
        'id'             => (int) $lic->id,
        'release_id'     => (int) $lic->release_id,
        'status'         => (string) $lic->status,
        'track_count'    => (int) ( $lic->track_count ?? 0 ),
        'unit_price'     => isset($lic->unit_price) ? (float) $lic->unit_price : 0.0,
        'amount_charged' => isset($lic->amount_charged) ? (float) $lic->amount_charged : 0.0,
        'discount'       => isset($lic->discount_applied) ? (float) $lic->discount_applied : 0.0,
        'coupon_code'    => $lic->coupon_code ?: null,
        'admin_note'     => $lic->admin_note ?: null,
        'created_at'     => $lic->created_at ? mysql_to_rfc3339( $lic->created_at ) : null,
        'updated_at'     => $lic->updated_at ? mysql_to_rfc3339( $lic->updated_at ) : null,
    ];
}


/* ============================================================================
 * GET /licensing/status
 *
 * Hub central — devolve tudo que a app precisa para render do dashboard:
 *   - sistema activo?
 *   - estado actual do registo SOMAS do artista (null se nunca pediu)
 *   - se está aprovado → somas_number
 *   - preços actuais (registo, por faixa, existing-member)
 *   - saldo da carteira (para mostrar se chega para licenciar)
 * ============================================================================ */
function rmbz_api_handle_licensing_status( WP_REST_Request $request ) {
    $tel = (string) $request->get_param( 'rmbz_telemovel' );

    $enabled = function_exists('rmbz_licensing_is_enabled')
        ? (bool) rmbz_licensing_is_enabled()
        : false;

    $reg = function_exists('rmbz_licensing_get_artist_somas_registration')
        ? rmbz_licensing_get_artist_somas_registration( $tel )
        : null;

    $has_approved = function_exists('rmbz_licensing_artist_has_approved_somas')
        ? (bool) rmbz_licensing_artist_has_approved_somas( $tel )
        : false;

    $price_registration = function_exists('rmbz_licensing_get_registration_price')
        ? (float) rmbz_licensing_get_registration_price()
        : 700.0;
    $price_per_track = function_exists('rmbz_licensing_get_per_track_price')
        ? (float) rmbz_licensing_get_per_track_price()
        : 100.0;
    $price_existing_member = function_exists('rmbz_licensing_get_existing_member_price')
        ? (float) rmbz_licensing_get_existing_member_price()
        : 0.0;

    $balance = function_exists('rmbz_get_wallet_balance_by_phone')
        ? (float) rmbz_get_wallet_balance_by_phone( $tel )
        : 0.0;

    return rmbz_api_ok( [
        '_api_version'           => RMBZ_API_LICENSING_VERSION,
        'enabled'                => $enabled,
        'has_approved_somas'     => $has_approved,
        'somas_number'           => $reg && $reg->status === 'approved' ? ( $reg->somas_number ?: null ) : null,
        'registration'           => rmbz_api_licensing_format_registration( $reg ),
        'prices' => [
            'registration_new'      => $price_registration,
            'registration_existing' => $price_existing_member,
            'per_track'             => $price_per_track,
        ],
        'wallet_balance' => $balance,
    ] );
}


/* ============================================================================
 * POST /uploads/somas-document
 *
 * Upload de BI/Passaporte ou comprovante SOMAS. Devolve URL absoluta +
 * path relativo (que a app envia depois nos endpoints de submit).
 * Aceita JPG/PNG/PDF até 10MB.
 *
 * Multipart com campo "document".
 * ============================================================================ */
function rmbz_api_handle_upload_somas_document( WP_REST_Request $request ) {
    $tel = (string) $request->get_param( 'rmbz_telemovel' );

    if ( function_exists('rmbz_rate_limit')
         && ! rmbz_rate_limit( 'api_upload_somas_doc_' . $tel, 10 ) ) {
        return rmbz_api_error( 'Demasiados uploads. Aguarda um minuto.', 429, 'rate_limit' );
    }

    $files = $request->get_file_params();
    if ( empty( $files['document'] ) || ! isset( $files['document']['tmp_name'] ) ) {
        return rmbz_api_error( 'Nenhum ficheiro recebido (campo "document").', 400, 'no_file' );
    }
    $file = $files['document'];

    if ( $file['error'] !== UPLOAD_ERR_OK ) {
        return rmbz_api_error( 'Erro no upload (código ' . $file['error'] . ').', 400, 'upload_error' );
    }

    // Reutilizar validação do plugin (tamanho, tipo)
    if ( function_exists('rmbz_licensing_validate_bi_upload') ) {
        $check = rmbz_licensing_validate_bi_upload( $file );
        if ( ! $check['valid'] ) {
            return rmbz_api_error( $check['error'], 422, 'invalid_file' );
        }
    }

    // Reutilizar handler do plugin (move para uploads/, devolve url+path)
    if ( ! function_exists('rmbz_licensing_handle_bi_upload') ) {
        return rmbz_api_error( 'Sistema indisponível.', 500, 'module_missing' );
    }

    $result = rmbz_licensing_handle_bi_upload( $file, $tel );
    if ( ! $result['success'] ) {
        return rmbz_api_error( 'Falha a guardar: ' . $result['error'], 500, 'upload_failed' );
    }

    return rmbz_api_ok( [
        '_api_version' => RMBZ_API_LICENSING_VERSION,
        'url'          => $result['url'],
        'path'         => $result['path'],
        'size'         => (int) ( $file['size'] ?? 0 ),
    ] );
}


/* ============================================================================
 * POST /licensing/somas/register-new — caminho A
 *
 * Body (JSON):
 *   {
 *     "form_data": { "apelido", "nome", "morada", "localidade",
 *                    "telemovel_contacto", "email", "bi_passaporte",
 *                    "local_emissao", "data_emissao", "nacionalidade",
 *                    "data_nascimento", "nome_cartao" },
 *     "bi_upload_path": "<path devolvido por /uploads/somas-document>"
 *   }
 *
 * O plugin precisa do array $bi_file no formato $_FILES — vamos
 * reconstruir esse array a partir do path já uploaded (truque).
 * ============================================================================ */
function rmbz_api_handle_register_somas_new( WP_REST_Request $request ) {
    $tel = (string) $request->get_param( 'rmbz_telemovel' );

    $form_data = $request->get_param( 'form_data' );
    $bi_path   = (string) $request->get_param( 'bi_upload_path' );

    if ( ! is_array( $form_data ) ) {
        return rmbz_api_error( 'Campo "form_data" obrigatório.', 422, 'missing_form' );
    }
    if ( empty( $bi_path ) || ! file_exists( $bi_path ) ) {
        return rmbz_api_error( 'Faltou o upload do BI. Submete primeiro o ficheiro.', 422, 'missing_bi' );
    }

    if ( ! function_exists('rmbz_licensing_submit_somas_registration') ) {
        return rmbz_api_error( 'Sistema indisponível.', 500, 'module_missing' );
    }

    // Reconstruir $bi_file a partir do path já guardado no servidor.
    // A função do plugin chama validate_bi_upload() depois e move o ficheiro
    // de novo via wp_handle_upload — por isso copiamos para tmp.
    $tmp = tempnam( sys_get_temp_dir(), 'somas_bi_' );
    if ( ! @copy( $bi_path, $tmp ) ) {
        return rmbz_api_error( 'Falha a preparar o ficheiro.', 500, 'tmp_copy_failed' );
    }
    $name = basename( $bi_path );
    $size = (int) filesize( $bi_path );
    $mime = function_exists('mime_content_type') ? @mime_content_type( $bi_path ) : 'application/octet-stream';

    $bi_file = [
        'name'     => $name,
        'type'     => $mime ?: 'application/octet-stream',
        'tmp_name' => $tmp,
        'error'    => UPLOAD_ERR_OK,
        'size'     => $size,
    ];

    // Sanitizar form_data (manter strings simples)
    $clean_form = [];
    foreach ( $form_data as $k => $v ) {
        $clean_form[ sanitize_key( (string) $k ) ] = is_string( $v )
            ? sanitize_text_field( $v )
            : (string) $v;
    }

    $result = rmbz_licensing_submit_somas_registration( $tel, $clean_form, $bi_file );

    @unlink( $tmp );

    if ( empty( $result['success'] ) ) {
        return rmbz_api_error(
            $result['error'] ?: 'Falha ao submeter pedido.',
            400,
            'submit_failed'
        );
    }

    // Devolver registo recém-criado
    $reg = rmbz_licensing_get_artist_somas_registration( $tel );
    return rmbz_api_ok( [
        '_api_version'    => RMBZ_API_LICENSING_VERSION,
        'registration_id' => (int) $result['registration_id'],
        'registration'    => rmbz_api_licensing_format_registration( $reg ),
        'message'         => 'Pedido SOMAS submetido. O admin vai processar em breve.',
    ], 201 );
}


/* ============================================================================
 * POST /licensing/somas/register-existing — caminho B
 *
 * Body:
 *   {
 *     "form_data": { "apelido", "nome", "email", "somas_number" },
 *     "bi_upload_path": "...",
 *     "somas_card_upload_path": "..."
 *   }
 * ============================================================================ */
function rmbz_api_handle_register_somas_existing( WP_REST_Request $request ) {
    $tel = (string) $request->get_param( 'rmbz_telemovel' );

    $form_data = $request->get_param( 'form_data' );
    $bi_path   = (string) $request->get_param( 'bi_upload_path' );
    $card_path = (string) $request->get_param( 'somas_card_upload_path' );

    if ( ! is_array( $form_data ) ) {
        return rmbz_api_error( 'Campo "form_data" obrigatório.', 422, 'missing_form' );
    }
    if ( empty( $bi_path ) || ! file_exists( $bi_path ) ) {
        return rmbz_api_error( 'Falta upload do BI.', 422, 'missing_bi' );
    }
    if ( empty( $card_path ) || ! file_exists( $card_path ) ) {
        return rmbz_api_error( 'Falta upload do comprovante SOMAS.', 422, 'missing_card' );
    }

    if ( ! function_exists('rmbz_licensing_submit_existing_member') ) {
        return rmbz_api_error( 'Sistema indisponível.', 500, 'module_missing' );
    }

    // Reconstruir os 2 $_FILES
    $bi_tmp   = tempnam( sys_get_temp_dir(), 'somas_bi_' );
    $card_tmp = tempnam( sys_get_temp_dir(), 'somas_card_' );
    @copy( $bi_path, $bi_tmp );
    @copy( $card_path, $card_tmp );

    $bi_file = [
        'name' => basename( $bi_path ),
        'type' => @mime_content_type( $bi_path ) ?: 'application/octet-stream',
        'tmp_name' => $bi_tmp,
        'error' => UPLOAD_ERR_OK,
        'size' => (int) filesize( $bi_path ),
    ];
    $card_file = [
        'name' => basename( $card_path ),
        'type' => @mime_content_type( $card_path ) ?: 'application/octet-stream',
        'tmp_name' => $card_tmp,
        'error' => UPLOAD_ERR_OK,
        'size' => (int) filesize( $card_path ),
    ];

    // Sanitizar form_data
    $clean_form = [];
    foreach ( $form_data as $k => $v ) {
        $clean_form[ sanitize_key( (string) $k ) ] = is_string( $v )
            ? sanitize_text_field( $v )
            : (string) $v;
    }

    $result = rmbz_licensing_submit_existing_member( $tel, $clean_form, $bi_file, $card_file );

    @unlink( $bi_tmp );
    @unlink( $card_tmp );

    if ( empty( $result['success'] ) ) {
        return rmbz_api_error(
            $result['error'] ?: 'Falha ao submeter pedido.',
            400,
            'submit_failed'
        );
    }

    $reg = rmbz_licensing_get_artist_somas_registration( $tel );
    return rmbz_api_ok( [
        '_api_version'    => RMBZ_API_LICENSING_VERSION,
        'registration_id' => (int) $result['registration_id'],
        'registration'    => rmbz_api_licensing_format_registration( $reg ),
        'message'         => 'Pedido enviado. O admin vai validar o teu nº SOMAS.',
    ], 201 );
}


/* ============================================================================
 * POST /licensing/coupon/validate
 *
 * Body: { "coupon_code": "...", "release_id": 123 }
 *
 * Devolve o desconto e o total final SEM submeter — para preview.
 * Usado pela tela de licenciamento de release para mostrar o impacto
 * do cupão antes de o utilizador confirmar.
 * ============================================================================ */
function rmbz_api_handle_validate_coupon( WP_REST_Request $request ) {
    $tel  = (string) $request->get_param( 'rmbz_telemovel' );
    $code = trim( (string) $request->get_param( 'coupon_code' ) );
    $release_id = (int) $request->get_param( 'release_id' );

    if ( empty( $code ) ) {
        return rmbz_api_error( 'Código de cupão obrigatório.', 422, 'missing_code' );
    }
    if ( $release_id <= 0 ) {
        return rmbz_api_error( 'Release inválido.', 422, 'invalid_release' );
    }

    // Verificar ownership
    global $wpdb;
    $owns = (int) $wpdb->get_var( $wpdb->prepare(
        "SELECT COUNT(*) FROM {$wpdb->prefix}rmbz_distro_releases
         WHERE id = %d AND artist_telemovel = %s",
        $release_id, $tel
    ) );
    if ( ! $owns ) {
        return rmbz_api_error( 'Release não encontrado.', 404, 'not_found' );
    }

    $track_count = function_exists('rmbz_licensing_count_release_tracks')
        ? rmbz_licensing_count_release_tracks( $release_id )
        : 0;
    $unit_price = function_exists('rmbz_licensing_get_per_track_price')
        ? rmbz_licensing_get_per_track_price()
        : 100.0;

    if ( ! function_exists('rmbz_licensing_validate_coupon') ) {
        return rmbz_api_error( 'Sistema indisponível.', 500, 'module_missing' );
    }

    $check = rmbz_licensing_validate_coupon( $code, $tel, $track_count, $unit_price );

    if ( ! $check['valid'] ) {
        return rmbz_api_error( $check['error'] ?: 'Cupão inválido.', 400, 'invalid_coupon' );
    }

    return rmbz_api_ok( [
        '_api_version' => RMBZ_API_LICENSING_VERSION,
        'valid'        => true,
        'discount'     => (float) $check['discount'],
        'final_total'  => (float) $check['final_total'],
        'base_total'   => (float) ( $unit_price * $track_count ),
        'unit_price'   => (float) $unit_price,
        'track_count'  => (int) $track_count,
    ] );
}


/* ============================================================================
 * GET /releases/{id}/license — licença actual da release (ou null)
 * ============================================================================ */
function rmbz_api_handle_get_release_license( WP_REST_Request $request ) {
    $tel = (string) $request->get_param( 'rmbz_telemovel' );
    $id  = (int) $request->get_param( 'id' );

    // Verificar ownership
    global $wpdb;
    $owns = (int) $wpdb->get_var( $wpdb->prepare(
        "SELECT COUNT(*) FROM {$wpdb->prefix}rmbz_distro_releases
         WHERE id = %d AND artist_telemovel = %s",
        $id, $tel
    ) );
    if ( ! $owns ) {
        return rmbz_api_error( 'Release não encontrado.', 404, 'not_found' );
    }

    $lic = function_exists('rmbz_licensing_get_release_license')
        ? rmbz_licensing_get_release_license( $id )
        : null;
    $track_count = function_exists('rmbz_licensing_count_release_tracks')
        ? rmbz_licensing_count_release_tracks( $id )
        : 0;
    $unit_price = function_exists('rmbz_licensing_get_per_track_price')
        ? rmbz_licensing_get_per_track_price()
        : 100.0;

    return rmbz_api_ok( [
        '_api_version' => RMBZ_API_LICENSING_VERSION,
        'license'      => rmbz_api_licensing_format_license( $lic ),
        'track_count'  => (int) $track_count,
        'unit_price'   => (float) $unit_price,
        'estimated_total' => (float) ( $unit_price * $track_count ),
    ] );
}


/* ============================================================================
 * POST /releases/{id}/license — pedir licenciamento da release
 *
 * Body: { "coupon_code": "..." }   // opcional
 *
 * O servidor:
 *   - Valida que tem nº SOMAS aprovado
 *   - Valida que a release é do user e ainda não tem licença activa
 *   - Aplica cupão se fornecido
 *   - Cobra da carteira (se total > 0)
 *   - Cria registo de licença (status=pending)
 * ============================================================================ */
function rmbz_api_handle_submit_release_license( WP_REST_Request $request ) {
    $tel = (string) $request->get_param( 'rmbz_telemovel' );
    $id  = (int) $request->get_param( 'id' );
    $coupon = trim( (string) $request->get_param( 'coupon_code' ) );

    if ( ! function_exists('rmbz_licensing_submit_release_license') ) {
        return rmbz_api_error( 'Sistema indisponível.', 500, 'module_missing' );
    }

    $result = rmbz_licensing_submit_release_license( $tel, $id, $coupon );

    if ( empty( $result['success'] ) ) {
        return rmbz_api_error(
            $result['error'] ?: 'Falha no licenciamento.',
            400,
            'submit_failed'
        );
    }

    // Devolver licença recém-criada
    $lic = rmbz_licensing_get_release_license( $id );
    return rmbz_api_ok( [
        '_api_version'   => RMBZ_API_LICENSING_VERSION,
        'license_id'     => (int) $result['license_id'],
        'amount_charged' => (float) $result['amount_charged'],
        'discount'       => (float) $result['discount'],
        'license'        => rmbz_api_licensing_format_license( $lic ),
        'message'        => 'Pedido de licenciamento enviado. O admin processa em breve.',
    ], 201 );
}
