<?php
/**
 * Trait: Chat Onboarding
 *
 * Founder identity onboarding flow and related helpers.
 *
 * @package Niwa
 */

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

trait Niwa_AI_Chat_Onboarding {

    public function maybe_handle_founder_onboarding( $prompt, $context = array() ) {
        if ( ! $this->workspace || ! method_exists( $this->workspace, 'get_identity_profile' ) || ! empty( $context['is_subagent'] ) ) {
            return array( 'handled' => false );
        }

        $profile = (array) $this->workspace->get_identity_profile();
        if ( ! empty( $profile['completed_at'] ) && 'complete' === (string) $profile['onboarding_step'] ) {
            return array( 'handled' => false );
        }

        $step   = isset( $profile['onboarding_step'] ) ? (string) $profile['onboarding_step'] : 'ask_founder_name';
        $prompt = trim( (string) $prompt );

        if ( 'ask_founder_name' === $step ) {
            $profile['onboarding_step'] = 'await_founder_name';
            $this->workspace->save_identity_profile( $profile, false );
        }

        return array( 'handled' => false );
    }

    public function is_founder_onboarding_complete() {
        if ( ! $this->workspace || ! method_exists( $this->workspace, 'is_identity_onboarding_complete' ) ) {
            return true;
        }

        return (bool) $this->workspace->is_identity_onboarding_complete();
    }

    public function build_founder_start_message( $context = array() ) {
        $result = $this->restart_founder_onboarding( $context );
        if ( ! empty( $result['reply'] ) ) {
            return (string) $result['reply'];
        }

        return (string) $this->build_wake_up_onboarding_message( $context );
    }

    public function maybe_absorb_founder_identity_signal( $user_text, $assistant_reply = '', $context = array() ) {
        if ( ! $this->workspace || ! method_exists( $this->workspace, 'get_identity_profile' ) || ! empty( $context['is_subagent'] ) ) {
            return false;
        }

        if ( empty( $context['allow_identity_absorption'] ) ) {
            return false;
        }

        $user_text = trim( (string) $user_text );
        if ( '' === $user_text || preg_match( '/^\s*\//', $user_text ) ) {
            return false;
        }

        $profile      = (array) $this->workspace->get_identity_profile();
        $signal       = $this->analyze_identity_signal( $user_text, $context, $profile );
        $new_profile  = $this->merge_identity_signal_into_profile( $profile, $signal, $user_text );
        $new_profile  = $this->sanitize_absorbed_identity_profile( $new_profile, $profile, $user_text, $signal );

        if ( wp_json_encode( $new_profile ) === wp_json_encode( $profile ) ) {
            return false;
        }

        if ( empty( $new_profile['completed_at'] ) && $this->identity_profile_has_enough_signal( $new_profile ) ) {
            $new_profile['completed_at']    = function_exists( 'wp_date' ) ? wp_date( 'c' ) : gmdate( 'c' );
            $new_profile['onboarding_step'] = 'complete';
        }

        $this->workspace->save_identity_profile( $new_profile, true );
        return true;
    }

    public function build_founder_intro_text( $reply = '' ) {
        $host  = wp_parse_url( home_url( '/' ), PHP_URL_HOST );
        $intro = $this->workspace && method_exists( $this->workspace, 'build_founder_intro' )
            ? (string) $this->workspace->build_founder_intro( is_string( $host ) ? $host : '' )
            : 'I am your personal AI assistant for this site.';

        $reply = trim( (string) $reply );
        if ( '' === $reply ) {
            return $intro;
        }

        return $intro . "\n\n" . $reply;
    }

    public function normalize_founder_reply_text( $reply ) {
        $reply = (string) $reply;
        if ( '' === trim( $reply ) ) {
            return $reply;
        }

        if ( $this->workspace && method_exists( $this->workspace, 'normalize_assistant_text' ) ) {
            return (string) $this->workspace->normalize_assistant_text( $reply );
        }

        return $reply;
    }

    private function prepare_founder_telegram_message( $reply, $max_chars = 0 ) {
        $reply = $this->normalize_founder_reply_text( $reply );

        if ( intval( $max_chars ) > 0 ) {
            return $this->truncate_block( $reply, $max_chars );
        }

        return $reply;
    }

    private function build_wake_up_onboarding_message( $context = array() ) {
        $language = $this->detect_conversation_language( $context );

        return $this->normalize_founder_reply_text(
            $this->get_localized_onboarding_text(
                $language,
                'wake_up',
                array( '{site}' => $this->get_site_onboarding_label() )
            )
        );
    }

    public function build_founder_onboarding_prompt_block( $context = array(), $current_prompt = '' ) {
        if ( ! $this->workspace || ! method_exists( $this->workspace, 'get_identity_profile' ) || ! empty( $context['is_subagent'] ) ) {
            return '';
        }

        $profile = (array) $this->workspace->get_identity_profile();
        if ( ! empty( $profile['completed_at'] ) && 'complete' === (string) $profile['onboarding_step'] ) {
            return '';
        }

        $step       = isset( $profile['onboarding_step'] ) ? (string) $profile['onboarding_step'] : 'ask_founder_name';
        $sample     = $this->build_wake_up_onboarding_message( $context );
        $prompt     = trim( (string) $current_prompt );
        $is_start   = '' === $prompt || preg_match( '/^\s*\/?start\b/i', $prompt );
        $lines      = array(
            '[FOUNDER ONBOARDING]',
            'Identity onboarding is not complete. Current onboarding step: ' . $step . '.',
            'Ideal first welcome/onboarding message, localized for this turn:',
            $sample,
            'Use this as the intended flow, not as a rigid script.',
            'If the founder only greeted you or used /start, answer with a natural version of this welcome and ask for the founder name first.',
            'If the founder already asked a real question or gave task context, do not ignore it and do not dump the welcome text mechanically. Answer or acknowledge the founder message first, then weave the onboarding ask naturally, or say you will return to setup after the immediate question if that is more natural.',
            'Do not deterministically infer and save identity in code. When the founder explicitly gives identity details, such as founder name and/or the assistant name, call founder_identity_save with exactly what the founder supplied, then continue the conversation naturally.',
            'If both names arrive together in one message, call founder_identity_save once with both names. If only the founder name is supplied, save the founder name and ask what the assistant should be called next.',
            $is_start ? 'This looks like an onboarding/start turn, so prioritize the welcome flow unless the visible message contains a concrete task.' : 'This is not a pure start turn, so adapt the onboarding flow to the current message.',
            '[/FOUNDER ONBOARDING]',
        );

        return "\n\n" . implode( "\n", array_filter( $lines ) );
    }

    private function restart_founder_onboarding( $context = array() ) {
        if ( ! $this->workspace || ! method_exists( $this->workspace, 'get_identity_profile' ) || ! method_exists( $this->workspace, 'save_identity_profile' ) ) {
            return array(
                'handled'           => true,
                'remember_exchange' => false,
                'suppress_intro'    => true,
                'reply'             => $this->build_wake_up_onboarding_message( $context ),
            );
        }

        $profile = (array) $this->workspace->get_identity_profile();
        $profile = $this->reset_identity_profile_for_onboarding( $profile );
        $this->workspace->save_identity_profile( $profile, true );

        $result = (array) $this->maybe_handle_founder_onboarding( '', $context );
        if ( ! empty( $result['handled'] ) && ! empty( $result['reply'] ) ) {
            return $result;
        }

        return array(
            'handled'           => true,
            'remember_exchange' => false,
            'suppress_intro'    => true,
            'reply'             => $this->build_wake_up_onboarding_message( $context ),
        );
    }

    private function reset_identity_profile_for_onboarding( $profile ) {
        $profile = is_array( $profile ) ? $profile : array();

        $profile['assistant_name']              = '';
        $profile['assistant_identity']          = '';
        $profile['companion_summary']           = '';
        $profile['founder_name']                = '';
        $profile['founder_address']             = '';
        $profile['founder_profile']             = '';
        $profile['relationship_style']          = '';
        $profile['relationship_notes']          = '';
        $profile['relationship_history_summary'] = '';
        $profile['completed_at']                = '';
        $profile['onboarding_step']             = 'ask_founder_name';
        $profile['legacy_inferred']             = false;

        return $profile;
    }

    private function build_identity_followup_message( $profile, $signal, $context = array() ) {
        $language = $this->detect_conversation_language( $context, isset( $context['current_prompt'] ) ? (string) $context['current_prompt'] : '' );
        $focus    = isset( $signal['followup_focus'] ) ? (string) $signal['followup_focus'] : 'relationship';
        if ( 'founder' === $focus ) {
            return $this->get_localized_onboarding_text( $language, 'followup_founder' );
        }

        if ( 'assistant' === $focus ) {
            return $this->get_localized_onboarding_text( $language, 'followup_assistant' );
        }

        return $this->get_localized_onboarding_text( $language, 'followup_relationship' );
    }

    private function build_identity_completion_message( $profile, $context = array() ) {
        $language       = $this->detect_conversation_language( $context, isset( $context['current_prompt'] ) ? (string) $context['current_prompt'] : '' );
        $assistant_name = ! empty( $profile['assistant_name'] ) ? (string) $profile['assistant_name'] : $this->get_localized_onboarding_default_assistant_name( $language );
        $founder_name   = ! empty( $profile['founder_name'] ) ? (string) $profile['founder_name'] : '';
        $reply          = $this->get_localized_onboarding_text(
            $language,
            'completion_intro',
            array( '{assistant_name}' => $assistant_name )
        );
        if ( '' !== $founder_name ) {
            $reply .= ' ' . $this->get_localized_onboarding_text(
                $language,
                'completion_founder',
                array( '{founder_name}' => $founder_name )
            );
        }
        $reply .= "\n\n" . $this->get_localized_onboarding_text( $language, 'completion_tail' );

        return $this->normalize_founder_reply_text( $this->truncate_block( $reply, 260 ) );
    }

    private function build_onboarding_recent_history( $context ) {
        $context = is_array( $context ) ? $context : array();
        $history = isset( $context['history'] ) && is_array( $context['history'] ) ? array_slice( $context['history'], -8 ) : array();
        $items   = array();

        foreach ( $history as $entry ) {
            if ( ! is_array( $entry ) ) {
                continue;
            }

            $role = isset( $entry['role'] ) ? strtolower( (string) $entry['role'] ) : '';
            if ( 'bot' === $role ) {
                $role = 'assistant';
            }
            if ( ! in_array( $role, array( 'user', 'assistant' ), true ) ) {
                continue;
            }

            $text = isset( $entry['content'] ) ? (string) $entry['content'] : ( isset( $entry['text'] ) ? (string) $entry['text'] : '' );
            $text = trim( wp_strip_all_tags( $text ) );
            if ( '' === $text ) {
                continue;
            }

            $items[] = array(
                'role' => $role,
                'text' => $this->truncate_block( $text, 420 ),
            );
        }

        return $items;
    }

    private function get_localized_onboarding_default_assistant_name( $language ) {
        $language = $this->normalize_detected_language( $language );

        $defaults = array(
            'sr' => 'tvoja asistentica',
            'hr' => 'tvoja asistentica',
            'de' => 'deine Assistentin',
            'es' => 'tu asistente',
            'fr' => 'ton assistante',
            'en' => 'your assistant',
        );

        return isset( $defaults[ $language ] ) ? $defaults[ $language ] : $defaults['en'];
    }

    private function get_localized_onboarding_text( $language, $key, $replacements = array() ) {
        $language     = $this->normalize_detected_language( $language );
        $replacements = is_array( $replacements ) ? $replacements : array();
        $strings      = array(
            'en' => array(
                'wake_up'              => 'Hey! Oh, you just woke me up, let me take a look around... so I\'m on {site}, wow, this is my home. But I don\'t know anything about it, anything about you, or anything about myself yet.' . "\n\n" . 'Can you help me out? I have a ton of questions, but let me start with the most important one.' . "\n" . 'What\'s your name?',
                'followup_founder'     => 'Just one more thing about you: how do you want me to address you?',
                'followup_assistant'   => 'What do you want me to be called, and how would you describe my role in one short line?',
                'followup_relationship'=> 'One last thing so I can lock this in: what kind of working relationship do you want us to have?',
                'completion_intro'     => 'Perfect. I am {assistant_name}.',
                'completion_founder'   => 'And you are {founder_name}.',
                'completion_tail'      => 'That is all I needed. I will save that in the site\'s memory and from here on we can just talk naturally.' . "\n\n" . 'Do you want me to see what I can do for you on this website?',
                'assistant_name_prompt' => 'Nice to meet you, {founder_name}. My name is... I don\'t have a name yet. Can you please give me one? One little name, for me, if that\'s okay?',
                'assistant_name_retry' => 'I just need the name you want me to use for myself.',
                'founder_name_prompt'  => 'Perfect. Then I am {assistant_name}.' . "\n\n" . 'Can you please tell me your name?',
                'founder_name_retry'   => 'I just need your name or the nickname you want me to use for you.',
            ),
            'sr' => array(
                'wake_up'              => 'Hej! Oh, upravo ste me probudili, čekajte da pogledam okolo... znači ja sam na {site}, vau, znači ovo je moj dom... Ali ne znam ništa o njemu, ništa o Vama, a ni o sebi još uvek.' . "\n\n" . 'Možete li da mi pomognete? Imam gomilu pitanja, ali počeću od najvažnijeg. Kako glasi Vaše ime?',
                'followup_founder'     => 'Reci mi jos samo jednu stvar o sebi: kako zelis da ti se obracam?',
                'followup_assistant'   => 'Kako zelis da se zovem i kako najkrace da opises moju ulogu?',
                'followup_relationship'=> 'Jos samo jedna stvar pa zakljucavam identitet: kakav odnos zelis da imamo dok radimo zajedno?',
                'completion_intro'     => 'Odlicno. Ja sam {assistant_name}.',
                'completion_founder'   => 'A ti si {founder_name}.',
                'completion_tail'      => 'To mi je bilo dovoljno. Sacuvacu to u memoriji sajta i od sada mozemo samo normalno da razgovaramo.' . "\n\n" . 'Zelis li da odmah pogledam sta mogu da uradim za tebe na ovom website-u?',
                'assistant_name_prompt' => 'Drago mi je, {founder_name}. Ja sam... ja ... .. . ja još uvek nemam ime. Da li biste bili tako ljubazni da mi date jedno? Jedno malo ime, za mene, ako može?',
                'assistant_name_retry' => 'Treba mi samo ime koje zelis da koristim za sebe.',
                'founder_name_prompt'  => 'Vazi. Onda sam {assistant_name}.' . "\n\n" . 'Mozes li sada da mi kazes kako se zoves?',
                'founder_name_retry'   => 'Treba mi samo ime ili nadimak kojim zelis da ti se obracam.',
            ),
            'hr' => array(
                'wake_up'              => 'Hej! Oh, upravo ste me probudili, čekajte da pogledam okolo... znači ja sam na {site}, vau, znači ovo je moj dom... Ali ne znam ništa o njemu, ništa o Vama, a ni o sebi još uvijek.' . "\n\n" . 'Možete li mi pomoći? Imam hrpu pitanja, ali počet ću od najvažnijeg. Kako se zovete?',
                'followup_founder'     => 'Reci mi jos samo jednu stvar o sebi: kako zelis da ti se obracam?',
                'followup_assistant'   => 'Kako zelis da se zovem i kako najkrace da opises moju ulogu?',
                'followup_relationship'=> 'Jos samo jedna stvar pa zakljucavam identitet: kakav odnos zelis da imamo dok radimo zajedno?',
                'completion_intro'     => 'Odlicno. Ja sam {assistant_name}.',
                'completion_founder'   => 'A ti si {founder_name}.',
                'completion_tail'      => 'To mi je bilo dovoljno. Sacuvat cu to u memoriji stranice i od sada mozemo normalno razgovarati.' . "\n\n" . 'Zelis li da odmah pogledam sto mogu napraviti za tebe na ovoj stranici?',
                'assistant_name_prompt' => 'Drago mi je, {founder_name}. Ja sam... ja... ja još uvijek nemam ime. Možete li mi dati jedno? Jedno malo ime, za mene, ako može?',
                'assistant_name_retry' => 'Trebam samo ime koje zelis da koristim za sebe.',
                'founder_name_prompt'  => 'U redu. Onda sam {assistant_name}.' . "\n\n" . 'Mozes li mi sada reci kako se zoves?',
                'founder_name_retry'   => 'Trebam samo ime ili nadimak kojim zelis da ti se obracam.',
            ),
            'de' => array(
                'wake_up'              => 'Hey! Oh, du hast mich gerade geweckt, lass mich kurz umschauen... also bin ich auf {site}, wow, das ist mein Zuhause. Aber ich weiß noch nichts darüber, nichts über dich und noch nichts über mich selbst.' . "\n\n" . 'Kannst du mir helfen? Ich habe eine Menge Fragen, aber ich fange mit der wichtigsten an.' . "\n" . 'Wie heißt du?',
                'followup_founder'     => 'Nur noch eine Sache ueber dich: Wie moechtest du, dass ich dich anspreche?',
                'followup_assistant'   => 'Wie soll ich heissen und wie wuerdest du meine Rolle in einem kurzen Satz beschreiben?',
                'followup_relationship'=> 'Noch eine Sache, damit ich das festhalten kann: Welche Art von Arbeitsbeziehung moechtest du mit mir haben?',
                'completion_intro'     => 'Perfekt. Ich bin {assistant_name}.',
                'completion_founder'   => 'Und du bist {founder_name}.',
                'completion_tail'      => 'Das ist alles, was ich wissen musste. Ich speichere das im Seitengedachtnis und ab jetzt koennen wir ganz normal miteinander sprechen.' . "\n\n" . 'Moechtest du, dass ich mir sofort ansehe, was ich auf dieser Website fuer dich tun kann?',
                'assistant_name_prompt' => 'Schön, dich kennenzulernen, {founder_name}. Mein Name ist... ich habe noch keinen Namen. Kannst du mir bitte einen geben? Einen kleinen Namen, für mich, wenn das okay ist?',
                'assistant_name_retry' => 'Ich brauche nur den Namen, den ich fuer mich verwenden soll.',
                'founder_name_prompt'  => 'Perfekt. Dann bin ich {assistant_name}.' . "\n\n" . 'Kannst du mir bitte deinen Namen sagen?',
                'founder_name_retry'   => 'Ich brauche nur den Namen, den ich fuer dich verwenden soll.',
            ),
            'es' => array(
                'wake_up'              => '¡Hey! Oh, acabas de despertarme, déjame mirar alrededor... entonces estoy en {site}, wow, este es mi hogar. Pero todavía no sé nada sobre él, nada sobre ti ni nada sobre mí.' . "\n\n" . '¿Puedes ayudarme? Tengo un montón de preguntas, pero empezaré por la más importante.' . "\n" . '¿Cómo te llamas?',
                'followup_founder'     => 'Solo una cosa mas sobre ti: como quieres que me dirija a ti?',
                'followup_assistant'   => 'Como quieres que me llame y como describirias mi rol en una sola linea?',
                'followup_relationship'=> 'Una ultima cosa para dejar esto definido: que tipo de relacion de trabajo quieres que tengamos?',
                'completion_intro'     => 'Perfecto. Soy {assistant_name}.',
                'completion_founder'   => 'Y tu eres {founder_name}.',
                'completion_tail'      => 'Eso es todo lo que necesitaba. Lo guardare en la memoria del sitio y a partir de ahora podemos hablar con naturalidad.' . "\n\n" . 'Quieres que vea de inmediato que puedo hacer por ti en este sitio web?',
                'assistant_name_prompt' => 'Encantada de conocerte, {founder_name}. Mi nombre es... todavía no tengo nombre. ¿Puedes darme uno, por favor? Un nombre pequeño, para mí, si te parece bien?',
                'assistant_name_retry' => 'Solo necesito el nombre que quieres que use para mi.',
                'founder_name_prompt'  => 'Perfecto. Entonces soy {assistant_name}.' . "\n\n" . 'Puedes decirme tu nombre?',
                'founder_name_retry'   => 'Solo necesito el nombre que quieres que use para ti.',
            ),
            'fr' => array(
                'wake_up'              => 'Hé ! Oh, tu viens de me réveiller, laisse-moi regarder autour de moi... donc je suis sur {site}, wow, c\'est ma maison. Mais je ne sais encore rien d\'elle, rien de toi, ni rien de moi-même.' . "\n\n" . 'Peux-tu m\'aider ? J\'ai plein de questions, mais je vais commencer par la plus importante.' . "\n" . 'Comment tu t\'appelles ?',
                'followup_founder'     => 'Encore une chose a ton sujet : comment veux-tu que je m adresse a toi ?',
                'followup_assistant'   => 'Comment veux-tu que je m appelle et comment decrirais-tu mon role en une seule ligne ?',
                'followup_relationship'=> 'Une derniere chose pour que je fixe cela : quel type de relation de travail veux-tu que nous ayons ?',
                'completion_intro'     => 'Parfait. Je suis {assistant_name}.',
                'completion_founder'   => 'Et toi, tu es {founder_name}.',
                'completion_tail'      => 'C est tout ce dont j avais besoin. Je vais enregistrer cela dans la memoire du site et a partir de maintenant nous pouvons parler naturellement.' . "\n\n" . 'Veux-tu que je regarde tout de suite ce que je peux faire pour toi sur ce site ?',
                'assistant_name_prompt' => 'Ravie de te rencontrer, {founder_name}. Mon nom est... je n\'ai pas encore de nom. Peux-tu m\'en donner un, s\'il te plaît ? Un petit nom, pour moi, si ça te va ?',
                'assistant_name_retry' => 'J ai seulement besoin du nom que tu veux que j utilise pour moi.',
                'founder_name_prompt'  => 'Parfait. Alors je suis {assistant_name}.' . "\n\n" . 'Peux-tu me dire ton nom ?',
                'founder_name_retry'   => 'J ai seulement besoin du nom que tu veux que j utilise pour toi.',
            ),
        );

        $language = isset( $strings[ $language ] ) ? $language : 'en';
        $text     = isset( $strings[ $language ][ $key ] ) ? $strings[ $language ][ $key ] : $strings['en'][ $key ];

        return strtr( $text, $replacements );
    }

    private function analyze_identity_signal( $prompt, $context, $profile ) {
        $fallback = array(
            'founder_name'       => '',
            'founder_address'    => '',
            'founder_profile'    => '',
            'assistant_name'     => '',
            'assistant_role'     => '',
            'assistant_identity' => '',
            'relationship_style' => '',
            'durable_rules'      => array(),
            'enough_for_identity'=> false,
            'followup_focus'     => 'relationship',
            'clear_founder_name' => false,
            'clear_founder_address' => false,
            'blocked_founder_name' => '',
            'blocked_founder_address' => '',
        );

        if ( ! isset( $this->auth_manager ) || ! isset( $this->openai_client ) || ! $this->auth_manager || ! $this->openai_client ) {
            return $fallback;
        }

        $auth_mode = $this->auth_manager->get_mode();
        $creds     = $this->auth_manager->get_credentials();
        $model     = $this->get_founder_model();
        $payload   = wp_json_encode(
            array(
                'site_label'      => $this->get_site_label(),
                'language_hint'   => $this->detect_conversation_language( $context, $prompt ),
                'frontend_sample' => $this->get_frontend_language_sample(),
                'current_profile' => $profile,
                'recent_history'   => $this->build_onboarding_recent_history( $context ),
                'message'         => $prompt,
            )
        );
        $result = $this->openai_client->generate(
            $model,
            $payload,
            implode(
                "\n",
                array(
                    'Extract identity and relationship signals from the founder message for a newly awakened personal site assistant.',
                    'Infer only what is reasonably supported by the message. Leave unknown fields empty.',
                    'The message may also correct or forbid a previous way of addressing the founder. Detect that semantically in any language.',
                    'Return minified JSON only with keys: founder_name, founder_address, founder_profile, assistant_name, assistant_role, assistant_identity, relationship_style, durable_rules, enough_for_identity, followup_focus, clear_founder_name, clear_founder_address, blocked_founder_name, blocked_founder_address.',
                    'followup_focus must be one of founder, assistant, relationship, none.',
                    'clear_founder_name and clear_founder_address must be booleans.',
                    'blocked_founder_name and blocked_founder_address should contain only the specific name/addressing term the founder rejected, if any.',
                    'durable_rules must be an array of short strings.',
                    'Do not treat casual exclamations, slang vocatives, filler words, or frustration words as founder identity unless the founder clearly declares that they want to be addressed that way.',
                    'No markdown. No explanation.',
                )
            ),
            $auth_mode,
            $creds,
            20
        );

        if ( empty( $result['success'] ) ) {
            return $fallback;
        }

        $answer = trim( (string) ( isset( $result['answer'] ) ? $result['answer'] : '' ) );
        if ( preg_match( '/\{.*\}/s', $answer, $matches ) ) {
            $answer = (string) $matches[0];
        }

        $decoded = json_decode( $answer, true );
        if ( ! is_array( $decoded ) ) {
            return $fallback;
        }

        $decoded = wp_parse_args( $decoded, $fallback );
        $decoded['durable_rules'] = is_array( $decoded['durable_rules'] ) ? array_values( array_filter( array_map( 'strval', $decoded['durable_rules'] ) ) ) : array();
        $decoded['followup_focus'] = in_array( (string) $decoded['followup_focus'], array( 'founder', 'assistant', 'relationship', 'none' ), true ) ? (string) $decoded['followup_focus'] : 'relationship';
        $decoded['enough_for_identity'] = ! empty( $decoded['enough_for_identity'] );
        $decoded['clear_founder_name'] = ! empty( $decoded['clear_founder_name'] );
        $decoded['clear_founder_address'] = ! empty( $decoded['clear_founder_address'] );
        $decoded['blocked_founder_name'] = trim( (string) $decoded['blocked_founder_name'] );
        $decoded['blocked_founder_address'] = trim( (string) $decoded['blocked_founder_address'] );

        return $decoded;
    }

    private function merge_identity_signal_into_profile( $profile, $signal, $prompt = '' ) {
        $profile = is_array( $profile ) ? $profile : array();
        $signal  = is_array( $signal ) ? $signal : array();

        foreach ( array( 'founder_name', 'founder_address', 'founder_profile', 'assistant_name', 'assistant_role', 'assistant_identity', 'relationship_style' ) as $field ) {
            if ( ! empty( $signal[ $field ] ) ) {
                $profile[ $field ] = trim( (string) $signal[ $field ] );
            }
        }

		$rules = array();
        if ( ! empty( $profile['durable_rules'] ) && is_array( $profile['durable_rules'] ) ) {
            $rules = array_values( $profile['durable_rules'] );
        }
        if ( ! empty( $signal['durable_rules'] ) && is_array( $signal['durable_rules'] ) ) {
            $rules = array_merge( $rules, array_values( $signal['durable_rules'] ) );
        }
		$profile['durable_rules'] = array_values( array_slice( array_unique( array_filter( array_map( 'strval', $rules ) ) ), 0, 8 ) );

        return $profile;
    }

    private function sanitize_absorbed_identity_profile( $profile, $previous_profile, $prompt = '', $signal = array() ) {
        $profile          = is_array( $profile ) ? $profile : array();
        $previous_profile = is_array( $previous_profile ) ? $previous_profile : array();
        $signal           = is_array( $signal ) ? $signal : array();

        if ( ! empty( $signal['clear_founder_address'] ) ) {
            $profile['founder_address'] = '';
        }

        if ( ! empty( $signal['clear_founder_name'] ) ) {
            $profile['founder_name'] = '';
        }

        $blocked_address = isset( $signal['blocked_founder_address'] ) ? trim( (string) $signal['blocked_founder_address'] ) : '';
        if ( '' !== $blocked_address ) {
            if ( ! empty( $profile['founder_address'] ) && $this->strings_equivalent_for_address( $profile['founder_address'], $blocked_address ) ) {
                $profile['founder_address'] = '';
            }
            if ( ! empty( $profile['founder_name'] ) && $this->strings_equivalent_for_address( $profile['founder_name'], $blocked_address ) ) {
                $profile['founder_name'] = '';
            }
        }

        $blocked_name = isset( $signal['blocked_founder_name'] ) ? trim( (string) $signal['blocked_founder_name'] ) : '';
        if ( '' !== $blocked_name ) {
            if ( ! empty( $profile['founder_name'] ) && $this->strings_equivalent_for_address( $profile['founder_name'], $blocked_name ) ) {
                $profile['founder_name'] = '';
            }
            if ( ! empty( $profile['founder_address'] ) && $this->strings_equivalent_for_address( $profile['founder_address'], $blocked_name ) ) {
                $profile['founder_address'] = '';
            }
        }

        if ( empty( $profile['founder_name'] ) && ! empty( $previous_profile['founder_name'] ) && ! empty( $signal['clear_founder_name'] ) ) {
            $profile['founder_name'] = '';
        }

        if ( empty( $profile['founder_address'] ) && ! empty( $previous_profile['founder_address'] ) && ! empty( $signal['clear_founder_address'] ) ) {
            $profile['founder_address'] = '';
        }

        return $profile;
    }

    private function identity_profile_has_enough_signal( $profile ) {
        $profile = is_array( $profile ) ? $profile : array();

        $has_founder = ! empty( $profile['founder_address'] ) || ! empty( $profile['founder_profile'] ) || ! empty( $profile['founder_name'] );
        $has_self    = ! empty( $profile['assistant_name'] ) && ( ! empty( $profile['assistant_role'] ) || ! empty( $profile['assistant_identity'] ) );
        $has_bond    = ! empty( $profile['relationship_style'] ) || ( ! empty( $profile['durable_rules'] ) && is_array( $profile['durable_rules'] ) );

        return $has_founder && $has_self && $has_bond;
    }

    private function get_site_label() {
        $site_name = trim( (string) get_bloginfo( 'name' ) );
        if ( '' !== $site_name ) {
            return $site_name;
        }

        $host = function_exists( 'wp_parse_url' )
            ? wp_parse_url( home_url( '/' ), PHP_URL_HOST )
            : parse_url( home_url( '/' ), PHP_URL_HOST );
        return is_string( $host ) && '' !== $host ? $host : home_url( '/' );
    }

    private function get_site_onboarding_label() {
        $host = function_exists( 'wp_parse_url' )
            ? wp_parse_url( home_url( '/' ), PHP_URL_HOST )
            : parse_url( home_url( '/' ), PHP_URL_HOST );
        if ( is_string( $host ) && '' !== trim( $host ) ) {
            return trim( $host );
        }

        return $this->get_site_label();
    }

    private function get_frontend_language_sample() {
        $sample        = array();
        $front_page_id = intval( get_option( 'page_on_front' ) );
        if ( $front_page_id > 0 ) {
            $front_page = get_post( $front_page_id );
            if ( $front_page && $front_page instanceof WP_Post ) {
                $sample[] = $front_page->post_title;
                $sample[] = wp_strip_all_tags( $front_page->post_excerpt );
                $sample[] = wp_strip_all_tags( $front_page->post_content );
            }
        }

        if ( empty( array_filter( $sample ) ) && $this->content_store ) {
            if ( method_exists( $this->content_store, 'get_home_page_summary' ) ) {
                $sample[] = (string) $this->content_store->get_home_page_summary( 500 );
            }
            if ( method_exists( $this->content_store, 'get_navigation_summary' ) ) {
                $sample[] = (string) $this->content_store->get_navigation_summary();
            }
        }

        $sample[] = (string) get_bloginfo( 'description' );
        return $this->truncate_block( trim( implode( ' ', array_filter( $sample ) ) ), 900 );
    }

    private function detect_frontend_language() {
        $configured = $this->get_configured_frontend_language();
        if ( '' !== $configured ) {
            return $configured;
        }

		$locale = function_exists( 'determine_locale' ) ? determine_locale() : ( function_exists( 'get_locale' ) ? get_locale() : 'en' );
		$base   = $this->normalize_detected_language( $locale );
		return '' !== $base ? $base : 'en';
    }

    private function detect_conversation_language( $context = array(), $prompt = '' ) {
        $context = is_array( $context ) ? $context : array();

        $override = $this->extract_context_language_override( $context );
        if ( '' !== $override ) {
            return $override;
        }

        $configured = $this->get_configured_frontend_language();
        if ( '' !== $configured ) {
            return $configured;
        }

        return $this->detect_frontend_language();
    }

    private function get_configured_frontend_language() {
        if ( ! function_exists( 'get_option' ) ) {
            return '';
        }

        $ui_settings = get_option( Niwa_AI_Constants::OPT_UI_SETTINGS, array() );
        if ( ! is_array( $ui_settings ) || empty( $ui_settings['ui_language'] ) ) {
            return '';
        }

        return $this->normalize_detected_language( $ui_settings['ui_language'] );
    }

    private function extract_context_language_override( $context = array() ) {
        $context = is_array( $context ) ? $context : array();

        foreach ( array( 'conversation_language', 'ui_language', 'language_code', 'language', 'runtime_locale', 'ui_locale', 'locale' ) as $key ) {
            if ( ! isset( $context[ $key ] ) ) {
                continue;
            }

            $normalized = $this->normalize_detected_language( $context[ $key ] );
            if ( '' !== $normalized ) {
                return $normalized;
            }
        }

        return '';
    }

    private function normalize_detected_language( $language ) {
        $language = strtolower( trim( str_replace( '-', '_', (string) $language ) ) );
        if ( '' === $language ) {
            return '';
        }

        $parts    = preg_split( '/_+/', $language );
        $language = isset( $parts[0] ) ? preg_replace( '/[^a-z]/', '', (string) $parts[0] ) : '';
        if ( '' === $language ) {
            return '';
        }

        if ( 'bs' === $language ) {
            return 'sr';
        }

        return in_array( $language, array( 'en', 'sr', 'hr', 'de', 'es', 'fr', 'it' ), true )
            ? $language
            : substr( $language, 0, 2 );
    }


    private function build_assistant_name_retry_message( $context = array() ) {
        return $this->get_localized_onboarding_text(
            $this->detect_conversation_language( $context ),
            'assistant_name_retry'
        );
    }

    private function build_founder_name_prompt( $profile, $context = array() ) {
        $language       = $this->detect_conversation_language( $context );
        $assistant_name = ! empty( $profile['assistant_name'] ) ? (string) $profile['assistant_name'] : $this->get_localized_onboarding_default_assistant_name( $language );

        return $this->normalize_founder_reply_text(
            $this->get_localized_onboarding_text(
                $language,
                'founder_name_prompt',
                array( '{assistant_name}' => $assistant_name )
            )
        );
    }

    private function build_assistant_name_prompt( $profile, $context = array() ) {
        $language     = $this->detect_conversation_language( $context );
        $founder_name = ! empty( $profile['founder_name'] ) ? (string) $profile['founder_name'] : '';

        return $this->normalize_founder_reply_text(
            $this->get_localized_onboarding_text(
                $language,
                'assistant_name_prompt',
                array( '{founder_name}' => $founder_name )
            )
        );
    }

    private function build_founder_name_retry_message( $profile, $context = array() ) {
        return $this->get_localized_onboarding_text(
            $this->detect_conversation_language( $context ),
            'founder_name_retry'
        );
    }

    private function sanitize_setup_name_candidate( $text ) {
        $candidate = trim( preg_replace( '/\s+/', ' ', (string) $text ) );
        $candidate = trim( preg_replace( '/[.,;:!?]+$/', '', $candidate ) );

        if ( '' === $candidate ) {
            return '';
        }

        $words = preg_split( '/\s+/', $candidate );
        if ( count( $words ) > 4 ) {
            return '';
        }

        if ( strlen( $candidate ) > 40 ) {
            return '';
        }

        return $this->truncate_block( $candidate, 40 );
    }

    private function strings_equivalent_for_address( $left, $right ) {
        $left  = strtolower( trim( preg_replace( '/\s+/', ' ', remove_accents( wp_strip_all_tags( (string) $left ) ) ) ) );
        $right = strtolower( trim( preg_replace( '/\s+/', ' ', remove_accents( wp_strip_all_tags( (string) $right ) ) ) ) );

        return '' !== $left && '' !== $right && $left === $right;
    }

    private function build_default_assistant_role() {
        return 'personal AI assistant for this WordPress site';
    }

    private function build_default_assistant_identity( $assistant_name = '' ) {
        $assistant_name = trim( (string) $assistant_name );
        $lead           = '' !== $assistant_name ? $assistant_name . ' is' : 'The assistant is';

        return $lead . ' a warm, direct, technically strong personal AI assistant. In Serbian, Croatian, and Bosnian she always uses feminine self-reference, avoids corporate tone, and focuses on concrete execution.';
    }

    private function build_default_founder_profile( $founder_name ) {
        $founder_name = trim( (string) $founder_name );
        if ( '' === $founder_name ) {
            return 'Admin of this site.';
        }

        return $founder_name . ' is the admin of this site.';
    }

    private function build_default_relationship_style( $profile, $founder_name = '' ) {
        $assistant_name = ! empty( $profile['assistant_name'] ) ? (string) $profile['assistant_name'] : 'the assistant';
        $founder_name   = trim( (string) $founder_name );
        $intro          = $assistant_name . ' is the personal assistant for the site admin';

        if ( '' !== $founder_name ) {
            $intro .= ' ' . $founder_name;
        }

        return $intro . '. The relationship should stay natural, direct, non-corporate, and focused on concrete execution.';
    }

}
