<?php

namespace CleantalkSP\SpbctWP\Scanner;

use CleantalkSP\Fpdf\Pdf;
use CleantalkSP\SpbctWP\Scanner\ScannerActions\BackupsActions;
use CleantalkSP\SpbctWP\Scanner\ScannerActions\CloudAnalysisActions;
use CleantalkSP\SpbctWP\Scanner\ScannerActions\FileSystemActions;
use CleantalkSP\SpbctWP\Scanner\ScannerActions\QuarantineActions;
use CleantalkSP\SpbctWP\Scanner\ScannerActions\ScanResultsTableActions;
use CleantalkSP\SpbctWP\Scanner\ScannerActions\FrontendPagesActions;
use CleantalkSP\SpbctWP\Scanner\ScanningLog\ScanningLogFacade;
use CleantalkSP\SpbctWP\Scanner\Services\SendFileToCloudService;
use CleantalkSP\Variables\Post;

class ScannerAjaxEndpoints
{
    /**
     * Restore file from backup AJAX action handler
     * @return void
     */
    public static function restoreFileFromBackup()
    {
        spbc_check_ajax_referer('spbc_secret_nonce', 'security');

        $file_fast_hash = isset($_POST['file_fast_hash']) ? esc_sql($_POST['file_fast_hash']) : null;

        $restore_result = BackupsActions::restoreFileFromBackup($file_fast_hash);

        if (isset($restore_result['success'])) {
            wp_send_json_success(esc_html__('Success!', 'security-malware-firewall'));
        } elseif (isset($restore_result['error'])) {
            wp_send_json_error($restore_result['error']);
        }
    }

    /**
     * Cure file AJAX action handler
     * @return void
     */
    public static function cureFile()
    {
        spbc_check_ajax_referer('spbc_secret_nonce', 'security');

        $file_fast_hash = isset($_POST['file_fast_hash']) ? esc_sql($_POST['file_fast_hash']) : null;

        $result = Cure::cureFile($file_fast_hash);

        if (is_wp_error($result)) {
            wp_send_json_error($result->get_error_message());
        }

        wp_send_json_success($result);
    }

    /**
     * Get PDF file name AJAX action handler
     * @return void
     */
    public static function getPDFReportFileName()
    {
        spbc_check_ajax_referer('spbc_secret_nonce', 'security');

        global $spbc;
        wp_send_json_success(
            'spbct-mscan-'
            . preg_replace('/^http(s)?:\/\//', '', site_url())
            . '-'
            . date('M-d-Y', $spbc->data['scanner']['last_scan'])
            . '.pdf'
        );
    }

    /**
     * Save scanner logs to pdf - AJAX action handler
     * @return void
     */
    public static function downloadPDFReport()
    {
        spbc_check_ajax_referer('spbc_secret_nonce', 'security');

        $pdf = new Pdf();

        $pdf->AliasNbPages();

        $pdf->AddPage();
        $pdf->drawScanCommonStatsTable();

        $pdf->Ln();
        $pdf->drawScanResultsOfScanType('heuristic_results');
        $pdf->drawScanResultsOfScanType('signature_results');

        $pdf->Ln();
        $pdf->drawFilesListByType('cure_log');

        $pdf->AddPage();
        $pdf->drawFilesListByType('critical_files');

        $pdf->AddPage();
        $pdf->drawFilesListByType('suspicious_files');

        $pdf->AddPage();
        $pdf->drawScanLogs();

        $pdf->Output();
    }

    /**
     * Load more scan logs on the scan results page - AJAX action handler
     */
    public static function loadMoreScanLogs()
    {
        spbc_check_ajax_referer('spbc_secret_nonce', 'security');

        $offset = Post::getInt('offset');

        $scan_logs = ScanningLogFacade::render(100, (int)$offset, true);

        wp_send_json_success($scan_logs);
    }

    /**
     * Delete file from the database - AJAX action handler
     * @param bool $direct_call
     * @param int|string $file_id
     * @return void
     */
    public static function deleteFile()
    {
        spbc_check_ajax_referer('spbc_secret_nonce', 'security');

        $time_start = microtime(true);

        $file_id = Post::getString('file_id');
        $output = FileSystemActions::deleteFile($file_id);

        $exec_time           = round(microtime(true) - $time_start);
        $output['exec_time'] = $exec_time;

        wp_send_json($output);
    }

    /**
     * Clear table from results - AJAX action handler
     *
     * @return void
     */
    public static function clearScannerResults()
    {
        spbc_check_ajax_referer('spbc_secret_nonce', 'security');

        wp_send_json(Helper::clearScannerResults());
    }

    /**
     * Approve file - AJAX action handler
     * @return void
     */
    public static function approveFile()
    {
        spbc_check_ajax_referer('spbc_secret_nonce', 'security');

        $file_id   = Post::get('file_id', 'hash');

        $time_start = microtime(true);

        $output = ScanResultsTableActions::approveFile($file_id);

        $exec_time           = round(microtime(true) - $time_start);
        $output['exec_time'] = $exec_time;

        wp_send_json($output);
    }

    /**
     * Delete file from analysis log
     */
    public static function deleteFileFromAnalysisLog($direct_call = false)
    {
        if ( ! $direct_call ) {
            spbc_check_ajax_referer('spbc_secret_nonce', 'security');
        }

        $output = ScanResultsTableActions::deleteFileFromAnalysisLog(Post::getArray('file_ids'));

        if ( ! $direct_call ) {
            wp_send_json($output);
        }

        return $output;
    }

    /**
     * Restore file from quarantine
     *
     * @param bool $direct_call
     * @param int|string $file_id
     *
     * @return void|array
     */
    public static function restoreFromQuarantine($direct_call = false, $file_id = null)
    {
        if ( ! $direct_call) {
            spbc_check_ajax_referer('spbc_secret_nonce', 'security');
        }

        $file_id = $direct_call ? $file_id : Post::get('file_id', 'hash');

        if (!$file_id) {
            $file_ids = Post::getArray('selectedIds');
            if (!$file_ids) {
                return array('error' => 'WRONG_FILE_IDS');
            }

            foreach ($file_ids as $file_id) {
                $output = QuarantineActions::restoreFromQuarantine($file_id);
                if (isset($output['error'])) {
                    $err = $output['error'];
                    if ($err === 'FILE_NOT_EXISTS') {
                        $err .= ' - '
                            . $file_id . ' - '
                            . __('File ID is invalid and will be removed from the list.', 'security-malware-firewall');
                        QuarantineActions::removeFileFromQuarantineList($file_id);
                    }
                    wp_send_json_error($err);
                }
            }

            $output = array('data' => array('success' => true, 'message' => esc_html__('Success!', 'security-malware-firewall')));
            wp_send_json($output);
        }


        $output = QuarantineActions::restoreFromQuarantine((string)$file_id);
        if (isset($output['error']) && ($output['error'] === 'FILE_NOT_FOUND' || $output['error'] === 'FILE_NOT_EXISTS')) {
            $output['error'] = $output['error'] . ' - '
                . $file_id . ' - '
                . __('File ID is invalid and will be removed from the list.', 'security-malware-firewall');
            QuarantineActions::removeFileFromQuarantineList((string)$file_id);
        }

        if ($direct_call) {
            return $output;
        } else {
            wp_send_json($output);
        }
    }

    /**
     * Quarantine file
     *
     * @param bool $direct_call
     * @param int|string $file_id
     *
     * @return void|array
     */
    public static function doQuarantineFile($direct_call = false, $file_id = null)
    {
        if ( ! $direct_call ) {
            spbc_check_ajax_referer('spbc_secret_nonce', 'security');
        }

        $file_id = $direct_call ? $file_id : Post::get('file_id', 'hash');

        $output = QuarantineActions::doQuarantineFile((string)$file_id);

        if ($direct_call) {
            return QuarantineActions::makeQuarantineResultHumanReadable($output);
        } else {
            wp_send_json($output);
        }
    }

    /**
     * Delete the quarantined copy of a file
     *
     * @param bool $direct_call
     * @param int|string $file_id
     *
     * @return void|array
     */
    public static function deleteFromQuarantine($direct_call = false, $file_id = null)
    {
        if ( ! $direct_call ) {
            spbc_check_ajax_referer('spbc_secret_nonce', 'security');
        }

        $file_id = $direct_call ? $file_id : Post::get('file_id', 'hash');

        $output = QuarantineActions::deleteFromQuarantine((string)$file_id);

        if ($direct_call) {
            return $output;
        } else {
            wp_send_json($output);
        }
    }

    /**
     * Replace file
     *
     * @param bool $direct_call
     * @param int|string $file_id
     *
     * @return void|array
     */
    public static function replaceFileWithOriginal($direct_call = false, $file_id = null)
    {
        if ( ! $direct_call) {
            spbc_check_ajax_referer('spbc_secret_nonce', 'security');
        }

        $file_id = $direct_call ? $file_id : Post::get('file_id', 'hash');

        $output = FileSystemActions::replaceFileWithOriginal((string)$file_id);

        if ($direct_call) {
            return $output;
        } else {
            wp_send_json($output);
        }
    }

    /**
     * View page
     *
     * @param bool $direct_call
     * @param string|false $page_url
     *
     * @return void
     */
    public static function viewPage()
    {
        spbc_check_ajax_referer('spbc_secret_nonce', 'security');

        $page_url = Post::get('page_url', null, 'url');
        $output = FrontendPagesActions::viewPage($page_url);

        wp_send_json($output);
    }

    /**
     * todo Remove input and return args
     * todo Extract handler to FileSystemActions
     * View file
     *
     * @param bool $direct_call
     * @param int|string $file_id
     *
     * @return void
     */
    public static function viewFile()
    {
        spbc_check_ajax_referer('spbc_secret_nonce', 'security');

        $output = FileSystemActions::viewFile(Post::get('file_id', 'hash'));

        wp_send_json($output);
    }

    /**
     * Disapprove file
     *
     * @param bool $direct_call
     * @param int|string $file_id
     *
     * @return void|array
     */
    public static function disapproveFile($direct_call = false, $file_id = null)
    {
        if (!$direct_call) {
            spbc_check_ajax_referer('spbc_secret_nonce', 'security');
        }

        $file_id = $direct_call ? $file_id : Post::get('file_id', 'hash');

        $output = ScanResultsTableActions::disapproveFile($file_id);

        if ($direct_call) {
            return $output;
        } else {
            wp_send_json($output);
        }
    }

    /**
     * todo METHODS BELOW SHOULD BE REFACTORED
     */


    /**
     * todo Remove input and return args
     * * todo Extract handler to CloudAnalysisActions
     * Checks analysis status of passed file(s)
     *
     * @param bool $direct_call Direct call flag. Show that the function was called directly from other function, not from AJAX
     * @param string|array $file_ids_input IDs of files to check the analysis status
     *
     * @return array|true[]|void
     */
    public static function checkFilesAnalysisStatus($direct_call = false, $file_ids_input = '')
    {
        global $spbc;

        // Check ajax nonce
        if ( !$direct_call ) {
            spbc_check_ajax_referer('spbc_secret_nonce', 'security');
            $file_ids_input = Post::get('file_id', 'hash') ? (string)Post::getString('file_id') : '';
        }

        $out = CloudAnalysisActions::checkFilesAnalysisStatus($file_ids_input);

        // Shift cron task
        \CleantalkSP\SpbctWP\Cron::updateTask(
            'scanner_update_pscan_files_status',
            'spbc_scanner_update_pscan_files_status',
            SPBC_PSCAN_UPDATE_FILES_STATUS_PERIOD,
            time() + SPBC_PSCAN_UPDATE_FILES_STATUS_PERIOD
        );

        // Resend queued files if available
        if ( $out['counters']['queued'] > 0 && $spbc->settings['spbc_scanner_user_can_force_pscan_update'] ) {
            spbc_scanner_resend_pscan_files();
        }

        if ($direct_call) {
            return $out;
        }

        wp_send_json_success($out);
    }

    /**
     * Send file to Cleantalk Cloud
     * @param bool $direct_call
     * @param int|string $file_id
     * @param bool $do_rescan
     * @param string $handler
     * @return array
     * @todo: check if $do_rescan is needed
     * @todo: total refactoring tests for this method
     * @todo: remove handler MOCK!
     * @todo: remove PossiblyUnusedReturnValue
     * @psalm-suppress PossiblyUnusedReturnValue
     */
    public static function sendFileForAnalysis($direct_call = false, $file_id = null, $do_rescan = true, $handler = SendFileToCloudService::class)
    {
        if ( ! $direct_call) {
            spbc_check_ajax_referer('spbc_secret_nonce', 'security');
            $file_id = preg_match('@[a-zA-Z0-9]{32}@', Post::getString('file_id')) ? Post::getString('file_id') : null;
        }

        $output = $handler::sendFile($file_id, $do_rescan);

        if ( !$direct_call ) {
            wp_send_json($output);
        }

        return $output;
    }
}
