<?php
/**
 * Admin menu, page rendering, and POST handlers for KB ingestion.
 *
 * @package AetherisAIChat
 */

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

final class Aetheris_AI_Chat_Admin {

	const SLUG = 'aetheris-ai-chat';
	const CAP  = 'manage_options';

	public static function init() {
		add_action( 'admin_menu', array( __CLASS__, 'register_menu' ) );
		add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_assets' ) );
		add_action( 'admin_post_aetheris_ingest_url', array( __CLASS__, 'handle_ingest_url' ) );
		add_action( 'admin_post_aetheris_ingest_file', array( __CLASS__, 'handle_ingest_file' ) );
	}

	public static function register_menu() {
		$icon = 'data:image/svg+xml;base64,' . base64_encode(
			'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="#a7aaad">'
			. '<path d="M3 4.5A2.5 2.5 0 0 1 5.5 2h9A2.5 2.5 0 0 1 17 4.5v7A2.5 2.5 0 0 1 14.5 14H10l-4 4v-4H5.5A2.5 2.5 0 0 1 3 11.5v-7Z"/>'
			. '</svg>'
		);

		add_menu_page(
			__( 'Aetheris AI Chat', 'aetheris-ai-chat' ),
			__( 'Aetheris Chat', 'aetheris-ai-chat' ),
			self::CAP,
			self::SLUG,
			array( __CLASS__, 'render_settings' ),
			$icon,
			58
		);

		add_submenu_page(
			self::SLUG,
			__( 'Settings', 'aetheris-ai-chat' ),
			__( 'Settings', 'aetheris-ai-chat' ),
			self::CAP,
			self::SLUG,
			array( __CLASS__, 'render_settings' )
		);

		add_submenu_page(
			self::SLUG,
			__( 'Knowledge Base', 'aetheris-ai-chat' ),
			__( 'Knowledge Base', 'aetheris-ai-chat' ),
			self::CAP,
			self::SLUG . '-kb',
			array( __CLASS__, 'render_knowledge_base' )
		);

		add_submenu_page(
			self::SLUG,
			__( 'Dashboard', 'aetheris-ai-chat' ),
			__( 'Dashboard', 'aetheris-ai-chat' ),
			self::CAP,
			self::SLUG . '-dashboard',
			array( __CLASS__, 'render_dashboard' )
		);

		add_submenu_page(
			self::SLUG,
			__( 'Help', 'aetheris-ai-chat' ),
			__( 'Help', 'aetheris-ai-chat' ),
			self::CAP,
			self::SLUG . '-help',
			array( __CLASS__, 'render_help' )
		);
	}

	public static function enqueue_assets( $hook ) {
		if ( false === strpos( (string) $hook, self::SLUG ) ) {
			return;
		}
		wp_enqueue_style(
			'aetheris-ai-chat-admin',
			AETHERIS_AI_CHAT_URL . 'admin/css/admin.css',
			array(),
			AETHERIS_AI_CHAT_VERSION
		);
		wp_enqueue_script(
			'aetheris-ai-chat-admin',
			AETHERIS_AI_CHAT_URL . 'admin/js/admin.js',
			array(),
			AETHERIS_AI_CHAT_VERSION,
			true
		);
	}

	public static function render_settings() {
		if ( ! current_user_can( self::CAP ) ) {
			return;
		}
		$settings = Aetheris_AI_Chat_Settings::get();
		include AETHERIS_AI_CHAT_DIR . 'admin/views/settings.php';
	}

	public static function render_knowledge_base() {
		if ( ! current_user_can( self::CAP ) ) {
			return;
		}
		$settings = Aetheris_AI_Chat_Settings::get();
		$has_auth = Aetheris_AI_Chat_API::has_credentials();
		include AETHERIS_AI_CHAT_DIR . 'admin/views/knowledge-base.php';
	}

	public static function render_dashboard() {
		if ( ! current_user_can( self::CAP ) ) {
			return;
		}
		$settings = Aetheris_AI_Chat_Settings::get();
		$stats    = null;
		$convos   = null;
		if ( Aetheris_AI_Chat_API::has_credentials() ) {
			$stats  = Aetheris_AI_Chat_API::get_stats();
			$convos = Aetheris_AI_Chat_API::get_conversations( 20 );
		}
		include AETHERIS_AI_CHAT_DIR . 'admin/views/dashboard.php';
	}

	public static function render_help() {
		if ( ! current_user_can( self::CAP ) ) {
			return;
		}
		include AETHERIS_AI_CHAT_DIR . 'admin/views/help.php';
	}

	public static function handle_ingest_url() {
		if ( ! current_user_can( self::CAP ) ) {
			wp_die( esc_html__( 'Permission denied.', 'aetheris-ai-chat' ) );
		}
		check_admin_referer( 'aetheris_ingest_url' );

		$url = isset( $_POST['kb_url'] ) ? esc_url_raw( wp_unslash( $_POST['kb_url'] ) ) : '';
		if ( empty( $url ) ) {
			self::redirect_with_notice( 'kb', 'error', __( 'Enter a valid URL.', 'aetheris-ai-chat' ) );
		}

		$result = Aetheris_AI_Chat_API::ingest_url( $url );
		if ( is_wp_error( $result ) ) {
			self::redirect_with_notice( 'kb', 'error', $result->get_error_message() );
		}

		$chunks = isset( $result['chunks'] ) ? (int) $result['chunks'] : 0;
		self::redirect_with_notice(
			'kb',
			'success',
			sprintf(
				/* translators: %1$s: ingested URL. %2$d: number of chunks indexed. */
				__( 'Ingested %1$s — %2$d chunks indexed.', 'aetheris-ai-chat' ),
				esc_url( $url ),
				$chunks
			)
		);
	}

	public static function handle_ingest_file() {
		if ( ! current_user_can( self::CAP ) ) {
			wp_die( esc_html__( 'Permission denied.', 'aetheris-ai-chat' ) );
		}
		check_admin_referer( 'aetheris_ingest_file' );

		if ( empty( $_FILES['kb_file']['tmp_name'] ) ) {
			self::redirect_with_notice( 'kb', 'error', __( 'No file uploaded.', 'aetheris-ai-chat' ) );
		}

		// Pull each $_FILES field individually with the right sanitiser; never pass
		// the raw array around. Plugin Check's sniff catches blanket access.
		$file_name  = isset( $_FILES['kb_file']['name'] ) ? sanitize_file_name( wp_unslash( $_FILES['kb_file']['name'] ) ) : '';
		$file_tmp   = isset( $_FILES['kb_file']['tmp_name'] ) ? sanitize_text_field( wp_unslash( $_FILES['kb_file']['tmp_name'] ) ) : '';
		$file_size  = isset( $_FILES['kb_file']['size'] ) ? (int) $_FILES['kb_file']['size'] : 0;
		$file_error = isset( $_FILES['kb_file']['error'] ) ? (int) $_FILES['kb_file']['error'] : 0;

		if ( $file_error ) {
			self::redirect_with_notice( 'kb', 'error', __( 'Upload error.', 'aetheris-ai-chat' ) );
		}

		$allowed = array( 'pdf', 'txt', 'md', 'html', 'htm', 'docx' );
		$ext     = strtolower( pathinfo( $file_name, PATHINFO_EXTENSION ) );
		if ( ! in_array( $ext, $allowed, true ) ) {
			self::redirect_with_notice(
				'kb',
				'error',
				__( 'Unsupported file type. Allowed: PDF, TXT, MD, HTML, DOCX.', 'aetheris-ai-chat' )
			);
		}

		if ( $file_size > 20 * 1024 * 1024 ) {
			self::redirect_with_notice( 'kb', 'error', __( 'File exceeds 20 MB limit.', 'aetheris-ai-chat' ) );
		}

		$title  = isset( $_POST['kb_title'] ) ? sanitize_text_field( wp_unslash( $_POST['kb_title'] ) ) : '';
		$result = Aetheris_AI_Chat_API::ingest_file( $file_tmp, $title );
		if ( is_wp_error( $result ) ) {
			self::redirect_with_notice( 'kb', 'error', $result->get_error_message() );
		}

		$chunks = isset( $result['chunks'] ) ? (int) $result['chunks'] : 0;
		self::redirect_with_notice(
			'kb',
			'success',
			sprintf(
				/* translators: %1$s: uploaded filename. %2$d: number of chunks indexed. */
				__( 'Ingested %1$s — %2$d chunks indexed.', 'aetheris-ai-chat' ),
				esc_html( $file_name ),
				$chunks
			)
		);
	}

	private static function redirect_with_notice( $page, $status, $message ) {
		$slug = self::SLUG;
		if ( 'kb' === $page ) {
			$slug = self::SLUG . '-kb';
		} elseif ( 'dashboard' === $page ) {
			$slug = self::SLUG . '-dashboard';
		}
		$url = add_query_arg(
			array(
				'page'              => $slug,
				'aetheris_status'   => $status,
				'aetheris_message'  => rawurlencode( $message ),
			),
			admin_url( 'admin.php' )
		);
		wp_safe_redirect( $url );
		exit;
	}

	/**
	 * Render the brand-mark header at the top of each admin view. Drops in
	 * the ink-ring + copper-dot SVG, an "AETHERIS · WORDPRESS" eyebrow, the
	 * page title, and the version badge — same composition as the marketing
	 * banner.
	 */
	public static function render_header( $title ) {
		$svg = '<svg viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">'
			. '<circle cx="18" cy="18" r="18" fill="#1a1814"/>'
			. '<circle cx="18" cy="18" r="5.5" fill="#b8693d"/>'
			. '</svg>';
		printf(
			'<div class="aetheris-header">'
			. '<span class="aetheris-mark" role="img" aria-label="Aetheris">%s</span>'
			. '<span class="aetheris-title-block">'
			. '<span class="aetheris-title-eyebrow">%s</span>'
			. '<span class="aetheris-title">%s<span class="copper-dot">.</span></span>'
			. '</span>'
			. '<span class="aetheris-version">v%s</span>'
			. '</div>',
			$svg, // SVG hand-built above; safe to echo unescaped.
			esc_html__( 'Aetheris · WordPress', 'aetheris-ai-chat' ),
			esc_html( $title ),
			esc_html( AETHERIS_AI_CHAT_VERSION )
		);
	}

	public static function flash_notice() {
		// Read-only display of the status query string set by self::redirect_with_notice()
		// after a nonce-verified handler in this class. No nonce check on this read,
		// because we do not act on the value — we only render it as escaped text.
		// phpcs:disable WordPress.Security.NonceVerification.Recommended
		if ( empty( $_GET['aetheris_status'] ) || empty( $_GET['aetheris_message'] ) ) {
			return;
		}
		$status      = sanitize_key( wp_unslash( $_GET['aetheris_status'] ) );
		$message_raw = sanitize_text_field( wp_unslash( $_GET['aetheris_message'] ) );
		// phpcs:enable WordPress.Security.NonceVerification.Recommended

		$message = sanitize_text_field( rawurldecode( $message_raw ) );
		$class   = 'success' === $status ? 'notice-success' : 'notice-error';
		printf(
			'<div class="notice %s is-dismissible"><p>%s</p></div>',
			esc_attr( $class ),
			esc_html( $message )
		);
	}
}
