<?php

declare( strict_types=1 );

namespace StrykeWP\Modules\Backup;

use StrykeWP\Modules\AbstractModule;

/**
 * STRYKE Backup (Google Drive Edition) Module.
 *
 * Performs full website backups (files + DB) via Google Drive API with OAuth 2.0.
 * Migrated from STRYKE_Agent (singleton + procedural) → DI-based module.
 *
 * Backward compat:
 *  - DB table:   wp_stryke_backups_log          (preserved)
 *  - Cron hook:  stryke_scheduled_backup_event  (preserved)
 *  - Option:     stryke_backup_options          (preserved)
 *
 * @package StrykeWP\Modules\Backup
 */
class BackupModule extends AbstractModule {

	private BackupSettings $backup_settings;
	private BackupAdmin    $admin;

	// -----------------------------------------------------------------------
	// ModuleInterface metadata
	// -----------------------------------------------------------------------

	public function get_id(): string {
		return 'backup';
	}

	public function get_name(): string {
		return __( 'Google Drive Backup', 'stryke-wp' );
	}

	public function get_description(): string {
		return __( 'Vollständige Website-Backups (Dateien + Datenbank) mit automatischem Upload auf Google Drive via OAuth 2.0.', 'stryke-wp' );
	}

	public function get_version(): string {
		return STRYKE_WP_VERSION;
	}

	public function get_icon(): string {
		return 'dashicons-cloud-upload';
	}

	// -----------------------------------------------------------------------
	// Boot
	// -----------------------------------------------------------------------

	/**
	 * Instantiates Backup services and registers WordPress hooks.
	 *
	 * @return void
	 */
	protected function boot_module(): void {
		$this->backup_settings = new BackupSettings();
		$this->admin           = new BackupAdmin( $this->backup_settings );

		// Backup cron callback — must be registered on every request.
		add_action( BackupSettings::CRON_HOOK, array( $this, 'do_scheduled_backup' ) );

		// Admin and cron context hooks.
		if ( is_admin() || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
			$this->admin->register_hooks();
		}

		$this->logger->info( 'BackupModule booted.' );
	}

	// -----------------------------------------------------------------------
	// Cron Callback
	// -----------------------------------------------------------------------

	/**
	 * Runs the backup via WP-Cron.
	 *
	 * @return void
	 */
	public function do_scheduled_backup(): void {
		$runner = new BackupRunner();

		if ( $runner->run() ) {
			$this->logger->info( 'Scheduled backup completed successfully.' );
		} else {
			$this->logger->info( 'Scheduled backup failed. Details in backup log table.' );
		}
	}

	// -----------------------------------------------------------------------
	// Lifecycle
	// -----------------------------------------------------------------------

	/**
	 * Runs when the module is first enabled.
	 * Creates the backup log table and schedules the first backup run.
	 *
	 * @return void
	 */
	public function on_enable(): void {
		BackupSettings::create_table();

		if ( ! wp_next_scheduled( BackupSettings::CRON_HOOK ) ) {
			$options    = BackupSettings::get_options();
			$time_parts = explode( ':', $options['schedule_time'] );
			$hour       = (int) ( $time_parts[0] ?? 3 );
			$minute     = (int) ( $time_parts[1] ?? 0 );

			$tz         = wp_timezone();
			$now        = new \DateTimeImmutable( 'now', $tz );
			$scheduled  = $now->setTime( $hour, $minute );
			if ( $scheduled <= $now ) {
				$scheduled = $scheduled->modify( '+1 day' );
			}
			$start_time = $scheduled->getTimestamp();

			$schedule = match ( $options['schedule_frequency'] ) {
				'weekly'  => 'stryke_weekly',
				'monthly' => 'stryke_monthly',
				default   => 'daily',
			};

			wp_schedule_event( $start_time, $schedule, BackupSettings::CRON_HOOK );
		}
	}

	/**
	 * Runs when the module is disabled.
	 * Clears the scheduled backup cron job.
	 *
	 * @return void
	 */
	public function on_disable(): void {
		wp_clear_scheduled_hook( BackupSettings::CRON_HOOK );
	}

	// -----------------------------------------------------------------------
	// Settings UI
	// -----------------------------------------------------------------------

	/**
	 * Renders Backup module settings inside the STRYKE WP dashboard.
	 *
	 * @return void
	 */
	public function render_settings(): void {
		if ( isset( $this->admin ) ) {
			$this->admin->render_settings();
		}
	}
}
