<?php

namespace CleantalkSP\SpbctWP\Scanner\ScannerActions;

use CleantalkSP\SpbctWP\Helpers\Arr;
use CleantalkSP\SpbctWP\Scanner\FileInfoExtended;

class ScanActions
{
    /**
     * Do rescan a single file with heuristic and signatures.
     * @param $file_path
     * @param $full_hash
     * @param $root_path
     * @return array[]|string[]
     * <ul>
     * <li>array('heuristic_result' => Verdict,
     * <br>'signatures_result' => Verdict,
     * <br>'merged_result' => array(
     * <br>&nbsp&nbsp&nbsp&nbsp 'status' => '',
     * <br>&nbsp&nbsp&nbsp&nbsp 'severity' => '',
     * <br>&nbsp&nbsp&nbsp&nbsp 'weak_spots' => '')) on success
     * </li>
     * <li>array('error' => 'error_text') on failure.</li>
     * </ul>
     */
    public static function rescanSingleFile($file_path, $full_hash, $root_path)
    {
        global $wpdb;

        $out = array(
            'heuristic_result' => array(),
            'signatures_result' => array(),
            'merged_result' => array(),
        );

        //Heuristic
        $heuristic_scanner = new \CleantalkSP\Common\Scanner\HeuristicAnalyser\Controller();
        $file_to_check = new FileInfoExtended(array('path' => $file_path));
        $result_heur = $heuristic_scanner->scanFile($file_to_check, $root_path);

        if ($result_heur->status === 'ERROR') {
            return array('error' => $result_heur->error_msg);
        }

        // Signature
        $signatures  = $wpdb->get_results('SELECT * FROM ' . SPBC_TBL_SCAN_SIGNATURES, ARRAY_A);
        $signatures_scanner = new \CleantalkSP\Common\Scanner\SignaturesAnalyser\Controller();
        $file_to_check = new \CleantalkSP\Common\Scanner\SignaturesAnalyser\Structures\FileInfo(
            $file_path,
            $full_hash
        );
        $result_sign = $signatures_scanner->scanFile($file_to_check, $root_path, $signatures);

        if ($result_sign->status === 'ERROR') {
            return array('error' => $result_sign->error_msg);
        }

        $out['heuristic_result'] = $result_heur;
        $out['signature_result'] = $result_sign;

        $merged_result = Arr::mergeWithSavingNumericKeysRecursive((array)$result_heur, (array)$result_sign);

        //merge weak-spots
        if ( isset($merged_result['weak_spots']) &&
             is_array($merged_result['weak_spots']) &&
             isset($merged_result['weak_spots'][0]) &&
             count($merged_result['weak_spots']) > 1 ) {
            unset($merged_result['weak_spots'][0]);
        }

        //merge status and severities
        if ($result_sign->status !== 'OK') {
            //signatures verdict is prior
            $merged_result['status'] = $result_sign->status;
            $merged_result['severity'] = $result_sign->severity;
        } elseif ($result_heur->status  !== 'OK') {
            //if no signatures found - check heuristic verict
            $merged_result['status'] = $result_heur->status;
            $merged_result['severity'] = $result_heur->severity;
        }

        $out['merged_result'] = $merged_result;

        return $out;
    }
}
