<?php declare( strict_types=1 );

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

use FernleafSystems\Wordpress\Plugin\Shield\DBs\Malware\Ops as MalDB;
use FernleafSystems\Wordpress\Plugin\Shield\Modules\PluginControllerConsumer;
use FernleafSystems\Wordpress\Services\Services;
use FernleafSystems\Wordpress\Services\Utilities\File\ConvertLineEndings;

class CreateLocalMalwareRecords {

	use PluginControllerConsumer;

	/**
	 * @throws \Exception
	 */
	public function run( string $pathFragment, string $malwareSignature, bool $isKnownValidFile = false ) :MalDB\Record {

		$fullPath = path_join( ABSPATH, $pathFragment );
		if ( !Services::WpFs()->isAccessibleFile( $fullPath ) ) {
			throw new \Exception( 'cannot access full file path: '.$fullPath );
		}

		$content = Services::WpFs()->getFileContent( $fullPath );
		if ( empty( $content ) ) {
			throw new \Exception( 'Cannot read file contents' );
		}
		$content = ( new ConvertLineEndings() )->dosToLinux( $content );
		$sha256 = \hash( 'sha256', $content, true );

		$dbh = self::con()->db_con->malware;
		/** @var MalDB\Select $select */
		$select = $dbh->getQuerySelector();
		/** @var ?MalDB\Record $record */
		$record = $select->filterBySHA256( $sha256 )
						 ->filterByFilePath( $pathFragment )
						 ->first();

		if ( empty( $record ) ) {
			$dbh->getQueryInserter()
				->setInsertData( [
					'hash_sha256'   => $sha256,
					'file_path'     => $pathFragment,
					'code_type'     => MalDB\Handler::CODE_TYPE_PHP,
					'sig'           => \base64_encode( $malwareSignature ),
					'is_valid_file' => $isKnownValidFile ? 100 : 0,
					'malai_status'  => MalwareStatus::STATUS_UNKNOWN,
					'file_content'  => \base64_encode( $content ),
					'last_seen_at'  => Services::Request()->ts(),
				] )
				->query();
			/** @var ?MalDB\Record $record */
			$record = $select->filterBySHA256( $sha256 )
							 ->filterByFilePath( $pathFragment )
							 ->first();
		}
		else {
			$dbh->getQueryUpdater()->updateById( $record->id, [
				'is_valid_file' => $isKnownValidFile ? 1 : 0,
				'last_seen_at'  => Services::Request()->ts(),
			] );
		}

		if ( empty( $record ) ) {
			throw new \Exception( 'Failed to create local malware record' );
		}

		return $record;
	}
}