<?php

namespace RemoveUnusedMedia\Util;

use Generator;
use RemoveUnusedMedia\DB as DB;
use WP_Query;

require_once 'rum_pro_search_conf.php';

use function wp_reset_postdata;

function debug_logging($message)
{
    $log = get_option("rum_log", array_fill(0, 100, []));
    array_unshift($log, [time(), $message]);
    array_pop($log);
    update_option("rum_log", $log, true);

    if(defined('RUM_DEBUG_LOGGING')) {
        error_log($message);
    }
}

function human_filesize($bytes, $decimals = 0): string
{
    $sz     = ['B', 'K', 'M', 'G', 'T', 'P'];
    $factor = floor((strlen($bytes) - 1) / 3);
    if ($factor > 1) {
        $decimals = 1;
    } elseif (!$bytes) {
        return '0B';
    }

    return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$sz[$factor];
}

function get_posts($types = false, $offset = 0): Generator
{
    if (!$types) {
        $types = get_post_types();
    }
    $args  = [
        'suppress_filters' => true,
        'post_type'        => $types,
        'offset'           => $offset,
        'post_status'      => 'any',
        'sort_order'       => 'asc',
        'orderby'          => 'ID',
        'lang'             => '',
        'posts_per_page'   => 15,
    ];
    $query = new WP_Query($args);
    while ($query->have_posts()) {
        $query->the_post();
        yield get_the_ID();
        wp_cache_delete(get_the_ID(), 'posts');
        wp_cache_delete(get_the_ID(), 'post_meta');
    }
    wp_reset_postdata();
}

function get_media($offset = 0): array
{
    return DB\get_col(
        'posts',
        'ID',
        "`post_type`='attachment' AND `post_status`='inherit' ORDER BY `ID` ASC LIMIT $offset, 15"
    );
}

function get_used(): array
{
    if (!DB\table_exists(DB\RESULT)) {
        return [];
    }
    $ignored = get_option('rum_ignored', []);
    if ($ignored) {
        $ignored  = join(",", $ignored);
        $data_raw = DB\get(
            DB\RESULT,
            ['id', 'used_where', 'used_how', 'url'],
            "used_where IS NOT NULL AND id NOT IN ($ignored)"
        );
    } else {
        $data_raw = DB\get(
            DB\RESULT,
            ['id', 'used_where', 'used_how', 'url'],
            "used_where IS NOT NULL"
        );
    }
    $data = [];
    foreach ($data_raw as $u) {
        $data[$u['id']] = [
            'ID'    => $u['id'],
            'url'   => $u['url'],
            'where' => unserialize($u['used_where']),
            'how'   => unserialize($u['used_how']),
        ];
    }

    return $data;
}

function get_unused(): array
{
    if (!DB\table_exists(DB\RESULT)) {
        return [];
    }
    $ignored = get_option('rum_ignored', []);
    if ($ignored) {
        $ignored  = join(",", $ignored);
        $data_raw =
            DB\get(DB\RESULT, ['id', 'used_where', 'used_how', 'url'], "used_where IS NULL AND id NOT IN ($ignored)");
    } else {
        $data_raw = DB\get(DB\RESULT, ['id', 'used_where', 'used_how', 'url'], "used_where IS NULL");
    }
    $data = [];
    foreach ($data_raw as $u) {
        $data[$u['id']] = [
            'ID'  => $u['id'],
            'url' => $u['url'],
        ];
    }

    return $data;
}

function get_ignored(): array
{
    if (!DB\table_exists(DB\RESULT)) {
        return [];
    }
    $ignored = get_option('rum_ignored', []);
    if (!$ignored) {
        return [];
    }
    $ignored     = join(",", $ignored);
    $ignored_raw = DB\get(DB\RESULT, ['id', 'url'], "id IN ($ignored)");
    $ignored     = [];
    foreach ($ignored_raw as $u) {
        $ignored[$u['id']] = [
            'ID'  => $u['id'],
            'url' => $u['url'],
        ];
    }

    return $ignored;
}

function num_used(): int
{
    $ignored = get_option('rum_ignored', []);
    if ($ignored) {
        $ignored = " AND id NOT IN (" . join(",", $ignored) . ")";
    } else {
        $ignored = "";
    }
    $wpml_lang = apply_filters('wpml_current_language', null);
    if (!empty($wpml_lang) && 'all' !== $wpml_lang) {
        return DB\count_wpml(DB\RESULT, $wpml_lang, "used_where IS NOT NULL$ignored");
    }

    return DB\count(DB\RESULT, "used_where IS NOT NULL$ignored");
}

function num_unused(): int
{
    $ignored = get_option('rum_ignored', []);
    if ($ignored) {
        $ignored = " AND id NOT IN (" . join(",", $ignored) . ")";
    } else {
        $ignored = "";
    }
    $wpml_lang = apply_filters('wpml_current_language', null);
    if (!empty($wpml_lang) && 'all' !== $wpml_lang) {
        return DB\count_wpml(DB\RESULT, $wpml_lang, "used_where IS NULL$ignored");
    }

    return DB\count(DB\RESULT, "used_where IS NULL$ignored");
}

function num_ignored(): int
{
    $ignored = get_option('rum_ignored', []);
    if (!$ignored) {
        return 0;
    }
    $ignored = join(",", $ignored);

    $wpml_lang = apply_filters('wpml_current_language', null);
    if (!empty($wpml_lang) && 'all' !== $wpml_lang) {
        return DB\count_wpml(DB\RESULT, $wpml_lang, "id IN ($ignored)");
    }

    return DB\count(DB\RESULT, "id IN ($ignored)");
}

function url_warnings(): array
{
    if (!DB\table_exists(DB\RESULT)) {
        return [];
    }
    $ignored = get_option('rum_ignored', []);
    if ($ignored) {
        $ignored = join(",", $ignored);

        return DB\get_col(DB\RESULT, 'id', "url_warning AND id not IN ($ignored)");
    }

    return DB\get_col(DB\RESULT, 'id', "url_warning");
}

function num_posts($types = []): int
{
    if(!count($types)) {
        $types = get_post_types();
    }

    $types = "\"" . implode("\",\"", $types) . "\"";

    return DB\count('posts', "post_type IN($types) AND post_status NOT IN('trash','auto-draft')");
}

function num_media(): int
{
    return DB\count('posts', ['post_type' => "'attachment'", 'post_status' => "'inherit'"]);
}

const SPECIAL_CPTs = [
    'attachment',
    'shop_order',
    'shop_order_refund',
    'revision',
];

function get_post_types(): array
{
    global $wpdb;
    $r = $wpdb->get_col("SELECT DISTINCT(post_type) FROM {$wpdb->prefix}posts");

    return array_diff($r, SPECIAL_CPTs);
}

function reset($hard = false)
{
    debug_logging(($hard ? "hard" : "soft") . " reset");
    $settings = [
        'rum_cache',//pre 1.2.0
        'rum_cached',//pre 1.3.0
        'rum_data',//pre 1.2.0
        'rum_waiting',//pre 1.3.0
        'rum_timing',//pre 1.3.0
        'rum_analysis_running',
        'rum_time',
        'rum_error_types',
        'rum_error',
        'rum_crashed',
    ];
    if ($hard) {
        $settings = array_merge($settings, [
            'remove-unused-media',//pre 1.2.0
            'rum_analysis_counter',
            'rum_analytics',
            'rum_deleted',
            'rum_dismissed_backup',
            'rum_ignored',
            'rum_log',
            'rum_media',//pre 1.2.0
            'rum_trashed',
            'rum_timeout',
        ]);
    }
    if (file_exists(dirname(__FILE__) . '/abort')) {//pre 1.3.0
        unlink(dirname(__FILE__) . '/abort');
    }
    DB\drop(DB\RESULT);
    foreach ($settings as $s) {
        delete_option($s);
    }
}

function check_rum_pro_active_items() {
    $found_items = [];

    // Check active plugins
    if (function_exists('get_plugins')) {
        $active_plugins = get_option('active_plugins', []);
        $all_plugins = get_plugins();

        // Check regular plugins
        foreach (RUM_PRO_PLUGINS as $text_domain => $value) {
            foreach ($active_plugins as $plugin_file) {
                if (strpos($plugin_file, $text_domain . '/') === 0 || strpos($plugin_file, $text_domain . '.php') !== false) {
                    // Get the real plugin name from plugin data
                    if (isset($all_plugins[$plugin_file]['Name'])) {
                        $found_items[] = $all_plugins[$plugin_file]['Name'];
                    } else {
                        // Fallback to text domain if name not found
                        $found_items[] = $text_domain;
                    }
                    break;
                }
            }
        }

        // Check special plugins
        foreach (RUM_PRO_SPECIAL_PLUGINS as $text_domain => $value) {
            foreach ($active_plugins as $plugin_file) {
                if (strpos($plugin_file, $text_domain . '/') === 0 || strpos($plugin_file, $text_domain . '.php') !== false) {
                    // Get the real plugin name from plugin data
                    if (isset($all_plugins[$plugin_file]['Name'])) {
                        $found_items[] = $all_plugins[$plugin_file]['Name'];
                    } else {
                        // Fallback to text domain if name not found
                        $found_items[] = $text_domain;
                    }
                    break;
                }
            }
        }
    }

    // Check active theme
    $current_theme = get_option('stylesheet'); // Gets the directory name of the active theme
    $parent_theme = get_option('template');    // Gets the parent theme if child theme is active

    // Check regular themes (if you add any to RUM_PRO_THEMES)
    foreach (RUM_PRO_THEMES as $text_domain => $value) {
        if ($current_theme === $text_domain || $parent_theme === $text_domain) {
            // Get the real theme name
            $theme_data = wp_get_theme($text_domain);
            if ($theme_data->exists()) {
                $found_items[] = $theme_data->get('Name');
            } else {
                // Fallback to text domain if theme data not found
                $found_items[] = $text_domain;
            }
        }
    }

    // Check special themes
    foreach (RUM_PRO_SPECIAL_THEMES as $text_domain => $value) {
        if ($current_theme === $text_domain || $parent_theme === $text_domain) {
            // Get the real theme name
            $theme_data = wp_get_theme($text_domain);
            if ($theme_data->exists()) {
                $found_items[] = $theme_data->get('Name');
            } else {
                // Fallback to text domain if theme data not found
                $found_items[] = $text_domain;
            }
        }
    }

    // Remove duplicates and return
    return array_unique($found_items);
}