<?php declare( strict_types=1 );

namespace FernleafSystems\Wordpress\Plugin\Shield\Scans\Afs\Utilities;

use FernleafSystems\Wordpress\Plugin\Shield\Modules\PluginControllerConsumer;
use FernleafSystems\Wordpress\Services\Services;
use FernleafSystems\Wordpress\Services\Utilities\File\Cache;
use FernleafSystems\Wordpress\Services\Utilities\Integrations\WpHashes\Malai\MalwarePatterns;

class MalwareScanPatterns {

	use PluginControllerConsumer;

	/**
	 * @return array{raw: string[], iraw: string[], re: string[], functions: string[], keywords: string[]}
	 */
	public function retrieve() :array {
		$con = self::con();
		$cacher = new Cache\CacheDefVO();
		$cacher->dir = $con->cache_dir_handler->buildSubDir( 'scans' );
		if ( !empty( $cacher->dir ) ) {
			$cacher->file_fragment = 'malcache_patterns_v2.txt';
			$cacher->expiration = \DAY_IN_SECONDS;
			( new Cache\LoadFromCache() )
				->setCacheDef( $cacher )
				->load();
		}

		if ( empty( $cacher->data ) ) {
			$token = $con->comps->api_token->getToken();
			// First attempt to download from WP Hashes API.
			$patterns = ( new MalwarePatterns( $token ) )->retrieve();

			// Fallback to original method
			if ( empty( $patterns[ 'raw' ] ) || empty( $patterns[ 're' ] ) ) {
				$patterns = [
					'raw'       => $this->getMalSignaturesSimple(),
					're'        => $this->getMalSignaturesRegex(),
					'iraw'      => [],
					'functions' => [],
					'keywords'  => [],
				];
			}

			$cacher->data = $patterns;
			if ( !empty( $cacher->dir ) ) {
				( new Cache\StoreToCache() )
					->setCacheDef( $cacher )
					->store();
			}
		}

		return \is_array( $cacher->data ) ? $cacher->data : [];
	}

	/**
	 * @return string[]
	 */
	public function getMalSignaturesSimple() :array {
		return $this->getMalSignatures( 'malsigs_simple.txt', self::con()->cfg->configuration->def( 'url_mal_sigs_simple' ) );
	}

	/**
	 * @return string[]
	 */
	public function getMalSignaturesRegex() :array {
		return $this->getMalSignatures( 'malsigs_regex.txt', self::con()->cfg->configuration->def( 'url_mal_sigs_regex' ) );
	}

	/**
	 * @return string[]
	 */
	private function getMalSignatures( string $fileName, string $url ) :array {
		$FS = Services::WpFs();
		$file = self::con()->cache_dir_handler->cacheItemPath( $fileName );
		if ( !empty( $file ) && $FS->exists( $file ) ) {
			$sigs = \explode( "\n", $FS->getFileContent( $file, true ) );
		}
		else {
			$sigs = \array_filter(
				\array_map( '\trim',
					\explode( "\n", Services::HttpRequest()->getContent( $url ) )
				),
				function ( $line ) {
					return ( \strpos( $line, '#' ) !== 0 ) && \strlen( $line ) > 0;
				}
			);

			if ( !empty( $file ) && !empty( $sigs ) ) {
				$FS->putFileContent( $file, \implode( "\n", $sigs ), true );
			}
		}

		return \is_array( $sigs ) ? $sigs : [];
	}
}