<?php
/**
 * Plugin Name: Fe Adulta — API crear traducción
 * Description: Endpoint REST idempotente para crear y enlazar traducciones Polylang.
 * Version: 1.0
 *
 * POST /wp-json/fea/v1/crear-traduccion
 * es_id=<post ES>, lang=<en|fr|it|pt>, title/content/excerpt/status/model
 *
 * Ver issue gitea.feadulta.com/rafa/feadulta#222.
 */

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

const FEA_TRANSLATION_LANGUAGES = ['en', 'fr', 'it', 'pt'];

add_action('rest_api_init', function () {
    register_rest_route('fea/v1', '/crear-traduccion', [
        'methods'             => WP_REST_Server::CREATABLE,
        'callback'            => 'fea_crear_traduccion_handle',
        'permission_callback' => 'fea_crear_traduccion_can_call',
        // Se valida después de autorizar para que las llamadas anónimas
        // obtengan 401 aunque omitan parámetros.
        'args'                => [
            'es_id' => [
                'sanitize_callback' => 'absint',
            ],
            'lang' => [
                'sanitize_callback' => 'sanitize_key',
            ],
            'status' => [
                'sanitize_callback' => 'sanitize_key',
            ],
            'model' => [
                'sanitize_callback' => 'sanitize_text_field',
            ],
        ],
    ]);
});

/** Editor o superior: mismo nivel que los demás endpoints fea/v1 de escritura. */
function fea_crear_traduccion_can_call(WP_REST_Request $request) {
    if (!is_user_logged_in()) {
        return new WP_Error(
            'fea_crear_traduccion_not_authenticated',
            'Debes autenticarte para crear una traducción.',
            ['status' => 401]
        );
    }
    if (!current_user_can('edit_others_posts')) {
        return new WP_Error(
            'fea_crear_traduccion_forbidden',
            'No tienes permiso para crear traducciones.',
            ['status' => 403]
        );
    }
    return true;
}

function fea_crear_traduccion_handle(WP_REST_Request $request) {
    $es_id = absint($request->get_param('es_id'));
    if (!$es_id) {
        return new WP_Error(
            'fea_crear_traduccion_invalid_source',
            'es_id es obligatorio.',
            ['status' => 400]
        );
    }

    $lang = (string) $request->get_param('lang');
    if (!in_array($lang, FEA_TRANSLATION_LANGUAGES, true)) {
        return new WP_Error(
            'fea_crear_traduccion_invalid_language',
            'lang debe ser en, fr, it o pt.',
            ['status' => 400]
        );
    }

    $status = (string) ($request->get_param('status') ?: 'draft');
    if (!in_array($status, ['draft', 'publish'], true)) {
        return new WP_Error(
            'fea_crear_traduccion_invalid_status',
            'status debe ser draft o publish.',
            ['status' => 400]
        );
    }

    $source = get_post($es_id);
    if (!$source) {
        return new WP_Error(
            'fea_crear_traduccion_source_not_found',
            'No existe el post español indicado.',
            ['status' => 404]
        );
    }
    if (!function_exists('pll_get_post') || !function_exists('pll_set_post_language') || !function_exists('pll_save_post_translations')) {
        return new WP_Error(
            'fea_crear_traduccion_polylang_unavailable',
            'Polylang no está disponible.',
            ['status' => 500]
        );
    }

    // Idempotencia dura: se responde antes de interpretar un payload nuevo.
    $existing_id = (int) pll_get_post($es_id, $lang);
    if ($existing_id && !get_post($existing_id)) $existing_id = 0;
    if ($existing_id) {
        return new WP_REST_Response([
            'es_id'          => $es_id,
            'lang'           => $lang,
            'translation_id' => $existing_id,
            'created'        => false,
            'url'            => get_permalink($existing_id),
        ], 200);
    }

    $title = (string) ($request->get_param('title') ?? '');
    $new_id = wp_insert_post([
        'post_title'   => wp_slash($title),
        'post_content' => wp_slash((string) ($request->get_param('content') ?? '')),
        'post_excerpt' => wp_slash((string) ($request->get_param('excerpt') ?? '')),
        'post_name'    => sanitize_title($title),
        'post_status'  => $status,
        'post_type'    => 'post',
        'post_author'  => (int) $source->post_author,
        'post_date'    => $source->post_date,
        'to_ping'      => '',
        'pinged'       => '',
    ], true);
    if (is_wp_error($new_id)) {
        return new WP_Error(
            'fea_crear_traduccion_insert_failed',
            'No se pudo crear la traducción: ' . $new_id->get_error_message(),
            ['status' => 500]
        );
    }

    // El idioma se asigna antes de mapear categorías para que Polylang admita
    // los términos traducidos en el nuevo post.
    pll_set_post_language($new_id, $lang);

    $categories = wp_get_post_categories($es_id);
    $mapped_categories = [];
    foreach ($categories as $category_id) {
        $translated_category = function_exists('pll_get_term') ? (int) pll_get_term($category_id, $lang) : 0;
        $mapped_categories[] = $translated_category ?: $category_id;
    }
    if ($mapped_categories) {
        wp_set_post_categories($new_id, array_values(array_unique($mapped_categories)));
    }

    $translations = function_exists('pll_get_post_translations') ? pll_get_post_translations($es_id) : ['es' => $es_id];
    if (!$translations) $translations = ['es' => $es_id];
    $translations[$lang] = $new_id;
    pll_save_post_translations($translations);

    update_post_meta($new_id, 'traduccion_automatica', '1');
    update_post_meta($new_id, 'traduccion_origen', $es_id);
    update_post_meta($new_id, 'traduccion_modelo', (string) ($request->get_param('model') ?? ''));
    update_post_meta($new_id, 'traduccion_fecha', gmdate('c'));

    return new WP_REST_Response([
        'es_id'          => $es_id,
        'lang'           => $lang,
        'translation_id' => (int) $new_id,
        'created'        => true,
        'url'            => get_permalink($new_id),
    ], 201);
}
