<?php
/**
 * File to handle uninstaller-tasks.
 *
 * @package download-list-block-with-icons
 */

namespace DownloadListWithIcons\Plugin;

// prevent direct access.
defined( 'ABSPATH' ) || exit;

use DownloadListWithIcons\Dependencies\easyTransientsForWordPress\Transients;
use WP_Post;
use WP_Query;

/**
 * Object to handle uninstaller-tasks.
 */
class Uninstaller {

	/**
	 * Instance of this object.
	 *
	 * @var ?Uninstaller
	 */
	private static ?Uninstaller $instance = null;

	/**
	 * Constructor for Init-Handler.
	 */
	private function __construct() {}

	/**
	 * Prevent cloning of this object.
	 *
	 * @return void
	 */
	private function __clone() { }

	/**
	 * Return the instance of this Singleton object.
	 */
	public static function get_instance(): Uninstaller {
		if ( is_null( self::$instance ) ) {
			self::$instance = new self();
		}

		return self::$instance;
	}

	/**
	 * Run uninstallation tasks.
	 *
	 * @return void
	 */
	public function run(): void {
		global $wpdb;

		// delete our own post-type-entries.
		$query = array(
			'post_type'      => 'dl_icons',
			'post_status'    => array( 'any', 'trash' ),
			'posts_per_page' => -1,
			'fields'         => 'ids',
		);
		$posts = new WP_Query( $query );
		foreach ( $posts->get_posts() as $post_id ) {
			if ( $post_id instanceof WP_Post ) {
				continue;
			}
			$post_id = absint( $post_id );

			// get the assigned media-file.
			$attachment_id = absint( get_post_meta( $post_id, 'icon', true ) );

			// remove the image-sizes generated by this plugin from the image.
			if ( $attachment_id > 0 ) {
				$attachment_meta = wp_get_attachment_metadata( $attachment_id );
				// remove our sizes from the meta data.
				if ( $attachment_meta ) {
					if ( ! empty( $attachment_meta['sizes'] ) ) {
						foreach ( $attachment_meta['sizes'] as $name => $size ) {
							if ( str_contains( $name, 'downloadlist-icon-' ) ) {
								unset( $attachment_meta['sizes'][ $name ] );
							}
						}
					}
					// save the updated meta data.
					wp_update_attachment_metadata( $attachment_id, $attachment_meta );
				}
			}

			// delete the entry.
			wp_delete_post( $post_id, true );
		}

		// delete all terms of our taxonomy.
		$taxonomy = 'dl_icon_set';
		$wpdb->query(
			$wpdb->prepare(
				'DELETE FROM ' . $wpdb->terms . '
			WHERE term_id IN
			(
				SELECT ' . $wpdb->terms . '.term_id
				FROM ' . $wpdb->terms . '
				JOIN ' . $wpdb->term_taxonomy . '
				ON ' . $wpdb->term_taxonomy . '.term_id = ' . $wpdb->terms . '.term_id
				WHERE taxonomy = %s
			)',
				array(
					$taxonomy,
				)
			)
		);

		// delete all taxonomy-entries.
		$wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $wpdb->term_taxonomy . ' WHERE taxonomy = %s', array( $taxonomy ) ) );

		// cleanup options from our taxonomy.
		delete_option( $taxonomy . '_children' );

		// get the filesystem handler.
		$wp_filesystem = Helper::get_wp_filesystem();

		// delete style-file.
		$path = Helper::get_style_path();
		if ( $wp_filesystem->exists( $path ) ) {
			$wp_filesystem->delete( $path );
		}

		// get media files with title and/or description to delete these entries.
		$query = array(
			'post_type'      => 'attachment',
			'post_status'    => array( 'any', 'trash' ),
			'posts_per_page' => -1,
			'fields'         => 'ids',
			'meta_query'     => array(
				'relation' => 'OR',
				array(
					'key'     => 'dl_title',
					'compare' => 'EXIST',
				),
				array(
					'key'     => 'dl_description',
					'compare' => 'EXIST',
				),
			),
		);
		$posts = new WP_Query( $query );
		foreach ( $posts->get_posts() as $post_id ) {
			if ( $post_id instanceof WP_Post ) {
				continue;
			}
			delete_post_meta( absint( $post_id ), 'dl_title' );
			delete_post_meta( absint( $post_id ), 'dl_description' );
		}

		// delete transients.
		$transients_obj = Transients::get_instance();
		foreach ( $transients_obj->get_transients() as $transient_obj ) {
			// delete transient-data.
			$transient_obj->delete();

			// delete dismiss-marker for this transient.
			delete_option( 'dl-dismissed-' . md5( $transient_obj->get_name() ) );
		}

		// delete options.
		$options = array(
			'downloadlistVersion',
			'downloadlist_inheriting_count',
			'downloadlist_inheriting_max',
			'downloadlist_inheriting_status',
			'downloadlist_inheriting_running',
			DL_TRANSIENT_LIST,
		);
		foreach ( $options as $option ) {
			delete_option( $option );
		}

		// enable the settings.
		$settings_obj = Settings::get_instance();
		$settings_obj->add_settings();
		$settings_obj->get_settings_obj()->activation();
		// and remove them.
		$settings_obj->get_settings_obj()->delete_settings();
	}
}
