<?php

namespace MediaWiki\Extension\AbuseFilter\Consequences\Consequence;

use MediaWiki\Block\BlockUserFactory;
use MediaWiki\Extension\AbuseFilter\Consequences\Parameters;
use MediaWiki\Extension\AbuseFilter\FilterUser;
use MediaWiki\Language\MessageLocalizer;
use MediaWiki\Logging\LogPage;
use MediaWiki\Status\Status;
use Psr\Log\LoggerInterface;
use Wikimedia\IPUtils;

/**
 * Base class for consequences that block a user
 */
abstract class BlockingConsequence extends Consequence implements HookAborterConsequence {

	public function __construct(
		Parameters $params,
		protected readonly string $expiry,
		private readonly BlockUserFactory $blockUserFactory,
		protected readonly FilterUser $filterUser,
		private readonly MessageLocalizer $messageLocalizer,
		private readonly LoggerInterface $logger
	) {
		parent::__construct( $params );
	}

	/**
	 * Perform a block by the AbuseFilter system user
	 * @param string $ruleDesc
	 * @param int|string $ruleNumber
	 * @param string $target
	 * @param string $expiry
	 * @param bool $isAutoBlock
	 * @param bool $preventEditOwnUserTalk
	 * @return Status
	 */
	protected function doBlockInternal(
		string $ruleDesc,
		$ruleNumber,
		string $target,
		string $expiry,
		bool $isAutoBlock,
		bool $preventEditOwnUserTalk
	): Status {
		$reason = $this->messageLocalizer->msg(
			'abusefilter-blockreason',
			$ruleDesc,
			$ruleNumber
		)->inContentLanguage()->text();

		$blockUser = $this->blockUserFactory->newBlockUser(
			$target,
			$this->filterUser->getAuthority(),
			$expiry,
			$reason,
			[
				'isHardBlock' => false,
				'isAutoblocking' => $isAutoBlock,
				'isCreateAccountBlocked' => true,
				'isUserTalkEditBlocked' => $preventEditOwnUserTalk
			]
		);
		if (
			str_contains( $this->parameters->getAction(), 'createaccount' )
			&& IPUtils::isIPAddress( $target )
		) {
			$blockUser->setLogDeletionFlags( LogPage::SUPPRESSED_ACTION );
		}
		$status = $blockUser->placeBlockUnsafe();
		if ( !$status->isGood() ) {
			$this->logger->warning(
				'AbuseFilter block to {block_target} failed: {errors}',
				[ 'block_target' => $target, 'errors' => $status->__toString() ]
			);
		}
		return $status;
	}
}
