<?php
/**
 * Plugin Constants
 *
 * Centralized magic numbers and configuration defaults used across the plugin.
 *
 * @package Niwa_AI
 * @since   0.10.25
 */

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

class Niwa_AI_Constants {

	// ── Session & Cookie ──
	const SESSION_COOKIE_NAME    = 'niwa_ai_session';
	const SESSION_COOKIE_DAYS    = 30;
	const SESSION_MAX_LENGTH     = 96;

	// ── Indexing ──
	const CHUNK_SIZE_CHARS       = 3000;
	const CHUNK_MIN_CHARS        = 500;
	const TEXT_THRESHOLD_CHARS   = 4000;
	const INDEX_QUEUE_BATCH_SIZE = 120;
	const INDEX_QUEUE_DELAY      = 5;
	const EMBEDDING_BATCH_SIZE   = 80;
	const EMBEDDING_INITIAL_BATCH_SIZE = 100;
	const EMBEDDING_QUEUE_DELAY  = 5;
	const EMBEDDING_CLIP_CHARS   = 6000;

	// ── Memory / Search ──
	const VECTOR_SCAN_DEFAULT    = 2000;
	const VECTOR_SCAN_MIN        = 200;
	const VECTOR_SCAN_MAX        = 10000;
	const CONFIDENCE_HIGH        = 0.85;
	const CONFIDENCE_THRESHOLD   = 0.60;

	// ── Conversation ──
	const HISTORY_LIMIT_FRONTEND = 40;
	const HISTORY_LIMIT_FOUNDER  = 800;
	const FRONTEND_DEFAULT_GREETING = 'Hi! I\'m Niwa 🌿 How can I help you today?';

	/**
	 * Get the built-in frontend greeting for the selected UI language.
	 *
	 * @param string $language UI language code.
	 * @return string
	 */
	public static function frontend_default_greeting( $language = 'en' ) {
		$language = strtolower( trim( str_replace( '-', '_', (string) $language ) ) );
		$language = explode( '_', $language )[0];

		$greetings = array(
			'sr' => 'Zdravo! Ja sam Niwa 🌿 Kako mogu da vam pomognem danas?',
			'hr' => 'Bok! Ja sam Niwa 🌿 Kako vam mogu pomoći danas?',
			'de' => 'Hallo! Ich bin Niwa 🌿 Wie kann ich Ihnen heute helfen?',
			'es' => '¡Hola! Soy Niwa 🌿 ¿Cómo puedo ayudarte hoy?',
			'fr' => 'Bonjour ! Je suis Niwa 🌿 Comment puis-je vous aider aujourd\'hui ?',
		);

		return isset( $greetings[ $language ] ) ? $greetings[ $language ] : self::FRONTEND_DEFAULT_GREETING;
	}

	// ── Rate Limiting ──
	const RATE_LIMIT_MAX         = 5;
	const RATE_LIMIT_WINDOW      = 900; // 15 minutes in seconds.

	// ── Cron Intervals ──
	const CRON_FIVE_MINUTES      = 300;
	const CRON_ONE_MINUTE        = 60;

	// ── Frontend Question Log ──
	const QUESTION_LOG_MAX_ROWS    = 10000;
	const QUESTION_LOG_CLEANUP     = 500;
	const QUESTION_LOG_CLEANUP_ODDS = 50; // 1 in 50 requests.

	// ── Latency Tracking ──
	const LATENCY_MAX_EVENTS     = 200;

	// ── Name Processor ──
	const NAME_MIN_LENGTH        = 2;
	const NAME_MAX_LENGTH        = 40;
	const NAME_MAX_WORDS         = 4;

	// ── Model Defaults ──
	const DEFAULT_MODEL_API_KEY  = 'gpt-5.4-mini';
	const DEFAULT_MODEL_OAUTH    = 'gpt-5.4-mini';
	const DEFAULT_MODEL_RLM      = 'gpt-5.4-mini';
	const DEFAULT_FRONTEND_MODEL = 'gpt-5.6-terra-medium';

	// ── Admin Autonomy ──
	const AUTONOMY_MAX_ROUNDS         = 30;
	const AUTONOMY_SUBAGENT_MAX_ROUNDS = 20;
	const AUTONOMY_MAX_DEPTH          = 3;
	const AUTONOMY_MAX_SESSIONS       = 24;
	const AUTONOMY_MAX_SKILLS         = 150;
	const AUTONOMY_SKILL_MAX_SIZE     = 262144; // 256 KB.
	const AUTONOMY_CONTEXT_TOKENS     = 600000;

	// ── Store Overview ──
	const OVERVIEW_MAX_LENGTH    = 10000;
	const OVERVIEW_SECTION_LIMIT = 3000;

	// ── Content Cleaning ──
	const MIN_TEXT_LENGTH        = 10;

	// ── Conversion Busters ──
	const CB_DEFAULT_COOLDOWN_MIN  = 30;
	const CB_DEFAULT_THRESHOLD     = 2;
	const CB_COUPON_DURATION_MIN   = 30;

	// ── Security ──
	const HONEYPOT_FIELD         = 'website';

	// ── Option Keys: Core Settings ──
	const OPT_AUTH                         = 'niwa_ai_auth';
	const OPT_SETTINGS                     = 'niwa_ai_settings';
	const OPT_UI_SETTINGS                  = 'niwa_ai_ui_settings';
	const OPT_RAG_SETTINGS                 = 'niwa_ai_rag_settings';
	const OPT_DB_SCHEMA_VERSION            = 'niwa_ai_db_schema_version';
	const OPT_ATTENTION_CAPTURE            = 'niwa_ai_attention_capture_opts';
	const OPT_CONVERSION_BUSTERS           = 'niwa_ai_conversion_busters_opts';
	const OPT_LEAD_CAPTURE                 = 'niwa_ai_lead_capture_settings';
	const OPT_LEAD_FORM_GENERATOR          = 'niwa_ai_lead_form_generator';

	// ── DB Tables: Lead Form Generator ──
	const TABLE_LEAD_FORM_SESSIONS         = 'niwa_ai_lead_form_sessions';
	const TABLE_LEAD_FORM_ANSWERS          = 'niwa_ai_lead_form_answers';
	const OPT_LEAD_FORM_SCHEMA_READY       = 'niwa_ai_lead_form_schema_ready';
	const OPT_AGENT_PROFILE                = 'niwa_ai_agent_profile';
	const OPT_AGENT_PROFILE_SUMMARIES      = 'niwa_ai_agent_profile_summaries';
	const OPT_OAUTH_REFRESH_LOCK           = 'niwa_ai_oauth_refresh_lock';

	// ── DB Tables / Options: Cart Recovery ──
	const TABLE_CART_RECOVERY              = 'niwa_ai_cart_recovery';
	const TABLE_CART_RECOVERY_SUPPRESSION  = 'niwa_ai_cart_recovery_suppression';
	const OPT_CART_RECOVERY_SETTINGS       = 'niwa_ai_cart_recovery_settings';
	const OPT_CART_RECOVERY_SCHEMA_READY   = 'niwa_ai_cart_recovery_schema_ready';
	const OPT_CART_RECOVERY_PHONE_HASH_KEY    = 'niwa_ai_cart_recovery_phone_hash_key';
	const TABLE_SESSION_CHUNKS             = 'niwa_ai_session_chunks';
	const OPT_SESSION_MEMORY_SCHEMA_READY  = 'niwa_ai_session_memory_schema_ready';
	const OPT_SESSION_MEMORY_BACKFILL_READY = 'niwa_ai_session_memory_backfill_ready';

	// ── Cart Recovery: Defaults (minutes / hours / days) ──
	const CART_RECOVERY_MAIL1_DELAY_MIN    = 15;
	const CART_RECOVERY_MAIL2_DELAY_HOURS  = 24;
	const CART_RECOVERY_INACTIVITY_CAP_H   = 72;
	const CART_RECOVERY_COOLDOWN_DAYS      = 7;
	const CART_RECOVERY_COUPON_TTL_HOURS   = 24;
	const CART_RECOVERY_COUPON_PERCENT     = 10;
	const CART_RECOVERY_COUPON_TYPE        = 'percent';        // 'percent' | 'fixed_cart' | 'fixed_product'
	const CART_RECOVERY_COUPON_PREFIX      = 'NIWA-BACK-';
	const CART_RECOVERY_COUPON_CLEANUP_GRACE_DAYS = 7;          // trash coupons this long past expiry

	// ── Cart Recovery: Cron + Action names ──
	const CRON_HOOK_CART_RECOVERY_TICK     = 'niwa_ai_cart_recovery_tick';
	const ACTION_CART_RECOVERY_SEND_MAIL1  = 'niwa_ai_cart_recovery_send_mail1';
	const ACTION_CART_RECOVERY_SEND_MAIL2  = 'niwa_ai_cart_recovery_send_mail2';

	// ── Cart Recovery: REST + Send limits ──
	const REST_NS_CART_RECOVERY               = 'niwa-ai/v1';
	const REST_ROUTE_CR_OPEN                  = '/cart-recovery/open/(?P<token>[a-z0-9]{32,64})';
	const REST_ROUTE_CR_CLICK                 = '/cart-recovery/click/(?P<token>[a-z0-9]{32,64})';
	const REST_ROUTE_CR_RECOVER               = '/cart-recovery/recover/(?P<token>[a-z0-9]{32,64})';
	const REST_ROUTE_CR_UNSUBSCRIBE           = '/cart-recovery/unsubscribe/(?P<token>[a-z0-9]{32,64})';
	const CART_RECOVERY_SEND_MAX_PER_TICK     = 20;
	const CART_RECOVERY_TRANSCRIPT_MAX_CHARS  = 1500;
	const CART_RECOVERY_TRANSCRIPT_MAX_MSGS   = 20;
	const CART_RECOVERY_TRANSCRIPT_LINE_MAX   = 400;

	// ── Cart Recovery: Phase 7 — retry cap + schema stamp ──
	// Bump CART_RECOVERY_SCHEMA_STAMP on any schema change so the
	// ensurer re-runs without requiring a full plugin-version bump.
	const CART_RECOVERY_SCHEMA_STAMP          = '0.13.630-cart-channels-v1';
	const CART_RECOVERY_MAX_SEND_ATTEMPTS     = 3;
	const SESSION_MEMORY_SCHEMA_STAMP         = '0.12.33-dev-phase1';

	// ── Option Keys: Indexing & Embeddings ──
	const OPT_INDEX_PROGRESS               = 'niwa_ai_index_progress';
	const OPT_INDEX_QUEUE                  = 'niwa_ai_index_queue';
	const OPT_INDEX_DOCS                   = 'niwa_ai_rlm_index_docs';
	const OPT_EMBEDDING_LAST_ERROR         = 'niwa_ai_embedding_last_error';
	const OPT_EMBEDDING_KICK               = 'niwa_ai_embedding_kick';
	const OPT_INDEX_WORKER_SECRET          = 'niwa_ai_index_worker_secret';

	// ── Option Keys: Frontend Queue ──
	const OPT_FRONTEND_CACHE_VERSION       = 'niwa_ai_frontend_cache_version';
	const OPT_FRONTEND_CHAT_QUEUE          = 'niwa_ai_frontend_chat_queue';
	const OPT_FRONTEND_WORKER_SECRET       = 'niwa_ai_frontend_worker_secret';
	const OPT_FRONTEND_LANE_PREFIX         = 'niwa_ai_frontend_lane_';
	const OPT_CLEANUP_LOCALSTORAGE         = 'niwa_ai_cleanup_localStorage_on_next_load';
	const OPT_LATENCY_EVENTS               = 'niwa_ai_latency_events';
	const OPT_LATENCY_EVENTS_LOCK          = 'niwa_ai_latency_events_lock';

	// ── Option Keys: Admin Autonomy ──
	const OPT_AUTONOMY                     = 'niwa_ai_admin_autonomy';
	const OPT_AUTONOMY_MEMORY              = 'niwa_ai_admin_autonomy_founder_memory';
	const OPT_AUTONOMY_EMAIL               = 'niwa_ai_admin_autonomy_email';
	const OPT_AUTONOMY_SESSION_STATE       = 'niwa_ai_admin_autonomy_session_state';
	const OPT_AUTONOMY_SUBAGENT_JOBS       = 'niwa_ai_admin_autonomy_subagent_jobs';
	const OPT_AUTONOMY_WORKSPACE_STATE     = 'niwa_ai_admin_autonomy_workspace_state';
	const OPT_AUTONOMY_REPORT_STATE        = 'niwa_ai_admin_autonomy_report_state';
	const OPT_AUTONOMY_LAST_ADMIN_CHANNEL = 'niwa_ai_admin_autonomy_last_admin_channel';
	const OPT_AUTONOMY_HEARTBEAT_STATE     = 'niwa_ai_admin_autonomy_heartbeat_state';
	const OPT_AUTONOMY_HEARTBEAT_CONFIG    = 'niwa_ai_admin_autonomy_heartbeat_config';
	const OPT_AUTONOMY_INSTALLED_AT        = 'niwa_ai_admin_autonomy_installed_at';
	const OPT_ADMIN_UI_CHAT_QUEUE          = 'niwa_ai_admin_ui_chat_queue';
	const OPT_ADMIN_UI_WORKER_SECRET       = 'niwa_ai_admin_ui_worker_secret';
	// Legacy turn runtime keys retained only for upgrade cleanup.
	const OPT_ADMIN_TURN_QUEUE             = 'niwa_ai_admin_turn_queue';
	const OPT_ADMIN_STEERING_BUFFER        = 'niwa_ai_admin_steering_buffer';
	const OPT_AUTONOMY_OPERATIVE_HB_CONFIG = 'niwa_ai_admin_autonomy_operative_hb_config';
	const OPT_AUTONOMY_OPERATIVE_HB_STATE  = 'niwa_ai_admin_autonomy_operative_hb_state';
	const OPT_AUTONOMY_STOCK_OPERATIVE_HB_CONFIG = 'niwa_ai_admin_autonomy_stock_operative_hb_config';
	const OPT_AUTONOMY_STOCK_OPERATIVE_HB_STATE  = 'niwa_ai_admin_autonomy_stock_operative_hb_state';
	const OPT_AUTONOMY_RUNTIME_VERSION     = 'niwa_ai_admin_autonomy_runtime_version';
	const OPT_WHATSAPP_RUNTIME_VERSION     = 'niwa_ai_admin_autonomy_whatsapp_runtime_version';
	const OPT_AUTONOMY_PROMPT_CACHE_USAGE  = 'niwa_ai_admin_autonomy_prompt_cache_usage';

	// ── Option Keys: Performance (cron + browser poll intervals) ──
	const OPT_PERFORMANCE_SETTINGS         = 'niwa_ai_performance_settings';

	// ── Option Keys: Telegram ──
	const OPT_AUTONOMY_TG_UPDATES          = 'niwa_ai_admin_autonomy_tg_updates';
	const OPT_AUTONOMY_TG_POLL_STATE       = 'niwa_ai_admin_autonomy_tg_poll_state';
	const OPT_AUTONOMY_TG_RUNNER_STATE     = 'niwa_ai_admin_autonomy_tg_runner_state';
	const OPT_AUTONOMY_TG_WEBHOOK_STATE    = 'niwa_ai_admin_autonomy_tg_webhook_state';
	const OPT_AUTONOMY_TG_INTRO_LOG        = 'niwa_ai_admin_autonomy_tg_intro_log';
	const OPT_AUTONOMY_TG_ALBUM_INDEX      = 'niwa_ai_admin_autonomy_tg_album_index';
	const OPT_AUTONOMY_TG_TEXT_FRAG_INDEX  = 'niwa_ai_admin_autonomy_tg_text_frag_index';
	const OPT_AUTONOMY_TG_STICKER_CACHE    = 'niwa_ai_admin_autonomy_tg_sticker_cache';
	const OPT_AUTONOMY_WA_TEXT_BATCH_INDEX = 'niwa_ai_admin_autonomy_wa_text_batch_index';

	// ── Legacy Option Keys ──
	const LEGACY_OPT_AGENT_PROFILE         = 'zaa_agent_profile';
}
