<?php
if ( ! defined( 'ABSPATH' ) ) { exit; }

class Falcify_Api {
    public static function init() {
        add_action( 'wp_ajax_falcify_generate', array( __CLASS__, 'ajax_generate' ) );
        add_action( 'wp_ajax_falcify_estimate', array( __CLASS__, 'ajax_estimate' ) );
        add_action( 'wp_ajax_falcify_test_connection', array( __CLASS__, 'ajax_test' ) );
        add_action( 'wp_ajax_falcify_refresh_usage', array( __CLASS__, 'ajax_usage' ) );
        add_action( 'wp_ajax_falcify_validate', array( __CLASS__, 'ajax_validate' ) );
        add_action( 'wp_ajax_falcify_set_status', array( __CLASS__, 'ajax_set_status' ) );
        add_action( 'wp_ajax_falcify_save_content', array( __CLASS__, 'ajax_save_content' ) );
        add_action( 'wp_ajax_falcify_regenerate_pictos', array( __CLASS__, 'ajax_regenerate_pictos' ) );
        add_action( 'save_post', array( __CLASS__, 'sync_post_save' ), 20, 3 );
    }

    private static function endpoint( $path ) {
        $base = untrailingslashit( Falcify_Settings::get_value( 'saas_url' ) );
        return $base . $path;
    }

    private static function get_credentials_or_fail() {
        $api_key  = trim( (string) Falcify_Settings::get_value( 'api_key' ) );
        $site_url = trim( (string) home_url() );
        if ( $api_key === '' ) {
            wp_send_json_error( array( 'error' => esc_html__( 'Veuillez d\'abord saisir votre clé API dans Réglages > Falcify, puis cliquez sur "Enregistrer les modifications" avant de tester la connexion.', 'falcify-connector' ) ), 400 );
        }
        if ( $site_url === '' ) {
            wp_send_json_error( array( 'error' => esc_html__( 'URL du site WordPress introuvable.', 'falcify-connector' ) ), 400 );
        }
        return array( 'api_key' => $api_key, 'site_url' => $site_url );
    }

    public static function request( $path, $body = array(), $method = 'POST' ) {
        $args = array(
            'timeout' => 60,
            'headers' => array( 'Content-Type' => 'application/json', 'Accept' => 'application/json' ),
        );
        $url = self::endpoint( $path );
        if ( $method === 'GET' ) {
            $url = add_query_arg( $body, $url );
            $res = wp_remote_get( $url, $args );
        } else {
            $args['body'] = wp_json_encode( $body );
            $res = wp_remote_post( $url, $args );
        }
        if ( is_wp_error( $res ) ) return array( 'ok' => false, 'error' => $res->get_error_message() );
        $code = wp_remote_retrieve_response_code( $res );
        $data = json_decode( wp_remote_retrieve_body( $res ), true );
        return array( 'ok' => $code >= 200 && $code < 300, 'status' => $code, 'data' => $data );
    }

    public static function ajax_test() {
        check_ajax_referer( 'falcify_admin', 'nonce' );
        if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( array( 'message' => esc_html__( 'Action non autorisée.', 'falcify-connector' ) ), 403 );
        $cred = self::get_credentials_or_fail();
        $r = self::request( '/api/wordpress/verify', $cred );
        if ( ! $r['ok'] ) wp_send_json_error( $r['data'] ?: array( 'error' => $r['error'] ?? esc_html__( 'Erreur', 'falcify-connector' ) ), 400 );
        wp_send_json_success( $r['data'] );
    }

    public static function ajax_usage() {
        check_ajax_referer( 'falcify_admin', 'nonce' );
        if ( ! current_user_can( 'manage_options' ) ) wp_send_json_error( array( 'message' => esc_html__( 'Action non autorisée.', 'falcify-connector' ) ), 403 );
        $cred = self::get_credentials_or_fail();
        $r = self::request( '/api/wordpress/usage', $cred, 'GET' );
        if ( ! $r['ok'] ) wp_send_json_error( $r['data'] ?: array( 'error' => $r['error'] ?? esc_html__( 'Erreur', 'falcify-connector' ) ), 400 );
        wp_send_json_success( $r['data'] );
    }

    private static function get_post_payload( $post_id ) {
        $post = get_post( $post_id );
        if ( ! $post ) return null;
        // v2.7.17 — on envoie le HTML brut du contenu WordPress au moteur FALC
        // au lieu d'un texte aplati. Cela préserve les <h2>/<h3>/<p> déjà
        // présents (y compris dans le markup Gutenberg stocké dans post_content)
        // afin que la génération FALC conserve la hiérarchie du document.
        // Le pipeline SaaS supprime déjà les balises non autorisées et les
        // commentaires de blocs, donc on évite ici `wp_strip_all_tags()` qui
        // détruisait toute la structure avant la génération.
        $original = (string) $post->post_content;
        $api_key  = trim( (string) Falcify_Settings::get_value( 'api_key' ) );
        if ( $api_key === '' ) return 'missing_api_key';
        return array(
            'api_key'          => $api_key,
            'site_url'         => home_url(),
            'post_id'          => $post_id,
            'post_title'       => get_the_title( $post_id ),
            'post_type'        => $post->post_type,
            'original_content' => $original,
        );
    }

    private static function sync_falc_meta( $post_id, $raw_content ) {
        $has_pictos = false !== strpos( $raw_content, 'falc-picto' );
        $content = $raw_content !== ''
            ? Falcify_Renderer::repair_flattened_blocks( Falcify_Renderer::kses_falc( $raw_content ) )
            : '';

        if ( $content !== '' && class_exists( 'Falcify_Renderer' ) ) {
            if ( $has_pictos ) {
                // L'éditeur contient déjà des pictos — on les préserve.
                // _falcify_content_pictos = contenu tel quel (avec pictos).
                // _falcify_content = version sans spans pictos (texte pur).
                $base = preg_replace( '#<span[^>]*class="[^"]*falc-picto[^"]*"[^>]*>[\s\S]*?</span>\s*#is', '', $content );
                $base = Falcify_Renderer::repair_flattened_blocks( (string) $base );
                update_post_meta( $post_id, '_falcify_content', Falcify_Renderer::kses_falc( (string) $base ) );
                update_post_meta( $post_id, '_falcify_content_pictos', $content );
            } else {
                // Pas de pictos — injection automatique.
                $injected = Falcify_Renderer::repair_flattened_blocks( Falcify_Renderer::inject_pictos_fallback( $content ) );
                update_post_meta( $post_id, '_falcify_content', $content );
                update_post_meta( $post_id, '_falcify_content_pictos', Falcify_Renderer::kses_falc( $injected ) );
            }
        } else {
            update_post_meta( $post_id, '_falcify_content', $content );
            if ( $content === '' ) {
                delete_post_meta( $post_id, '_falcify_content_pictos' );
            }
        }

        $current = get_post_meta( $post_id, '_falcify_status', true );
        if ( $current === 'published' ) {
            update_post_meta( $post_id, '_falcify_status', 'validated' );
        } elseif ( ! $current && $content !== '' ) {
            update_post_meta( $post_id, '_falcify_status', 'draft' );
        }

        $word_count = str_word_count( wp_strip_all_tags( $content ) );
        update_post_meta( $post_id, '_falcify_word_count', $word_count );

        return array(
            'content'    => $content,
            'status'     => get_post_meta( $post_id, '_falcify_status', true ),
            'word_count' => $word_count,
        );
    }

    public static function ajax_estimate() {
        check_ajax_referer( 'falcify_admin', 'nonce' );
        $post_id = absint( wp_unslash( $_POST['post_id'] ?? 0 ) );
        if ( ! $post_id || ! current_user_can( 'edit_post', $post_id ) ) {
            wp_send_json_error( array( 'message' => esc_html__( 'Action non autorisée.', 'falcify-connector' ) ), 403 );
        }
        $payload = self::get_post_payload( $post_id );
        if ( $payload === 'missing_api_key' ) wp_send_json_error( array( 'error' => esc_html__( 'Clé API manquante. Configurez-la dans Réglages > Falcify.', 'falcify-connector' ) ), 400 );
        if ( ! $payload ) wp_send_json_error( array( 'error' => esc_html__( 'Contenu introuvable.', 'falcify-connector' ) ), 404 );
        $r = self::request( '/api/wordpress/estimate', $payload );
        if ( ! $r['ok'] ) wp_send_json_error( $r['data'] ?: array( 'error' => $r['error'] ?? esc_html__( 'Erreur', 'falcify-connector' ) ), $r['status'] ?? 400 );
        wp_send_json_success( $r['data'] );
    }

    public static function ajax_generate() {
        check_ajax_referer( 'falcify_admin', 'nonce' );
        $post_id = absint( wp_unslash( $_POST['post_id'] ?? 0 ) );
        if ( ! $post_id || ! current_user_can( 'edit_post', $post_id ) ) {
            wp_send_json_error( array( 'message' => esc_html__( 'Action non autorisée.', 'falcify-connector' ) ), 403 );
        }
        $payload = self::get_post_payload( $post_id );
        if ( $payload === 'missing_api_key' ) wp_send_json_error( array( 'error' => esc_html__( 'Clé API manquante. Configurez-la dans Réglages > Falcify.', 'falcify-connector' ) ), 400 );
        if ( ! $payload ) wp_send_json_error( array( 'error' => esc_html__( 'Contenu introuvable.', 'falcify-connector' ) ), 404 );
        $allowed_modes = array( 'standard', 'strict', 'medico-social', 'administratif', 'enfants', 'seniors' );
        $mode = isset( $_POST['mode'] ) ? sanitize_key( wp_unslash( $_POST['mode'] ) ) : '';
        if ( ! in_array( $mode, $allowed_modes, true ) ) {
            $mode = Falcify_Settings::get_value( 'strict_mode' ) ? 'strict' : 'standard';
        }
        $payload['mode']   = $mode;
        $payload['strict'] = ( $mode === 'strict' );

        $r = self::request( '/api/wordpress/falcify', $payload );

        if ( ! $r['ok'] || empty( $r['data']['success'] ) ) {
            wp_send_json_error( $r['data'] ?: array( 'error' => $r['error'] ?? esc_html__( 'Erreur', 'falcify-connector' ) ), $r['status'] ?? 400 );
        }
        $d = $r['data'];

        $falc_content = Falcify_Renderer::repair_flattened_blocks( Falcify_Renderer::kses_falc( $d['falc_content'] ) );
        update_post_meta( $post_id, '_falcify_content', $falc_content );

        $falc_pictos = isset( $d['falc_content_pictos'] ) && $d['falc_content_pictos'] !== ''
            ? Falcify_Renderer::kses_falc( Falcify_Renderer::repair_flattened_blocks( $d['falc_content_pictos'] ) )
            : '';
        // Si le SaaS n'a pas renvoyé de pictos, ou a renvoyé du texte sans
        // balises <img> (version sans pictogrammes), on injecte les pictos PHP.
        if ( $falc_content !== '' && ( $falc_pictos === '' || false === strpos( $falc_pictos, '<img' ) ) ) {
            $falc_pictos = Falcify_Renderer::kses_falc(
                Falcify_Renderer::repair_flattened_blocks( Falcify_Renderer::inject_pictos_fallback( $falc_content ) )
            );
        }
        update_post_meta( $post_id, '_falcify_content_pictos', $falc_pictos );

        update_post_meta( $post_id, '_falcify_status', 'draft' );
        update_post_meta( $post_id, '_falcify_mode', $mode );
        update_post_meta( $post_id, '_falcify_last_generated_at', current_time( 'mysql' ) );
        update_post_meta( $post_id, '_falcify_word_count', absint( $d['word_count'] ?? 0 ) );
        update_post_meta( $post_id, '_falcify_generation_id', sanitize_text_field( $d['generation_id'] ?? '' ) );
        $d['pictos_html'] = $falc_pictos;
        wp_send_json_success( $d );
    }

    public static function ajax_validate() {
        check_ajax_referer( 'falcify_admin', 'nonce' );
        $post_id = absint( wp_unslash( $_POST['post_id'] ?? 0 ) );
        if ( ! $post_id || ! current_user_can( 'edit_post', $post_id ) ) {
            wp_send_json_error( array( 'message' => esc_html__( 'Action non autorisée.', 'falcify-connector' ) ), 403 );
        }
        update_post_meta( $post_id, '_falcify_status', 'validated' );
        wp_send_json_success( array( 'status' => 'validated' ) );
    }

    public static function ajax_set_status() {
        check_ajax_referer( 'falcify_admin', 'nonce' );
        $post_id = absint( wp_unslash( $_POST['post_id'] ?? 0 ) );
        $status  = sanitize_key( wp_unslash( $_POST['status'] ?? '' ) );
        $raw_content = isset( $_POST['content'] ) ? (string) wp_unslash( $_POST['content'] ) : '';
        $allowed = array( 'draft', 'validated', 'published' );
        if ( ! $post_id || ! current_user_can( 'edit_post', $post_id ) ) {
            wp_send_json_error( array( 'message' => esc_html__( 'Action non autorisée.', 'falcify-connector' ) ), 403 );
        }
        if ( ! in_array( $status, $allowed, true ) ) {
            wp_send_json_error( array( 'error' => esc_html__( 'Statut invalide.', 'falcify-connector' ) ), 400 );
        }
        if ( $raw_content !== '' ) {
            self::sync_falc_meta( $post_id, $raw_content );
        }
        $content = (string) get_post_meta( $post_id, '_falcify_content', true );
        if ( $content !== '' && class_exists( 'Falcify_Renderer' ) ) {
            $has_pictos = false !== strpos( $content, 'falc-picto' );
            if ( $has_pictos ) {
                $base = preg_replace( '#<span[^>]*class="[^"]*falc-picto[^"]*"[^>]*>[\s\S]*?</span>\s*#is', '', $content );
                $base = Falcify_Renderer::repair_flattened_blocks( (string) $base );
                update_post_meta( $post_id, '_falcify_content', Falcify_Renderer::kses_falc( (string) $base ) );
                update_post_meta( $post_id, '_falcify_content_pictos', Falcify_Renderer::kses_falc( $content ) );
            } else {
                $content  = Falcify_Renderer::repair_flattened_blocks( $content );
                $pictos   = Falcify_Renderer::inject_pictos_fallback( $content );
                $clean    = Falcify_Renderer::kses_falc( $content );
                $cleanPic = Falcify_Renderer::kses_falc( Falcify_Renderer::repair_flattened_blocks( $pictos ) );
                update_post_meta( $post_id, '_falcify_content', $clean );
                update_post_meta( $post_id, '_falcify_content_pictos', $cleanPic );
            }
        }
        update_post_meta( $post_id, '_falcify_status', $status );
        wp_send_json_success( array( 'status' => $status ) );
    }

    public static function ajax_save_content() {
        check_ajax_referer( 'falcify_admin', 'nonce' );
        $post_id = absint( wp_unslash( $_POST['post_id'] ?? 0 ) );
        if ( ! $post_id || ! current_user_can( 'edit_post', $post_id ) ) {
            wp_send_json_error( array( 'message' => esc_html__( 'Action non autorisée.', 'falcify-connector' ) ), 403 );
        }
        // v2.7.13 — utiliser kses_falc() au lieu de wp_kses_post pour
        // préserver les attributs ARIA / data-picto sur les pictos insérés
        // manuellement depuis la banque (sinon le wrapper perd `data-picto`,
        // `role`, `aria-label`, `title` et l'image).
        $raw_content = isset( $_POST['content'] ) ? (string) wp_unslash( $_POST['content'] ) : '';
        $saved = self::sync_falc_meta( $post_id, $raw_content );
        wp_send_json_success( array( 'status' => $saved['status'], 'word_count' => $saved['word_count'] ) );
    }

    public static function sync_post_save( $post_id, $post, $update ) {
        if ( ! $update || ! $post || wp_is_post_revision( $post_id ) ) return;
        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
        if ( ! current_user_can( 'edit_post', $post_id ) ) return;
        if ( ! Falcify_Post_Types::is_enabled( $post->post_type ) ) return;

        $nonce = isset( $_POST['falcify_metabox_nonce'] )
            ? sanitize_text_field( wp_unslash( $_POST['falcify_metabox_nonce'] ) )
            : '';
        if ( $nonce === '' || ! wp_verify_nonce( $nonce, 'falcify_metabox_save_' . $post_id ) ) return;

        $field = 'falcify_content_' . $post_id;
        if ( ! array_key_exists( $field, $_POST ) ) return;

        $raw_content = (string) wp_unslash( $_POST[ $field ] );
        self::sync_falc_meta( $post_id, $raw_content );
    }
    /**
     * Régénère uniquement la version pictogrammée (`_falcify_content_pictos`)
     * en relançant `Falcify_Renderer::inject_pictos_fallback()` sur la meta
     * `_falcify_content`. Aucun appel SaaS, aucun crédit consommé.
     */
    public static function ajax_regenerate_pictos() {
        check_ajax_referer( 'falcify_admin', 'nonce' );
        $post_id = absint( wp_unslash( $_POST['post_id'] ?? 0 ) );
        if ( ! $post_id || ! current_user_can( 'edit_post', $post_id ) ) {
            wp_send_json_error( array( 'message' => esc_html__( 'Action non autorisée.', 'falcify-connector' ) ), 403 );
        }
        $base = (string) get_post_meta( $post_id, '_falcify_content', true );
        if ( $base === '' ) {
            wp_send_json_error( array( 'error' => esc_html__( 'Aucun contenu FALC à pictogrammer. Générez d\'abord la version FALC.', 'falcify-connector' ) ), 400 );
        }
        $base     = Falcify_Renderer::repair_flattened_blocks( $base );
        $injected = Falcify_Renderer::repair_flattened_blocks( Falcify_Renderer::inject_pictos_fallback( $base ) );
        $clean    = Falcify_Renderer::kses_falc( $injected );
        update_post_meta( $post_id, '_falcify_content', Falcify_Renderer::kses_falc( $base ) );
        update_post_meta( $post_id, '_falcify_content_pictos', $clean );
        wp_send_json_success( array(
            'pictos_html' => $clean,
            'changed'     => $injected !== $base,
        ) );
    }
}
