<?php

namespace RtmMail\Helpers;

use Dubture\Monolog\Reader\LogReader;

/**
 * EventHelper - Helper for loading log data to a table
 */
class EventHelper
{
    /**
     * DEFAULT_ARGS - default settings to use for getting all logs
     * @type array
     */
    const DEFAULT_ARGS = [
        'orderby' => 'date',
        'order' => 'DESC',
        'post_per_page' => 10,
        'paged' => 1,
        'date' => null,
        's' => null,
    ];

    /**
     * get - Get all the logs from WP_PLUGIN_DIR/rtm-mail/logs
     * @param array $args
     * @return array
     */
    public static function get($args = [])
    {
        // Merge the defaults with given args
        $args = array_merge(self::DEFAULT_ARGS, $args);

        // total logs array
        $logs = [];
        $upload = wp_upload_dir();
        // Get all directories in logs path
        $log_directories = self::get_directories($upload['basedir'] . '/rtm-mail/logs');
        foreach ($log_directories as $directory) {
            // Scan for files in each directory
            $directory_files = array_diff(scandir($directory), ['.', '..']);
            // Array to save every log file path
            $log_paths = [];
            foreach ($directory_files as $log_file) {
                // For every file check if it has a log extension
                $ext = explode('.', $log_file);
                if (!empty($log_file) && isset($ext[1]) && strtolower($ext[1]) === 'log') {
                    // Add to paths array
                    $log_paths[] = $directory . '/' . $log_file;
                }
            }
            // Loop through every path
            foreach ($log_paths as $path) {
                // Add file path to the reader
                $reader = new LogReader($path, 0);
                // Loop through every line and add to logs when the channel is RTMMAIL
                foreach ($reader as $log) {
                    if (isset($log['logger']) && $log['logger'] === 'RTMMAIL') {
                        $logs[] = $log;
                    }
                }
            }
        }
        // Check for a given search string and filter
        if ($args['s'] != null && (isset($args['search_filter']) && !empty($args['search_filter']))) {
            // Filter the array by checking for every search_filter if the given string is in the log data
            $logs = array_filter($logs, function ($log_data) use ($args) {
                if ((isset($args['search_filter']['log_id']) && filter_var($args['search_filter']['log_id'], FILTER_VALIDATE_BOOLEAN) && isset($log_data['context']['log_id']) && $args['s'] === $log_data['context']['log_id']) ||
                    (isset($args['search_filter']['message']) && filter_var($args['search_filter']['message'], FILTER_VALIDATE_BOOLEAN) && stripos(strtolower($log_data['message']), strtolower($args['s'])) !== false) ||
                    (isset($args['search_filter']['level']) && filter_var($args['search_filter']['level'], FILTER_VALIDATE_BOOLEAN) && stripos(strtolower($log_data['level']), strtolower($args['s'])) !== false)) {
                    return true;
                }
                return false;
            });
        }

        // Check if date range is not null
        if ($args['date'] != null) {
            // Separate the start and end date
            $dates = explode(' - ', sanitize_text_field(wp_unslash($args['date'])));
            // Filter the array between the dates
            $logs = array_filter($logs, function ($log_data) use ($dates) {
                $log_time = strtotime($log_data['date']->format('d-m-Y'));
                return $log_time >= strtotime($dates[0]) && $log_time <= strtotime($dates[1]);
            });
        }

        // Check if a filter_level is given
        if (isset($args['filter_level']) && isset($args['level_type']) && !empty($args['level_type'])) {
            // Filter the array by which level is selected
            $logs = array_filter($logs, function ($log_data) use ($args) {
                if (stripos(strtolower($log_data['level']), $args['level_type']) !== false) {
                    return true;
                }
                return false;
            });
        }

        // Order by level or date with given order type
        if (!empty($args['orderby']) && !empty($args['order'])) {
            if (strtolower($args['orderby']) === 'date') {
                // Order array by date depending on asc/desc
                usort($logs, function ($a, $b) use ($args) {
                    if ($a == $b) {
                        return 0;
                    }
                    if (strtolower($args['order']) === 'asc') {
                        return $a['date'] > $b['date'];
                    }
                    return $a['date'] < $b['date'];
                });
            } else if (strtolower($args['orderby']) === 'level') {
                usort($logs, function ($a, $b) use ($args) {
                    if (strtolower($args['order']) === 'asc') {
                        return strcmp($a['level'], $b['level']);
                    }
                    return strcmp($b['level'], $a['level']);
                });
            }
        }

        // Pagination for array
        if ($args['post_per_page'] != null && $args['post_per_page'] !== -1) {
            $logs = array_slice($logs, (($args['paged'] - 1) * $args['post_per_page']), $args['post_per_page']);
        }
        return $logs;
    }

    /**
     * get_directories - Get a list of every directory in a given starting path
     * @param $path
     * @return array|false
     */
    private static function get_directories($path)
    {
        $all_directories = [];
        $directories = array_filter(glob($path), 'is_dir');
        $all_directories = array_merge($all_directories, $directories);
        foreach ($directories as $directory) {
            $all_directories = array_merge($all_directories, self::get_directories($directory . '/*'));
        }

        return $all_directories;
    }

    /**
     * delete - delete all log files
     * @param false $deleted_only - only delete lines from deleted mail logs
     */
    public static function delete($deleted_only = false)
    {
        $upload = wp_upload_dir();
        // Get all directories in logs path
        $log_directories = self::get_directories($upload['basedir'] . '/rtm-mail/logs');
        // Array to save every log file path
        $log_paths = [];
        foreach ($log_directories as $directory) {
            // Scan for files in each directory
            $directory_files = array_diff(scandir($directory), ['.', '..']);
            foreach ($directory_files as $log_file) {
                // For every file check if it has a log extension
                $ext = explode('.', $log_file);
                if (!empty($log_file) && isset($ext[1]) && strtolower($ext[1]) === 'log') {
                    // Add to paths array
                    $log_paths[] = $directory . '/' . $log_file;
                }
            }
        }
        // Check if only to remove deleted mail logs
        if (!$deleted_only) {
            foreach ($log_paths as $file_path) {
                unlink($file_path);
            }
        } else {
            // Get all deleted mail logs
            $deleted_logs = self::get(['post_per_page' => null, 'search_filter' => ['message' => 'on'], 's' => 'deleted']);
            // Loop through all logs and paths
            foreach ($deleted_logs as $mail_log) {
                foreach ($log_paths as $file_path) {
                    // Get content of log file
                    $file = file_get_contents($file_path);
                    // Get every line
                    $lines = explode("\n", str_replace("\\r\\n", "\n", $file));
                    $new_lines = [];
                    // Loop over every line
                    foreach ($lines as $line) {
                        // Check if the current log_id contains in this line
                        if (strpos($line, '"log_id":"' . $mail_log['context']['log_id'] . '"')) {
                            // Skip this line
                            continue;
                        }
                        // Add line to the new lines if its not empty
                        if (!empty($line)) {
                            $new_lines[] = $line;
                        }
                    }
                    // Create new file content
                    $new_file = implode("\n", $new_lines);
                    // Set new file content
                    file_put_contents($file_path, $new_file);
                }
            }
        }
    }

    /**
     * get_total_rows - Get total amount of rows
     * @return int|void
     */
    public static function get_total_rows($args = [])
    {
        $args = array_merge($args, ['post_per_page' => -1]);
        return count(self::get($args));
    }
}