<?php
/**
 * 1MZ For Artists — Milestones Endpoint
 *
 * Expõe os marcos do artista ao app.
 *
 * ENDPOINTS:
 *   GET  /me/milestones                        — lista completa (atingidos + bloqueados)
 *   POST /me/milestones/{key}/acknowledge      — marcar como visto
 *   POST /me/milestones/recheck                — força recheck (debug/admin)
 *
 * @package 1MZ_For_Artists
 * @since 1.6.55
 */

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

if ( ! defined( 'RMBZ_API_MILESTONES_VERSION' ) ) {
    define( 'RMBZ_API_MILESTONES_VERSION', '1.6.55' );
}

add_action( 'rest_api_init', 'rmbz_api_register_milestones_routes' );

function rmbz_api_register_milestones_routes() {
    register_rest_route( RMBZ_API_NAMESPACE, '/me/milestones', [
        'methods'             => 'GET',
        'callback'            => 'rmbz_api_handle_me_milestones',
        'permission_callback' => 'rmbz_api_require_auth',
    ] );

    register_rest_route( RMBZ_API_NAMESPACE, '/me/milestones/(?P<key>[a-z0-9_]+)/acknowledge', [
        'methods'             => 'POST',
        'callback'            => 'rmbz_api_handle_milestone_acknowledge',
        'permission_callback' => 'rmbz_api_require_auth',
        'args' => [
            'key' => [ 'type' => 'string', 'required' => true ],
        ],
    ] );

    register_rest_route( RMBZ_API_NAMESPACE, '/me/milestones/recheck', [
        'methods'             => 'POST',
        'callback'            => 'rmbz_api_handle_milestones_recheck',
        'permission_callback' => 'rmbz_api_require_auth',
    ] );

    // [1.5.286] Mensagem de celebração (IA) para um marco atingido.
    register_rest_route( RMBZ_API_NAMESPACE, '/me/milestones/(?P<key>[a-z0-9_]+)/message', [
        'methods'             => 'GET',
        'callback'            => 'rmbz_api_handle_milestone_message',
        'permission_callback' => 'rmbz_api_require_auth',
        'args' => [
            'key' => [ 'type' => 'string', 'required' => true ],
        ],
    ] );
}

/**
 * GET /me/milestones/{key}/message
 *
 * Mensagem de parabéns personalizada por IA para um marco já atingido, com
 * 1 sugestão de como aproveitar o momento. Para todos os artistas. Cacheado
 * por artista+marco (a celebração não muda — uma chamada à IA por marco).
 */
function rmbz_api_handle_milestone_message( WP_REST_Request $request ) {
    $tel = (string) $request->get_param( 'rmbz_telemovel' );
    $key = sanitize_key( (string) $request->get_param( 'key' ) );

    $catalog = function_exists( 'rmbz_milestones_catalog' ) ? rmbz_milestones_catalog() : [];
    if ( ! isset( $catalog[ $key ] ) ) {
        return rmbz_api_error( 'Marco desconhecido.', 404, 'unknown_milestone' );
    }

    global $wpdb;
    $row = $wpdb->get_row( $wpdb->prepare(
        "SELECT achieved_value, achieved_at FROM {$wpdb->prefix}rmbz_artist_milestones
         WHERE artist_telemovel = %s AND milestone_key = %s",
        $tel, $key
    ) );
    if ( ! $row ) {
        return rmbz_api_error( 'Ainda não atingiste este marco.', 409, 'not_achieved' );
    }

    $cache_key = 'rmbz_ms_msg_' . md5( $tel ) . '_' . $key;
    $cached = get_transient( $cache_key );
    if ( is_array( $cached ) ) {
        return rmbz_api_ok( $cached );
    }

    $def   = $catalog[ $key ];
    $nome  = function_exists( 'rmbz_get_artist_nome_by_telemovel' )
        ? (string) rmbz_get_artist_nome_by_telemovel( $tel ) : '';
    $primeiro = $nome !== '' ? trim( explode( ' ', $nome )[0] ) : '';

    $built = rmbz_milestone_build_message( $def, (int) $row->achieved_value, $primeiro );

    $payload = [
        'key'        => $key,
        'message'    => $built['message'],
        'tip'        => $built['tip'],
        'ai_enabled' => function_exists( 'rmbz_insights_ai_enabled' ) && rmbz_insights_ai_enabled(),
    ];
    set_transient( $cache_key, $payload, 30 * DAY_IN_SECONDS );
    return rmbz_api_ok( $payload );
}

/** Gera a mensagem do marco (IA se disponível, senão template). */
function rmbz_milestone_build_message( array $def, $value, $primeiro ) {
    $title = (string) ( $def['title'] ?? 'Novo marco' );

    $fallback = [
        'message' => $primeiro !== ''
            ? sprintf( 'Parabéns, %s! Alcançaste "%s". A tua música está a ganhar vida. 🎉', $primeiro, $title )
            : sprintf( 'Parabéns! Alcançaste "%s". A tua música está a ganhar vida. 🎉', $title ),
        'tip' => [ 'icon' => '📣', 'text' => 'Partilha esta conquista com os teus fãs — eles fazem parte dela.' ],
    ];

    if ( ! function_exists( 'rmbz_ai_messages' )
         || ! function_exists( 'rmbz_insights_ai_enabled' )
         || ! rmbz_insights_ai_enabled() ) {
        return $fallback;
    }

    $ctx = [
        'marco'    => $title,
        'descricao'=> (string) ( $def['description'] ?? '' ),
        'valor'    => (int) $value,
        'artista'  => $primeiro ?: null,
    ];

    $system = "És o coach da 1MZ Records (Moçambique). Celebras conquistas de "
        . "artistas em pt-PT, de forma genuína, calorosa e breve. Usa só os dados "
        . "fornecidos. Responde só com JSON válido.";
    $instruction = "Um artista acabou de atingir um marco. Celebra-o.\n\n"
        . "DADOS:\n" . wp_json_encode( $ctx, JSON_UNESCAPED_UNICODE ) . "\n\n"
        . "Devolve EXACTAMENTE: { \"message\": \"parabéns personalizados (máx 140 caracteres)\", "
        . "\"tip\": { \"icon\": \"emoji\", \"text\": \"como aproveitar este momento (máx 120 caracteres)\" } }";

    $res = rmbz_ai_messages( $system, $instruction, [ 'max_tokens' => 300, 'temperature' => 0.85 ] );
    if ( empty( $res['ok'] ) ) return $fallback;

    $data = rmbz_ai_extract_json( $res['text'] );
    if ( ! is_array( $data ) || empty( $data['message'] ) ) return $fallback;

    return [
        'message' => (string) $data['message'],
        'tip'     => [
            'icon' => isset( $data['tip']['icon'] ) ? (string) $data['tip']['icon'] : '📣',
            'text' => isset( $data['tip']['text'] ) ? (string) $data['tip']['text'] : $fallback['tip']['text'],
        ],
    ];
}

/**
 * Devolve lista completa: marcos do catálogo + estado por artista.
 *
 * Estrutura do item:
 *   {
 *     key, category, title, description, icon, threshold, order_hint,
 *     achieved: bool,
 *     achieved_at: string|null,
 *     achieved_value: int|null,
 *     acknowledged: bool,
 *     progress: float|null,   // 0..1 para os escalonados; null para os booleanos
 *     progress_text: string|null  // "640 / 1000 streams"
 *   }
 */
function rmbz_api_handle_me_milestones( WP_REST_Request $request ) {
    $tel = (string) $request->get_param( 'rmbz_telemovel' );

    // Antes de devolver, fazemos um recheck rápido para garantir que
    // marcos recém-atingidos aparecem (caso o cron ainda não tenha corrido).
    if ( function_exists( 'rmbz_milestones_check_artist' ) ) {
        rmbz_milestones_check_artist( $tel );
    }

    global $wpdb;
    $catalog = function_exists( 'rmbz_milestones_catalog' )
        ? rmbz_milestones_catalog()
        : [];

    // Marcos já atingidos
    $achieved_rows = $wpdb->get_results( $wpdb->prepare(
        "SELECT milestone_key, achieved_value, achieved_at, acknowledged
         FROM {$wpdb->prefix}rmbz_artist_milestones
         WHERE artist_telemovel = %s",
        $tel
    ) );
    $achieved = [];
    foreach ( $achieved_rows as $r ) {
        $achieved[ $r->milestone_key ] = $r;
    }

    // Para calcular progresso, lemos as métricas actuais uma vez
    $metrics = function_exists( 'rmbz_milestones_compute_metrics' )
        ? rmbz_milestones_compute_metrics( $tel )
        : [];

    $items = [];
    foreach ( $catalog as $key => $def ) {
        $a = $achieved[ $key ] ?? null;
        $progress = rmbz_api_milestone_progress( $key, $def, $metrics );

        $items[] = [
            'key'            => $key,
            'category'       => $def['category'],
            'title'          => $def['title'],
            'description'    => $def['description'] ?? null,
            'icon'           => $def['icon'] ?? 'star',
            'threshold'      => $def['threshold'] ?? null,
            'order_hint'     => $def['order_hint'] ?? 999,
            'achieved'       => $a !== null,
            'achieved_at'    => $a ? mysql_to_rfc3339( $a->achieved_at ) : null,
            'achieved_value' => $a ? (int) $a->achieved_value : null,
            'acknowledged'   => $a ? (bool) $a->acknowledged : false,
            'progress'       => $progress['ratio'],
            'progress_text'  => $progress['text'],
        ];
    }

    // Ordem: atingidos não acknowledged primeiro, depois atingidos antigos,
    // depois bloqueados por order_hint.
    usort( $items, function( $a, $b ) {
        // Não acknowledged primeiro (são "novos")
        if ( $a['achieved'] && ! $a['acknowledged'] && ! ( $b['achieved'] && ! $b['acknowledged'] ) ) return -1;
        if ( $b['achieved'] && ! $b['acknowledged'] && ! ( $a['achieved'] && ! $a['acknowledged'] ) ) return 1;
        // Atingidos antes de bloqueados
        if ( $a['achieved'] && ! $b['achieved'] ) return -1;
        if ( $b['achieved'] && ! $a['achieved'] ) return 1;
        // Dentro do mesmo grupo: por order_hint
        return $a['order_hint'] - $b['order_hint'];
    } );

    $achieved_count = count( array_filter( $items, fn( $i ) => $i['achieved'] ) );
    $total = count( $items );

    return rmbz_api_ok( [
        'items'           => $items,
        'achieved_count'  => $achieved_count,
        'total_count'     => $total,
    ] );
}

/**
 * Calcula progresso para os marcos escalonados (com threshold).
 * Para os booleanos (primeira X), devolve null.
 */
function rmbz_api_milestone_progress( $key, $def, $metrics ) {
    $threshold = $def['threshold'] ?? null;
    if ( ! $threshold ) return [ 'ratio' => null, 'text' => null ];

    // Que métrica usar — espelha a lógica do check_one
    $metric = null;
    $label  = '';
    switch ( $def['category'] ) {
        case 'audience':
            $metric = $metrics['total_streams'] ?? 0;
            $label  = 'streams';
            break;
        case 'financial':
            if ( $key === 'first_payment' ) {
                $metric = $metrics['received_any_payment'] ?? 0;
                $label  = 'pagamento';
            } else {
                $metric = (int) ( $metrics['total_earnings'] ?? 0 );
                $label  = 'MT';
            }
            break;
        case 'catalog':
            if ( $key === 'first_ep' || $key === 'first_album' ) {
                $metric = $metrics['max_tracks_in_release'] ?? 0;
                $label  = 'faixas no maior release';
            } elseif ( $key === 'first_release_submitted' ) {
                $metric = $metrics['releases_submitted'] ?? 0;
                $label  = 'releases';
            } else {
                $metric = $metrics['releases_live'] ?? 0;
                $label  = 'releases';
            }
            break;
        case 'time':
            $metric = $metrics['days_as_artist'] ?? 0;
            $label  = 'dias';
            break;
        case 'community':
            if ( $key === 'first_split_accepted' ) {
                $metric = $metrics['splits_accepted_in_own_releases'] ?? 0;
                $label  = 'colaborações';
            } else {
                $metric = $metrics['referrals_count'] ?? 0;
                $label  = 'convites';
            }
            break;
    }

    if ( $metric === null ) return [ 'ratio' => null, 'text' => null ];

    $ratio = min( 1.0, $metric / max( 1, $threshold ) );
    $text  = number_format_i18n( (int) $metric ) . ' / '
           . number_format_i18n( (int) $threshold ) . ' ' . $label;

    return [ 'ratio' => $ratio, 'text' => $text ];
}

/**
 * POST /me/milestones/{key}/acknowledge
 */
function rmbz_api_handle_milestone_acknowledge( WP_REST_Request $request ) {
    $tel = (string) $request->get_param( 'rmbz_telemovel' );
    $key = (string) $request->get_param( 'key' );

    global $wpdb;
    $updated = $wpdb->update(
        $wpdb->prefix . 'rmbz_artist_milestones',
        [ 'acknowledged' => 1 ],
        [ 'artist_telemovel' => $tel, 'milestone_key' => $key ],
        [ '%d' ],
        [ '%s', '%s' ]
    );

    if ( $updated === false ) {
        return rmbz_api_error( 'Erro ao actualizar.', 500, 'db_error' );
    }

    return rmbz_api_ok( [ 'acknowledged' => true ] );
}

/**
 * POST /me/milestones/recheck — força re-detecção
 */
function rmbz_api_handle_milestones_recheck( WP_REST_Request $request ) {
    $tel = (string) $request->get_param( 'rmbz_telemovel' );
    $new_keys = function_exists( 'rmbz_milestones_check_artist' )
        ? rmbz_milestones_check_artist( $tel )
        : [];
    return rmbz_api_ok( [ 'new_keys' => $new_keys, 'count' => count( $new_keys ) ] );
}
