<?php
/**
 * Database layer for RAG chunks.
 *
 * @package Maca_Tjatt
 */

defined( 'ABSPATH' ) || exit;

/**
 * Class Maca_Tjatt_DB
 */
class Maca_Tjatt_DB {

	/**
	 * @return string
	 */
	public static function table_name() {
		global $wpdb;

		return $wpdb->prefix . 'maca_tjatt_chunks';
	}

	/**
	 * Create chunks table.
	 */
	public static function create_tables() {
		global $wpdb;

		if ( ! isset( $wpdb ) || empty( $wpdb ) ) {
			return;
		}

		$charset_collate = $wpdb->get_charset_collate();
		$table           = self::table_name();

		$sql = "CREATE TABLE $table (
			id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
			chunk_key varchar(191) NOT NULL DEFAULT '',
			source_type varchar(32) NOT NULL DEFAULT '',
			source_id varchar(64) NOT NULL DEFAULT '',
			lang varchar(8) NOT NULL DEFAULT '',
			title varchar(255) NOT NULL DEFAULT '',
			content longtext NOT NULL,
			embedding longtext NOT NULL,
			meta_json longtext DEFAULT NULL,
			updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
			PRIMARY KEY  (id),
			UNIQUE KEY chunk_key (chunk_key),
			KEY source_type (source_type),
			KEY source_lookup (source_type, source_id)
		) $charset_collate;";

		require_once ABSPATH . 'wp-admin/includes/upgrade.php';
		dbDelta( $sql );
	}

	/**
	 * Ensure table exists.
	 */
	public static function ensure_tables() {
		global $wpdb;

		static $ensured = false;

		if ( $ensured ) {
			return;
		}

		$table = self::table_name();
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$exists = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) );

		if ( $exists !== $table ) {
			self::create_tables();
		}

		$ensured = true;
	}

	/**
	 * Delete all chunks.
	 */
	public static function delete_all_chunks() {
		global $wpdb;

		self::ensure_tables();

		$table = self::table_name();
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name is plugin-controlled.
		$wpdb->query( "TRUNCATE TABLE $table" );
	}

	/**
	 * @param array<string, mixed> $data Chunk data.
	 * @return bool
	 */
	public static function upsert_chunk( $data ) {
		global $wpdb;

		self::ensure_tables();

		$chunk_key = isset( $data['chunk_key'] ) ? sanitize_text_field( (string) $data['chunk_key'] ) : '';
		$content   = isset( $data['content'] ) ? (string) $data['content'] : '';

		if ( '' === $chunk_key || '' === trim( $content ) ) {
			return false;
		}

		$table = self::table_name();
		$row   = array(
			'chunk_key'   => $chunk_key,
			'source_type' => isset( $data['source_type'] ) ? sanitize_key( (string) $data['source_type'] ) : '',
			'source_id'   => isset( $data['source_id'] ) ? sanitize_text_field( (string) $data['source_id'] ) : '',
			'lang'        => isset( $data['lang'] ) ? sanitize_text_field( (string) $data['lang'] ) : '',
			'title'       => isset( $data['title'] ) ? sanitize_text_field( (string) $data['title'] ) : '',
			'content'     => $content,
			'embedding'   => isset( $data['embedding'] ) ? (string) $data['embedding'] : '[]',
			'meta_json'   => isset( $data['meta_json'] ) ? (string) $data['meta_json'] : null,
			'updated_at'  => current_time( 'mysql' ),
		);

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$existing_id = $wpdb->get_var(
			$wpdb->prepare(
				// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name is plugin-controlled.
				"SELECT id FROM $table WHERE chunk_key = %s LIMIT 1",
				$chunk_key
			)
		);

		if ( $existing_id ) {
			// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			return false !== $wpdb->update( $table, $row, array( 'id' => (int) $existing_id ) );
		}

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		return false !== $wpdb->insert( $table, $row );
	}

	/**
	 * @return int
	 */
	public static function count_chunks() {
		global $wpdb;

		self::ensure_tables();

		$table = self::table_name();
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name is plugin-controlled.
		return (int) $wpdb->get_var( "SELECT COUNT(*) FROM $table" );
	}

	/**
	 * @return array<int, object>
	 */
	public static function get_all_chunks() {
		global $wpdb;

		self::ensure_tables();

		$table = self::table_name();
		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name is plugin-controlled.
		$rows = $wpdb->get_results( "SELECT id, chunk_key, source_type, source_id, lang, title, content, embedding, meta_json FROM $table" );

		return is_array( $rows ) ? $rows : array();
	}
}
