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

trait Niwa_AI_Chat_Session {

    private function format_operative_interval_minutes( $minutes ) {
        $minutes = max( 0.5, round( floatval( $minutes ), 2 ) );
        if ( $minutes < 1 ) {
            return intval( round( $minutes * 60 ) ) . ' sec';
        }

        return rtrim( rtrim( number_format( $minutes, 2, '.', '' ), '0' ), '.' ) . ' min';
    }

    public function get_session_status_text( $session_id ) {
        if ( ! $this->session_state || ! method_exists( $this->session_state, 'get_session_snapshot' ) ) {
            return 'Session runtime nije dostupan.';
        }

        $snapshot = $this->session_state->get_session_snapshot( $session_id );
        if ( empty( $snapshot ) ) {
            return 'Session nema sacuvano stanje.';
        }

        $lines   = array();
        $lines[] = 'Session: ' . ( isset( $snapshot['session_id'] ) ? (string) $snapshot['session_id'] : '' );
        $lines[] = 'Mode: ' . ( isset( $snapshot['mode'] ) ? (string) $snapshot['mode'] : 'main' );
        if ( ! empty( $snapshot['session_label'] ) ) {
            $lines[] = 'Label: ' . (string) $snapshot['session_label'];
        }
        if ( ! empty( $snapshot['session_scope'] ) ) {
            $lines[] = 'Scope: ' . (string) $snapshot['session_scope'];
        }
        $mode    = isset( $snapshot['mode'] ) ? (string) $snapshot['mode'] : 'main';
        $lines[] = 'Depth: ' . intval( isset( $snapshot['subagent_depth'] ) ? $snapshot['subagent_depth'] : 0 );
        if ( ! empty( $snapshot['parent_session_id'] ) ) {
            $lines[] = 'Parent: ' . (string) $snapshot['parent_session_id'];
        }
        $lines[] = 'subagent' === $mode
            ? 'Allow writes: ' . ( ! empty( $snapshot['allow_writes'] ) ? 'yes' : 'no' )
            : 'Main coding writes: yes via main_coding workspace tools';
        $lines[] = 'Turns: ' . intval( isset( $snapshot['turn_count'] ) ? $snapshot['turn_count'] : 0 );
        $lines[] = 'Compactions: ' . intval( isset( $snapshot['compaction_count'] ) ? $snapshot['compaction_count'] : 0 );
        if ( ! empty( $snapshot['active_tools'] ) && is_array( $snapshot['active_tools'] ) ) {
            $lines[] = 'Active tools: ' . implode( ', ', array_slice( array_values( $snapshot['active_tools'] ), 0, 12 ) );
        }

        if ( ! empty( $snapshot['recent_subagents'] ) && is_array( $snapshot['recent_subagents'] ) ) {
            $lines[] = 'Recent subagents: ' . count( $snapshot['recent_subagents'] );
        }
        if ( ! empty( $snapshot['worklog_summary'] ) ) {
            $lines[] = 'Worklog: ' . $this->truncate_block( (string) $snapshot['worklog_summary'], 360 );
        }

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

    public function compact_session_text( $session_id, $instructions = '' ) {
        if ( ! $this->session_state || ! method_exists( $this->session_state, 'compact_session' ) ) {
            return 'Session compaction runtime nije dostupan.';
        }

        $result = $this->session_state->compact_session( $session_id, $instructions );
        if ( empty( $result['success'] ) ) {
            return isset( $result['error'] ) ? (string) $result['error'] : 'Session compaction nije uspela.';
        }

        if ( ! empty( $result['note'] ) && 'empty_session' === (string) $result['note'] ) {
            return 'Session je vec prakticno prazan.';
        }

        return 'Session je kompaktovan. Compactions: ' . intval( isset( $result['compaction_count'] ) ? $result['compaction_count'] : 0 ) . "\n" . $this->truncate_block( isset( $result['summary'] ) ? (string) $result['summary'] : '', 500 );
    }

    public function reset_session_text( $session_id, $preserve_notes = true ) {
        if ( ! $this->session_state || ! method_exists( $this->session_state, 'reset_session' ) ) {
            return 'Session reset runtime nije dostupan.';
        }

        $ok = $this->session_state->reset_session( $session_id, $preserve_notes );
        if ( ! $ok ) {
            return 'Session reset nije uspeo.';
        }

        return $preserve_notes ? 'Session je resetovan. Sticky notes su sacuvane.' : 'Session je resetovan.';
    }

    public function get_subagents_status_text( $session_id ) {
        if ( ! $this->subagent_manager || ! method_exists( $this->subagent_manager, 'list_jobs_for_session' ) ) {
            return 'Subagent runtime nije dostupan.';
        }

        $jobs = $this->subagent_manager->list_jobs_for_session( $session_id, 8, true );
        if ( empty( $jobs ) ) {
            return 'Nema subagenata za ovu session nit.';
        }

        $lines = array( 'Subagents:' );
        foreach ( $jobs as $job ) {
            if ( ! is_array( $job ) ) {
                continue;
            }
            $line = '#' . ( isset( $job['id'] ) ? substr( (string) $job['id'], 0, 8 ) : 'unknown' ) . ' ' . ( isset( $job['label'] ) ? (string) $job['label'] : 'worker' ) . ' [' . ( isset( $job['status'] ) ? (string) $job['status'] : 'queued' ) . '] depth=' . intval( isset( $job['depth'] ) ? $job['depth'] : 1 );
            if ( ! empty( $job['progress_event'] ) ) {
                $line .= ' progress=' . (string) $job['progress_event'];
            }
            if ( ! empty( $job['progress_summary'] ) ) {
                $line .= ' ' . $this->truncate_block( (string) $job['progress_summary'], 80 );
            }
            if ( ! empty( $job['summary'] ) ) {
                $line .= ' ' . $this->truncate_block( (string) $job['summary'], 120 );
            }
            $lines[] = $line;
        }

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

    public function get_session_history_text( $session_id, $limit = 14 ) {
        if ( ! $this->session_state || ! method_exists( $this->session_state, 'get_session_transcript_excerpt' ) ) {
            return 'Session runtime nije dostupan.';
        }

        $session_id = trim( (string) $session_id );
        if ( '' === $session_id ) {
            return 'session_id je obavezan.';
        }

        $history = $this->session_state->get_session_transcript_excerpt( $session_id, $limit );
        if ( empty( $history ) ) {
            return 'Nema transcript istorije za trazenu session nit.';
        }

        return "Session history:\n" . implode( "\n", array_slice( (array) $history, -max( 1, intval( $limit ) ) ) );
    }

    public function control_subagents_text( $session_id, $action, $args = array() ) {
        if ( ! $this->subagent_manager || ! method_exists( $this->subagent_manager, 'control' ) ) {
            return 'Subagent runtime nije dostupan.';
        }

        $payload                      = is_array( $args ) ? $args : array();
        $payload['parent_session_id'] = (string) $session_id;
        $result                       = $this->subagent_manager->control( $action, $payload );
        if ( empty( $result['success'] ) ) {
            return isset( $result['error'] ) ? (string) $result['error'] : 'Subagent control nije uspeo.';
        }

        if ( 'list' === $action ) {
            $jobs = isset( $result['jobs'] ) && is_array( $result['jobs'] ) ? $result['jobs'] : array();
            if ( empty( $jobs ) ) {
                return 'Nema subagenata za ovu session nit.';
            }

            $lines = array( 'Subagents:' );
            foreach ( $jobs as $job ) {
                if ( ! is_array( $job ) ) {
                    continue;
                }
                $line = '#' . ( isset( $job['id'] ) ? substr( (string) $job['id'], 0, 8 ) : 'unknown' ) . ' ' . ( isset( $job['label'] ) ? (string) $job['label'] : 'worker' ) . ' [' . ( isset( $job['status'] ) ? (string) $job['status'] : 'queued' ) . '] depth=' . intval( isset( $job['depth'] ) ? $job['depth'] : 1 );
                if ( ! empty( $job['summary'] ) ) {
                    $line .= ' ' . $this->truncate_block( (string) $job['summary'], 120 );
                }
                $lines[] = $line;
            }

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

        if ( 'logs' === $action ) {
            $logs = isset( $result['logs'] ) && is_array( $result['logs'] ) ? $result['logs'] : array();
            if ( empty( $logs ) ) {
                return 'Nema logova za trazeni subagent.';
            }

            return "Subagent logs:\n" . implode( "\n", array_slice( $logs, -12 ) );
        }

        $summary = isset( $result['summary'] ) ? trim( (string) $result['summary'] ) : '';
        if ( '' !== $summary ) {
            return $summary;
        }

        $job = isset( $result['job'] ) && is_array( $result['job'] ) ? $result['job'] : array();
        if ( ! empty( $job ) ) {
            $line = 'Subagent #' . ( isset( $job['id'] ) ? substr( (string) $job['id'], 0, 8 ) : 'unknown' ) . ' [' . ( isset( $job['status'] ) ? (string) $job['status'] : 'queued' ) . '] depth=' . intval( isset( $job['depth'] ) ? $job['depth'] : 1 );
            if ( ! empty( $job['progress_event'] ) ) {
                $line .= "\nProgress: " . (string) $job['progress_event'];
            }
            if ( ! empty( $job['progress_summary'] ) ) {
                $line .= "\nProgress detail: " . $this->truncate_block( (string) $job['progress_summary'], 220 );
            }
            if ( ! empty( $job['summary'] ) ) {
                $line .= "\n" . $this->truncate_block( (string) $job['summary'], 220 );
            }
            return $line;
        }

        return 'Subagent control zavrsen.';
    }

    public function cancel_subagents_for_session_text( $session_id, $reason = 'Cancelled by founder.' ) {
        if ( ! $this->subagent_manager || ! method_exists( $this->subagent_manager, 'cancel_jobs_for_parent_session' ) ) {
            return array(
                'success' => false,
                'error'   => 'Subagent runtime nije dostupan.',
            );
        }

        return $this->subagent_manager->cancel_jobs_for_parent_session( $session_id, $reason );
    }

    public function send_to_session_text( $parent_session_id, $target_session_id, $task, $context = array() ) {
        if ( ! $this->subagent_manager || ! method_exists( $this->subagent_manager, 'send_to_session' ) ) {
            return 'Session send runtime nije dostupan.';
        }

        $parent_session_id = trim( (string) $parent_session_id );
        $target_session_id = trim( (string) $target_session_id );
        $task              = trim( (string) $task );
        $context           = is_array( $context ) ? $context : array();

        if ( '' === $target_session_id || '' === $task ) {
            return 'session_id i task su obavezni.';
        }

        $result = $this->subagent_manager->send_to_session(
            $this,
            $target_session_id,
            $task,
            array_merge(
                $context,
                array(
                    'session_id' => $parent_session_id,
                )
            ),
            array(
                'announce' => false,
            )
        );

        if ( empty( $result['success'] ) ) {
            return isset( $result['error'] ) ? (string) $result['error'] : 'Session send nije uspeo.';
        }

        return isset( $result['summary'] ) ? (string) $result['summary'] : 'Poruka je poslata u trazenu session nit.';
    }

    public function session_has_runtime_state( $session_id ) {
        $session_id = trim( (string) $session_id );
        if ( '' === $session_id || ! $this->session_state || ! method_exists( $this->session_state, 'get_session_snapshot' ) ) {
            return false;
        }

        $snapshot = $this->session_state->get_session_snapshot( $session_id );
        if ( empty( $snapshot ) || ! is_array( $snapshot ) ) {
            return false;
        }

        if ( intval( isset( $snapshot['turn_count'] ) ? $snapshot['turn_count'] : 0 ) > 0 ) {
            return true;
        }
        if ( ! empty( $snapshot['worklog_summary'] ) ) {
            return true;
        }
        if ( ! empty( $snapshot['sticky_notes'] ) ) {
            return true;
        }

        return ! empty( $snapshot['recent_subagents'] );
    }

    public function get_heartbeat_status_text() {
        $state     = $this->get_heartbeat_state();
        $hb_config = $this->get_heartbeat_config();
        $has_custom = $this->has_custom_heartbeat_instructions();
        $lines     = array();

        // Default heartbeat status.
        $mode = ! empty( $hb_config['paused'] ) ? 'paused' : ( $has_custom ? 'custom' : 'proactive' );
        $hours = isset( $hb_config['scheduled_hours'] ) && is_array( $hb_config['scheduled_hours'] ) ? $hb_config['scheduled_hours'] : array( 9, 13, 17, 20 );
        $lines[] = '=== Default Heartbeat ===';
        $lines[] = 'Mode: ' . $mode;
        $lines[] = 'Schedule: ' . implode( 'h, ', $hours ) . 'h (' . count( $hours ) . 'x/day)';
        $lines[] = 'Blog writing: ' . intval( $hb_config['blog_per_day'] ) . 'x/day max';
        $lines[] = 'Companion engage: off';
        $lines[] = 'Last check: ' . $this->format_internal_timestamp( isset( $state['last_checked_at'] ) ? $state['last_checked_at'] : 0 );
        $lines[] = 'Last sent: ' . $this->format_internal_timestamp( isset( $state['last_sent_at'] ) ? $state['last_sent_at'] : 0 );

        if ( ! empty( $state['last_task'] ) ) {
            $lines[] = 'Last task: ' . (string) $state['last_task'];
        }
        if ( ! empty( $state['last_status'] ) ) {
            $lines[] = 'Status: ' . (string) $state['last_status'];
        }
        if ( ! empty( $state['last_summary'] ) ) {
            $lines[] = 'Summary: ' . $this->truncate_block( (string) $state['last_summary'], 240 );
        }
        // Operative heartbeat status.
        $op_config = $this->get_operative_heartbeat_config();
        $op_state  = $this->get_operative_heartbeat_state();

        $lines[] = '';
        $lines[] = '=== Operative Heartbeat ===';
        $lines[] = 'Enabled: ' . ( ! empty( $op_config['enabled'] ) ? 'yes' : 'no' );
        $lines[] = 'Interval: ' . $this->format_operative_interval_minutes( isset( $op_config['interval_minutes'] ) ? $op_config['interval_minutes'] : 60 );
        $lines[] = 'Delivery: ' . ( ! empty( $op_config['delivery_channel'] ) ? (string) $op_config['delivery_channel'] : 'telegram' );
        $lines[] = 'Task file: OPERATIVE_HEARTBEAT.md';
        $lines[] = 'Last attempt: ' . $this->format_internal_timestamp( isset( $op_state['last_attempt_at'] ) ? $op_state['last_attempt_at'] : 0 );
        $lines[] = 'Last run: ' . $this->format_internal_timestamp( isset( $op_state['last_run_at'] ) ? $op_state['last_run_at'] : 0 );
        $lines[] = 'Last sent: ' . $this->format_internal_timestamp( isset( $op_state['last_sent_at'] ) ? $op_state['last_sent_at'] : 0 );
        $lines[] = 'Total runs: ' . intval( isset( $op_state['run_count'] ) ? $op_state['run_count'] : 0 );

        $op_instructions = method_exists( $this, 'get_operative_heartbeat_instructions' ) ? trim( (string) $this->get_operative_heartbeat_instructions( 'admin' ) ) : '';
        if ( '' !== $op_instructions ) {
            $lines[] = 'Task: ' . $this->truncate_block( wp_strip_all_tags( $op_instructions ), 240 );
        }
        if ( ! empty( $op_state['last_status'] ) ) {
            $lines[] = 'Status: ' . (string) $op_state['last_status'];
        }
        if ( ! empty( $op_state['last_summary'] ) ) {
            $lines[] = 'Summary: ' . $this->truncate_block( (string) $op_state['last_summary'], 240 );
        }

        $stock_op_config = $this->get_operative_heartbeat_config( 'stock_manager' );
        $stock_op_state  = $this->get_operative_heartbeat_state( 'stock_manager' );

        $lines[] = '';
        $lines[] = '=== Stock Operative Heartbeat ===';
        $lines[] = 'Enabled: ' . ( ! empty( $stock_op_config['enabled'] ) ? 'yes' : 'no' );
        $lines[] = 'Interval: ' . $this->format_operative_interval_minutes( isset( $stock_op_config['interval_minutes'] ) ? $stock_op_config['interval_minutes'] : 60 );
        $lines[] = 'Delivery: ' . ( ! empty( $stock_op_config['delivery_channel'] ) ? (string) $stock_op_config['delivery_channel'] : 'telegram' );
        $lines[] = 'Task file: STOCK_OPERATIVE_HEARTBEAT.md';
        $lines[] = 'Last attempt: ' . $this->format_internal_timestamp( isset( $stock_op_state['last_attempt_at'] ) ? $stock_op_state['last_attempt_at'] : 0 );
        $lines[] = 'Last run: ' . $this->format_internal_timestamp( isset( $stock_op_state['last_run_at'] ) ? $stock_op_state['last_run_at'] : 0 );
        $lines[] = 'Last sent: ' . $this->format_internal_timestamp( isset( $stock_op_state['last_sent_at'] ) ? $stock_op_state['last_sent_at'] : 0 );
        $lines[] = 'Total runs: ' . intval( isset( $stock_op_state['run_count'] ) ? $stock_op_state['run_count'] : 0 );

        $stock_instructions = method_exists( $this, 'get_operative_heartbeat_instructions' ) ? trim( (string) $this->get_operative_heartbeat_instructions( 'stock_manager' ) ) : '';
        if ( '' !== $stock_instructions ) {
            $lines[] = 'Task: ' . $this->truncate_block( wp_strip_all_tags( $stock_instructions ), 240 );
        }
        if ( ! empty( $stock_op_state['last_status'] ) ) {
            $lines[] = 'Status: ' . (string) $stock_op_state['last_status'];
        }
        if ( ! empty( $stock_op_state['last_summary'] ) ) {
            $lines[] = 'Summary: ' . $this->truncate_block( (string) $stock_op_state['last_summary'], 240 );
        }

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

    public function get_sessions_list_text( $prefix = 'admin-telegram-', $limit = 10 ) {
        if ( ! $this->session_state || ! method_exists( $this->session_state, 'list_sessions' ) ) {
            return 'Session runtime nije dostupan.';
        }

        $sessions = $this->session_state->list_sessions( $limit, $prefix );
        if ( empty( $sessions ) ) {
            return 'Nema session zapisa za trazeni opseg.';
        }

        $lines = array( 'Sessions:' );
        foreach ( $sessions as $session ) {
            if ( ! is_array( $session ) ) {
                continue;
            }

            $line = ( isset( $session['session_id'] ) ? (string) $session['session_id'] : 'unknown' ) .
                ' | turns=' . intval( isset( $session['turn_count'] ) ? $session['turn_count'] : 0 ) .
                ' | compactions=' . intval( isset( $session['compaction_count'] ) ? $session['compaction_count'] : 0 ) .
                ' | updated=' . $this->format_internal_timestamp( isset( $session['updated_at'] ) ? $session['updated_at'] : 0 );
            if ( ! empty( $session['session_label'] ) ) {
                $line .= ' | label=' . (string) $session['session_label'];
            }
            if ( ! empty( $session['session_scope'] ) ) {
                $line .= ' | scope=' . (string) $session['session_scope'];
            }
            $line .= ' | depth=' . intval( isset( $session['subagent_depth'] ) ? $session['subagent_depth'] : 0 );
            if ( ! empty( $session['parent_session_id'] ) ) {
                $line .= ' | parent=' . $this->truncate_block( (string) $session['parent_session_id'], 80 );
            }
            if ( ! empty( $session['worklog_summary'] ) ) {
                $line .= ' | ' . $this->truncate_block( (string) $session['worklog_summary'], 120 );
            }
            $lines[] = $line;
        }

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

    public function run_workspace_heartbeat_now() {
        return $this->maybe_send_workspace_heartbeat( true );
    }
}
