<?php

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

require_once realpath(__DIR__) . '/../views/pages/404-redirects.php';
require_once realpath(__DIR__) . '/../services/email.php';
require_once realpath(__DIR__) . '/../services/ip.php';
require_once realpath(__DIR__) . '/../helpers/utils.php';
require_once realpath(__DIR__) . '/ScheduleTrait.php';


class ISTKR_404Controller
{
    use ScheduleTrait;
    
    const SCHEDULE_MAIL_SEND = 'ISTKR_NOTIFY_404_URL';

    public static function istkr_render_view()
    {
        return ISTKR_404View::istkr_render_view();
    }

    // fire on template redirect hook
    public static function istkr_handle_404()
    {
        global $wpdb;

        if (is_404() && !is_admin()) {

            $attack_end_time = get_option('istkr_attack_end_time');
            if ($attack_end_time) {
                if (strtotime($attack_end_time) > time()) {
                    return false;
                } else {
                    delete_option('istkr_attack_end_time');
                }
            }

            if (self::istkr_404_is_site_under_attack()) {
                self::istkr_404_send_site_under_attack_email();

                $attack_end_time = date('Y-m-d H:i:s', strtotime('+1 hour'));

                add_option('istkr_attack_end_time', $attack_end_time, '', 'yes');
            }

            $path = untrailingslashit(esc_url($_SERVER['REQUEST_URI']));
            $ip = istkr_get_ip_address();
            $user_agent = esc_attr($_SERVER['HTTP_USER_AGENT']);

            $current_row = $wpdb->get_results("SELECT path, hits, referrer FROM " . ISTKR_404_LOG . " WHERE path = '" . $path . "'", ARRAY_A);

            if (isset($current_row[0]) && $current_row[0]['path']) {
                $wpdb->update(ISTKR_404_LOG, ['hits' => $current_row[0]['hits'] + 1], ['path' => $path]);
            } else {
                // id, hits, created, updated - will filled automatically
                $referrer = wp_get_referer() ? wp_get_referer() : 'n/a';
                $country_info = istkr_get_country_info_by_ip($ip);
                $wpdb->insert(ISTKR_404_LOG, [
                    'path' => $path,
                    'referrer' => $referrer,
                    'user_agent' => $user_agent,
                    'ip' => $ip,
                    'country_flag' => $country_info['country_flag'],
                    'country_name' => $country_info['country_name'],
                ]);
            }
        }
    }

    // fire by schedule if the notification is enables
    public static function istkr_send_404_log_handler($event)
    {
        global $wpdb;
        global $WP_CRON_SCHEDULE_INTERVALS;

        $options = get_option($event);

        if (!$options) {
            error_log('Options not found for event ' . $event);
            wp_die();
        }

        if (!array_key_exists('notifications_email', $options)) {
            error_log('Notification email not found in options for event ' . $event);
            wp_die();
        }
            
        if (!array_key_exists('notifications_email_recurrence', $options)) {
            error_log('Notification email recurrence not found in options for event ' . $event);
            wp_die();
        }

        $notification_email = $options['notifications_email'];
        $recurrence = $options['notifications_email_recurrence'];

        $datetime = new DateTime();
        $datetime->sub($WP_CRON_SCHEDULE_INTERVALS[$recurrence]);
        $datetimeOffset = $datetime->format('Y-m-d H:i:s');

        $records = $wpdb->get_results("SELECT DISTINCT * FROM " . ISTKR_404_LOG . " WHERE updated_at > '" . $datetimeOffset . "' ORDER BY id DESC LIMIT 500", ARRAY_A);

        if ($notification_email && $records) {
            // New 404 registered. Need to send notification if enabled.
            istkr_send_404_email(
                $notification_email,
                'Issues Tracker: New 404 URL found on your website',
                realpath(__DIR__) . '/../templates/email/404.tpl',
                [
                    'website' => get_site_url(),
                    'records' => $records,
                ]
            );
        }
    }

    // uses to render table in browser
    public static function istkr_get_404_log()
    {
        global $wpdb;
        verify_nonce($_POST);

        try {
            $draw = isset($_POST['draw']) ? (int) $_POST['draw'] : 0;
            $start = isset($_POST['start']) ? (int) $_POST['start'] : 1;
            $length = isset($_POST['length']) ? (int) $_POST['length'] : 25;
            $search_value = isset($_POST['search']['value']) ? sanitize_text_field($_POST['search']['value']) : null;

            $storage = [];

            $rows = $wpdb->get_results("SELECT *  FROM " . ISTKR_404_LOG . " ORDER BY STR_TO_DATE(created_at, '%Y-%m-%d %H:%i:%s') DESC", ARRAY_A);

            if (!$rows) {
                echo json_encode([
                    'success' => true,
                    'data' => [],
                    'draw' => $draw,
                    'recordsFiltered' => 0,
                    'recordsTotal' => 0
                ]);
                wp_die();
            }

            $storage = [];
            $rows_count = 0;
            foreach ($rows as $row) {
                if (!empty($row)) {

                    $rows_count++;

                    $country = !$row['country_flag'] && !$row['country_name'] ? 'Unknown' : $row['country_flag'] . ' ' . $row['country_name'];

                    array_push($storage, [
                        'id'           => $row['id'],
                        'path'         => $row['path'],
                        'referrer'     => $row['referrer'],
                        'user_agent'   => $row['user_agent'],
                        'ip'           => $row['ip'],
                        'country'      => $country,
                        'hits'         => $row['hits'],
                        'created_at'   => $row['created_at'],
                        'updated_at'   => $row['updated_at'],
                    ]);
                }
            }

            if ($search_value) {
                $search_string = trim(strtolower($search_value));
                $data = [];
                foreach ($storage as $index => $row) {
                    $results = find_string($row, $search_string);

                    if ($results) {
                        $data[] = $storage[$index];
                    }
                }

                $search_results_length = count($data);

                $storage = array_slice($data, $start, $length);
            } else {
                $storage = array_slice($storage, $start, $length);
            }

            echo json_encode([
                'success' => true,
                'data' => $storage ? $storage : [],
                'draw' => $draw,
                'recordsTotal' => $rows_count,
                'recordsFiltered' => $search_value ? $search_results_length : $rows_count,
            ]);
            wp_die();
        } catch (Exception $e) {
            // Do nothing
        }
    }

    public static function istkr_get_current_user_email()
    {
        verify_nonce($_POST);

        try {
            global $current_user;

            echo json_encode([
                'success' => true,
                'data' => $current_user->user_email
            ]);
            wp_die();
        } catch (Exception $e) {
            echo json_encode([
                'success' => false,
                'error' => $e->getMessage()
            ]);
            wp_die();
        }
    }

    public static function istkr_get_404_count()
    {
        verify_nonce($_POST);

        try {

            global $wpdb;
            $rows = $wpdb->get_results("SELECT COUNT(*) FROM " . ISTKR_404_LOG, ARRAY_A);

            echo json_encode([
                'success' => true,
                'data' => array_values($rows[0]) ?  array_values($rows[0])[0] : __('N/A', 'istkr')
            ]);
            wp_die();
        } catch (Exception $e) {
            echo json_encode([
                'success' => false,
                'error' => $e->getMessage()
            ]);
            wp_die();
        }
    }

    public static function istkr_404_clear_log()
    {
        verify_nonce($_POST);

        try {
            global $wpdb;

            $wpdb->get_results("DELETE FROM " . ISTKR_404_LOG, ARRAY_A);

            echo json_encode([
                'success' => true
            ]);
            wp_die();
        } catch (Exception $e) {
            echo json_encode([
                'success' => false,
                'error' => $e->getMessage()
            ]);
            wp_die();
        }
    }

    public static function istkr_404_recheck_path()
    {
        verify_nonce($_POST);
        
        try {
            global $wpdb;

            $id = isset($_POST['id']) ? (int) ($_POST['id']) : null;

            if (!$id) {
                throw new Exception('Key "id" not found in request');
            }

            $query = $wpdb->prepare('SELECT path FROM ' . ISTKR_404_LOG . ' WHERE `id`= %d LIMIT 1;', $id);

            $row = $wpdb->get_row($query);

            if (!$row) {
                throw new Exception('Specified path is not found in the database');
            }

            $url = get_home_url();

            $response = wp_remote_get(rtrim($url, '/') . $row->path);

            if ($response['response']['code'] === 200) {

                $wpdb->delete(ISTKR_404_LOG, array('id' => $id));

                echo json_encode([
                    'success' => true
                ]);
                wp_die();
            } else {
                echo json_encode([
                    'success' => false
                ]);
                wp_die();
            }
        } catch (Exception $e) {
            echo json_encode([
                'success' => false,
                'error' => $e->getMessage()
            ]);
            wp_die();
        }
    }

    public static function istkr_404_remove_path()
    {
        verify_nonce($_POST);
        
        try {
            global $wpdb;

            $id = isset($_POST['id']) ? (int) ($_POST['id']) : null;

            if (!$id) {
                throw new Exception('Key "ID" not found in request');
            }

            $wpdb->delete(ISTKR_404_LOG, array('id' => $id));

            echo json_encode([
                'success' => true
            ]);
            wp_die();
        } catch (Exception $e) {
            echo json_encode([
                'success' => false,
                'error' => $e->getMessage()
            ]);
            wp_die();
        }
    }

    public static function istkr_404_deactivate()
    {
        $notificator = new ISTKR_Notificator(new self());

        if ($notificator->istkr_is_notification_enabled()) {
            self::istkr_delete_wp_schedule_event($notificator->istkr_build_unique_event_name());
        }

        wp_unschedule_hook(self::SCHEDULE_MAIL_SEND);
    }

    public static function istkr_404_is_site_under_attack()
    {
        global $wpdb;
        
        $period = ISTKR_SITE_UNDER_ATTACK_TIME_PERIOD;
        $query = "SELECT COUNT(*) FROM " . ISTKR_404_LOG . " WHERE created_at > DATE_SUB(NOW(), INTERVAL %d MINUTE) OR updated_at > DATE_SUB(NOW(), INTERVAL %d MINUTE)";
        $count = $wpdb->get_var($wpdb->prepare($query, $period, $period));
    
        return $count >= ISTKR_SITE_UNDER_ATTACK_404_COUNT;
    }

    public static function istkr_404_send_site_under_attack_email()
    {
        global $wpdb;

        $notification_email = get_option('admin_email');
        $period = ISTKR_SITE_UNDER_ATTACK_TIME_PERIOD;
        $query = "SELECT * FROM " . ISTKR_404_LOG . " WHERE created_at > DATE_SUB(NOW(), INTERVAL %d MINUTE) OR updated_at > DATE_SUB(NOW(), INTERVAL %d MINUTE)";
        $records = $wpdb->get_results($wpdb->prepare($query, $period, $period), ARRAY_A);

        if ($notification_email && $records) {
            istkr_send_404_email(
                $notification_email,
                'Issues Tracker: Suspicious activity has been detected on your website',
                realpath(__DIR__) . '/../templates/email/site_under_attack.tpl',
                [
                    'website' => get_site_url(),
                    'records' => $records,
                ]
            );
        }
    }
}
