<?php
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Plugin uses custom tables and controlled internal query builders.
namespace SPAATG\Helper;

if (! defined('ABSPATH')) {
	exit; // Exit if accessed directly.
}

use SPAATG\ShortPixelLogger\ShortPixelLogger as Log;
use SPAATG\Controller\QueueController as QueueController;
use SPAATG\Controller\CronController as CronController;
use SPAATG\Controller\BulkController as BulkController;
use SPAATG\Controller\AdminNoticesController as AdminNoticesController;
use SPAATG\Controller\ApiKeyController as ApiKeyController;
use SPAATG\Model\SettingsModel as SettingsModel;


class InstallHelper
{

	public static function activatePlugin()
	{
		self::resetActivationState();

		self::checkTables();

		AdminNoticesController::resetOldNotices();
		\SPAATG_Settings::onActivate();

		try {
			$queueController = new QueueController();
			$q = $queueController->getQueue('media');
			$q->getShortQ()->install(); // create table.
		} catch (\Throwable $e) {
			Log::addWarn('ShortQ install failed during activation. Setup will retry on next admin load.', $e->getMessage());
		}

		$settings = SettingsModel::getInstance();
		$settings->currentVersion = SPAATG_IMAGE_OPTIMISER_VERSION;

		wp_cache_flush();
	}

	public static function deactivatePlugin()
	{
		$settings = new \SPAATG_Settings(); // \wpSPAATG()->settings();
		$settings::onDeactivate();

		self::clearPluginTransients();

			try {
				CronController::getInstance()->onDeactivate();
		} catch (\Throwable $e) {
			Log::addWarn('Cron cleanup failed during deactivation', $e->getMessage());
		}
	}

	public static function uninstallPlugin()
	{
		QueueController::uninstallPlugin();
		ApiKeyController::uninstallPlugin();

		delete_transient('spaatg_bulk-secret');
		delete_transient('spaatg_quotadata');
	}

	// Removes SPAATG data only. This must not touch unrelated files, tables, or .htaccess rules.
	public static function hardUninstall()
	{
		if (! current_user_can('manage_options')) {
			wp_die(esc_html__('You are not allowed to remove plugin data.', 'shortpixel-ai-alt-text-generator'));
		}

		$settings = new \SPAATG_Settings();

		$nonce = (isset($_POST['tools-nonce'])) ? sanitize_key(wp_unslash($_POST['tools-nonce'])) : null;
		if (! wp_verify_nonce($nonce, 'remove-all')) {
			wp_nonce_ays('');
		}

		self::deactivatePlugin(); // deactivate
		self::uninstallPlugin(); // uninstall

		// Bulk Log
		BulkController::uninstallPlugin();

		$settings::resetOptions();

		// new settings
		delete_option('spaatg_settings');

		self::removeTables();

		// Deactivate this plugin itself after removing SPAATG data.
		deactivate_plugins(plugin_basename(SPAATG_PLUGIN_FILE));
	}

	private static function resetActivationState()
	{
		\SPAATG_Settings::onDeactivate();
		self::clearPluginTransients();
	}

	private static function clearPluginTransients()
	{
		global $wpdb;

		if (! isset($wpdb) || ! isset($wpdb->options)) {
			return;
		}

		$sql = "delete from " . $wpdb->options . " where option_name like '%_transient_spaatg_%' or option_name like '%_transient_timeout_spaatg_%'";
			// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Static transient cleanup query; table name comes from $wpdb->options.
			$wpdb->query($sql); // remove this plugin's transients.
	}

	/**
	 * Check if TableName exists
	 * @param $tableName The Name of the Table without Prefix.
	 */
	public static function checkTableExists($tableName)
	{
		global $wpdb;
		$tableName = $wpdb->prefix . $tableName;
		$sql = $wpdb->prepare("
		               SHOW TABLES LIKE %s
		               ", $tableName);

			// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Query is prepared above.
			$result = intval($wpdb->query($sql));

		if ($result == 0)
			return false;
		else {
			return true;
		}
	}


	public static function checkTables()
	{
		global $wpdb;
		require_once(ABSPATH . 'wp-admin/includes/upgrade.php');

			dbDelta(self::getAIPostSQL());
			self::migrateLegacyAIPostTable();

			self::checkIndexes();
	}

	private static function checkIndexes()
	{
		global $wpdb;

		$definitions = array(
			'spaatg_aipostmeta' => array(
				'attach_id' => 'attach_id',
				'status' => 'status',
			),
		);

		foreach ($definitions as $raw_tableName => $indexes) {
			$tableName = $wpdb->prefix . $raw_tableName;
			foreach ($indexes as $indexName => $fieldName) {
				// Check exists
				$sql = 'SHOW INDEX FROM ' . $tableName . ' WHERE Key_name = %s';
				// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Query string contains validated dynamic table or clause fragments and is prepared before execution.
				$sql = $wpdb->prepare($sql, $indexName);

					// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Query is prepared above; table/index names are plugin-defined.
					$res = $wpdb->get_row($sql);

				if (is_null($res)) {
					// can't prepare for those, also not any user data here.
					$sql = 'CREATE INDEX ' . $indexName . ' ON ' . $tableName . ' ( ' . $fieldName . ')';
						// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- CREATE INDEX identifiers are plugin-defined, not user input.
						$res = $wpdb->query($sql);
				}
			}
		}
	}

	private static function removeTables()
	{
		global $wpdb;
		if (self::checkTableExists('spaatg_aipostmeta') === true) {
			$sql = 'DROP TABLE  ' . $wpdb->prefix . 'spaatg_aipostmeta';
					// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- DROP TABLE target is plugin-defined.
					$wpdb->query($sql);
		}
	}

	private static function migrateLegacyAIPostTable()
	{
		global $wpdb;

		if (self::checkTableExists('spaatg_aipostmeta') !== true || self::checkTableExists('shortpixel_aipostmeta') !== true) {
			return;
		}

		$new_table = $wpdb->prefix . 'spaatg_aipostmeta';
		$legacy_table = $wpdb->prefix . 'shortpixel_aipostmeta';

		$sql = "INSERT INTO {$new_table} (post_type, attach_id, original_data, generated_data, old_filename, new_filename, status, tsUpdated)
			SELECT post_type, attach_id, original_data, generated_data, old_filename, new_filename, status, tsUpdated
			FROM {$legacy_table} legacy
			WHERE NOT EXISTS (
				SELECT 1 FROM {$new_table} current
				WHERE current.attach_id = legacy.attach_id AND current.post_type = legacy.post_type
			)";
		// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Both table names are plugin-defined legacy/current AI tables.
		$wpdb->query($sql);
	}

	private static function getAIPostSQL()
	{
		global $wpdb; 
		$charsetCollate = $wpdb->get_charset_collate();
		$prefix = $wpdb->prefix;

		$sql = "CREATE TABLE {$prefix}spaatg_aipostmeta (
				id bigint unsigned not null AUTO_INCREMENT, 
				post_type tinyint default 1,
				attach_id bigint unsigned NOT NULL,  
				original_data text, 
				generated_data text, 
				old_filename varchar(300), 
				new_filename varchar(300),
				status int, 
				tsUpdated timestamp, 
				PRIMARY KEY id (id)
		) $charsetCollate";

		return $sql;
	}
} // InstallHelper
