<?php

namespace AdsTxtManager;

use WP_PowerSuite\Core\AbstractModule;
use WP_PowerSuite\Core\Contracts\DataLocationsInterface;
use WP_PowerSuite\Core\RootTextFileHelper;

class Module extends AbstractModule implements DataLocationsInterface {

	private const MODULE_ID = 'ads-txt-manager';
	private const MODULE_VERSION = '1.0.0';

	public function getId(): string {
		return self::MODULE_ID;
	}

	public function getName(): string {
		return __( 'Ads.txt Manager', 'wp-powersuite' );
	}

	public function getVersion(): string {
		return self::MODULE_VERSION;
	}

	public function getDescription(): string {
		return __( 'Edit ads.txt for programmatic ads from WordPress—no file manager required.', 'wp-powersuite' );
	}

	public function getContext(): string|array {
		return [ 'admin', 'frontend' ];
	}

	protected function registerHooks(): void {
		if ( is_admin() ) {
			return;
		}

		add_action( 'template_redirect', [ $this, 'maybeServeVirtualAdsTxt' ], 0 );
	}

	/**
	 * Serve ads.txt from OptionStore when the physical file doesn't exist.
	 * When the file exists, the web server serves it directly; WordPress never sees the request.
	 */
	public function maybeServeVirtualAdsTxt(): void {
		$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
		$path        = wp_parse_url( $request_uri, PHP_URL_PATH );
		$path        = is_string( $path ) ? $path : '';

		if ( rtrim( $path, '/' ) !== '/ads.txt' ) {
			return;
		}

		$file_path = $this->getAdsTxtPath();
		if ( file_exists( $file_path ) ) {
			// Physical file exists; server would have served it. This request shouldn't reach us.
			return;
		}

		$settings = $this->moduleSettings()->all( [] );
		$content  = isset( $settings['content'] ) ? (string) $settings['content'] : '';

		header( 'Content-Type: text/plain; charset=utf-8' );
		header( 'X-Robots-Tag: noindex' );
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- text/plain ads.txt; HTML escaping would break IAB records.
		echo $content;
		exit;
	}

	/**
	 * {@inheritdoc}
	 */
	public function getDataLocations(): array {
		return [
			'option_store_keys' => [ self::MODULE_ID ],
		];
	}

	public function getAdsTxtPath(): string {
		return RootTextFileHelper::getRootFilePath( 'ads.txt' );
	}

	public function getAdsTxtContent(): string {
		$file_path = $this->getAdsTxtPath();

		if ( ! file_exists( $file_path ) ) {
			return '';
		}

		$content = file_get_contents( $file_path );
		return $content !== false ? $content : '';
	}

	public function fileExists(): bool {
		return file_exists( $this->getAdsTxtPath() );
	}

	public function isWritable(): bool {
		return RootTextFileHelper::isWritable( $this->getAdsTxtPath() );
	}

	/**
	 * Create backup of ads.txt in private storage.
	 *
	 * @return array{success: bool, message: string}
	 */
	public function createBackup(): array {
		$path = $this->getAdsTxtPath();
		if ( ! file_exists( $path ) || ! is_readable( $path ) ) {
			return [
				'success' => true,
				'message' => __( 'No file exists to backup.', 'wp-powersuite' ),
			];
		}

		$backup = RootTextFileHelper::createSecureBackup( $path, 'ads-txt' );
		if ( $backup === false ) {
			return [
				'success' => false,
				'message' => __( 'Could not create backup.', 'wp-powersuite' ),
			];
		}

		return [
			'success' => true,
			'message' => sprintf(
				/* translators: %s: backup filename */
				__( 'Backup created: %s', 'wp-powersuite' ),
				basename( (string) $backup )
			),
		];
	}

	/**
	 * Write ads.txt to disk when writable (OptionStore save handled separately).
	 *
	 * @return array{success: bool, message: string}
	 */
	public function writeAdsTxtFile( string $content ): array {
		$size_error = RootTextFileHelper::validateContentSize( $content );
		if ( $size_error !== null ) {
			return [
				'success' => false,
				'message' => $size_error,
			];
		}

		if ( ! $this->isWritable() ) {
			return [
				'success' => true,
				'message' => '',
			];
		}

		$path = $this->getAdsTxtPath();
		if ( file_exists( $path ) && is_readable( $path ) ) {
			RootTextFileHelper::createSecureBackup( $path, 'ads-txt' );
		}

		if ( ! RootTextFileHelper::atomicWrite( $path, $content ) ) {
			return [
				'success' => false,
				'message' => __( 'Settings saved, but failed to write ads.txt file. Please check file permissions.', 'wp-powersuite' ),
			];
		}

		return [
			'success' => true,
			'message' => '',
		];
	}
}
