<?php

declare( strict_types=1 );

namespace StrykeWP\Modules\Backup;

/**
 * Handles the admin UI, OAuth flow, manual backup trigger, and download actions.
 *
 * Consolidates all admin-facing logic from STRYKE_Agent into one focused class.
 * Admin page slug: stryke-wp-backup (was: tools.php?page=stryke-backup-settings).
 *
 * @package StrykeWP\Modules\Backup
 */
class BackupAdmin {

	private BackupSettings $settings;

	public function __construct( BackupSettings $settings ) {
		$this->settings = $settings;
	}

	// -----------------------------------------------------------------------
	// Hook Registration
	// -----------------------------------------------------------------------

	/**
	 * Registers all admin hooks. Called from BackupModule::boot_module().
	 */
	public function register_hooks(): void {
		add_action( 'admin_init', array( $this->settings, 'register_settings' ) );
		add_action( 'admin_init', array( $this, 'handle_oauth_callback' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );

		// manual backup trigger (via admin-post.php).
		add_action( 'admin_action_run_now', array( $this, 'handle_manual_backup_start' ) );

		// Google OAuth start.
		add_action( 'admin_post_stryke_start_auth', array( $this, 'start_google_auth' ) );

		// File download.
		add_action( 'admin_post_stryke_download_backup', array( $this, 'handle_backup_download' ) );

		// AJAX delete.
		add_action( 'wp_ajax_stryke_delete_backup', array( $this, 'ajax_delete_backup_entry' ) );

		// NOTE: cron_schedules (stryke_weekly, stryke_monthly) are registered by
		// Core\CronManager at boot time so they are always available on every
		// request type (including non-admin cron). No filter needed here.
	}

	// -----------------------------------------------------------------------
	// Admin Scripts
	// -----------------------------------------------------------------------

	public function enqueue_scripts( string $hook ): void {
		// Only load on our backup settings page.
		if ( ! str_contains( $hook, BackupSettings::SETTINGS_PAGE ) ) {
			return;
		}

		$js_path = STRYKE_WP_DIR . 'src/Modules/Backup/assets/js/backup-admin.js';
		if ( ! file_exists( $js_path ) ) {
			return;
		}

		wp_enqueue_script(
			'stryke-backup-admin',
			STRYKE_WP_URL . 'src/Modules/Backup/assets/js/backup-admin.js',
			array( 'jquery' ),
			(string) filemtime( $js_path ),
			true
		);

		wp_localize_script(
			'stryke-backup-admin',
			'stryke_ajax',
			array(
				'ajax_url'     => admin_url( 'admin-ajax.php' ),
				'nonce'        => wp_create_nonce( 'stryke_delete_nonce' ),
				'confirm_text' => esc_html__( 'Backup wirklich löschen? Die Datei wird auf Google Drive und lokal entfernt.', 'stryke-wp' ),
			)
		);
	}

	// -----------------------------------------------------------------------
	// Manual Backup Trigger
	// -----------------------------------------------------------------------

	public function handle_manual_backup_start(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'Zugriff verweigert.', 'stryke-wp' ), 403 );
		}

		$nonce = sanitize_text_field( wp_unslash( $_GET['_nonce'] ?? '' ) );
		if ( ! wp_verify_nonce( $nonce, 'stryke_backup_action' ) ) {
			wp_die( esc_html__( 'Sicherheitsprüfung fehlgeschlagen.', 'stryke-wp' ), 403 );
		}

		$existing = wp_next_scheduled( BackupSettings::CRON_HOOK, array( 'single' => true ) );
		if ( $existing ) {
			$msg = 'pending';
		} else {
			wp_schedule_single_event( time(), BackupSettings::CRON_HOOK, array( 'single' => true ) );
			spawn_cron();
			$msg = 'started';
		}

		wp_safe_redirect(
			esc_url_raw(
				add_query_arg(
					array(
						'page'       => BackupSettings::SETTINGS_PAGE,
						'stryke_msg' => $msg,
					),
					admin_url( 'admin.php' )
				)
			)
		);
		exit;
	}

	// -----------------------------------------------------------------------
	// Google OAuth 2.0
	// -----------------------------------------------------------------------

	public function start_google_auth(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'Zugriff verweigert.', 'stryke-wp' ), 403 );
		}

		$options       = BackupSettings::get_options();
		$client_id     = $options['client_id'];
		$client_secret = $options['client_secret'];

		if ( empty( $client_id ) || empty( $client_secret ) ) {
			wp_safe_redirect(
				esc_url_raw( add_query_arg( 'stryke-error', 'missing_credentials', admin_url( 'admin.php?page=' . BackupSettings::SETTINGS_PAGE ) ) )
			);
			exit;
		}

		$redirect_uri = admin_url( 'admin.php?page=' . BackupSettings::SETTINGS_PAGE );
		$state        = wp_create_nonce( 'stryke_auth_state' );

		$auth_url = 'https://accounts.google.com/o/oauth2/v2/auth?' . http_build_query(
			array(
				'scope'                  => 'https://www.googleapis.com/auth/drive.file',
				'access_type'            => 'offline',
				'include_granted_scopes' => 'true',
				'state'                  => $state,
				'redirect_uri'           => $redirect_uri,
				'response_type'          => 'code',
				'client_id'              => $client_id,
			)
		);

		// External redirect to Google OAuth — domain is hardcoded, not user-controllable.
		wp_redirect( esc_url_raw( $auth_url ) ); // phpcs:ignore WordPress.Security.SafeRedirect
		exit;
	}

	/**
	 * Processes the OAuth callback from Google (runs on admin_init).
	 */
	public function handle_oauth_callback(): void {
		$page = sanitize_key( wp_unslash( $_GET['page'] ?? '' ) );
		if ( BackupSettings::SETTINGS_PAGE !== $page ) {
			return;
		}

		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		if ( isset( $_GET['error'] ) ) {
			add_settings_error(
				'stryke-backup',
				'auth_failed',
				esc_html( esc_html__( 'Autorisierung fehlgeschlagen: ', 'stryke-wp' ) . sanitize_text_field( wp_unslash( $_GET['error'] ) ) ),
				'error'
			);
			return;
		}

		if ( isset( $_GET['code'], $_GET['state'] ) ) {
			$state = sanitize_text_field( wp_unslash( $_GET['state'] ) );
			if ( ! wp_verify_nonce( $state, 'stryke_auth_state' ) ) {
				add_settings_error( 'stryke-backup', 'auth_nonce_fail', esc_html__( 'Sicherheitsprüfung fehlgeschlagen.', 'stryke-wp' ), 'error' );
				return;
			}

			$code = sanitize_text_field( wp_unslash( $_GET['code'] ) );
			$this->exchange_code_for_tokens( $code );

			wp_safe_redirect( admin_url( 'admin.php?page=' . BackupSettings::SETTINGS_PAGE ) );
			exit;
		}
	}

	private function exchange_code_for_tokens( string $code ): void {
		$options      = BackupSettings::get_options();
		$redirect_uri = admin_url( 'admin.php?page=' . BackupSettings::SETTINGS_PAGE );

		$response = wp_remote_post(
			'https://oauth2.googleapis.com/token',
			array(
				'body' => array(
					'code'          => $code,
					'client_id'     => $options['client_id'],
					'client_secret' => $options['client_secret'],
					'redirect_uri'  => $redirect_uri,
					'grant_type'    => 'authorization_code',
				),
			)
		);

		if ( is_wp_error( $response ) ) {
			add_settings_error( 'stryke-backup', 'token_error', esc_html__( 'Fehler beim Token-Abruf: ', 'stryke-wp' ) . $response->get_error_message(), 'error' );
			return;
		}

		$data = json_decode( wp_remote_retrieve_body( $response ), true );

		if ( isset( $data['refresh_token'] ) ) {
			$options['refresh_token'] = BackupSettings::encrypt( $data['refresh_token'] );
			update_option( BackupSettings::OPTION_GROUP, $options );
			add_settings_error( 'stryke-backup', 'auth_success', esc_html__( 'Erfolgreich mit Google Drive verbunden!', 'stryke-wp' ), 'updated' );
		} else {
			add_settings_error( 'stryke-backup', 'token_fail', esc_html__( 'Autorisierung fehlgeschlagen. Kein Refresh Token erhalten.', 'stryke-wp' ), 'error' );
			error_log( 'STRYKE TOKEN ERROR: Token-Austausch fehlgeschlagen. Keys: ' . implode( ', ', array_keys( $data ?? array() ) ) );
		}
	}

	// -----------------------------------------------------------------------
	// Backup Download
	// -----------------------------------------------------------------------

	public function handle_backup_download(): void {
		global $wpdb;

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'Zugriff verweigert.', 'stryke-wp' ), 403 );
		}

		if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'stryke_download_backup' ) ) {
			wp_die( esc_html__( 'Sicherheitsüberprüfung fehlgeschlagen.', 'stryke-wp' ), 403 );
		}

		$log_id = isset( $_GET['id'] ) ? (int) $_GET['id'] : 0;
		if ( $log_id <= 0 ) {
			wp_die( esc_html__( 'Ungültige Backup-ID.', 'stryke-wp' ) );
		}

		$table = BackupSettings::get_table_name();
		$entry = $wpdb->get_row( // phpcs:ignore WordPress.DB.DirectDatabaseQuery
			$wpdb->prepare( "SELECT filename, google_drive_file_id FROM {$table} WHERE ID = %d", $log_id ), // phpcs:ignore WordPress.DB.PreparedSQL
			ARRAY_A
		);

		if ( ! $entry || empty( $entry['google_drive_file_id'] ) ) {
			wp_die( esc_html__( 'Backup-Datei nicht gefunden.', 'stryke-wp' ) );
		}

		$api = new GoogleDriveClient();
		if ( ! $api->download_file( $entry['google_drive_file_id'], $entry['filename'] ) ) {
			wp_die( esc_html__( 'Fehler beim Download von Google Drive.', 'stryke-wp' ) );
		}
	}

	// -----------------------------------------------------------------------
	// AJAX — Delete Backup
	// -----------------------------------------------------------------------

	public function ajax_delete_backup_entry(): void {
		global $wpdb;

		if ( ! check_ajax_referer( 'stryke_delete_nonce', 'security', false ) || ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Sicherheitsprüfung fehlgeschlagen.', 'stryke-wp' ) ) );
			return;
		}

		$log_id = isset( $_POST['id'] ) ? (int) $_POST['id'] : 0;
		if ( $log_id <= 0 ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Ungültige Log-ID.', 'stryke-wp' ) ) );
			return;
		}

		$table = BackupSettings::get_table_name();
		$entry = $wpdb->get_row( // phpcs:ignore WordPress.DB.DirectDatabaseQuery
			$wpdb->prepare( "SELECT * FROM {$table} WHERE ID = %d", $log_id ), // phpcs:ignore WordPress.DB.PreparedSQL
			ARRAY_A
		);

		if ( ! $entry ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Log-Eintrag nicht gefunden.', 'stryke-wp' ) ) );
			return;
		}

		// Delete from Google Drive.
		$gdrive_id = $entry['google_drive_file_id'];
		if ( ! empty( $gdrive_id ) ) {
			$api = new GoogleDriveClient();
			if ( ! $api->delete_file( $gdrive_id ) ) {
				error_log( 'STRYKE Delete Error: GDrive-Datei konnte nicht gelöscht werden: ' . $gdrive_id );
			}
		}

		// Delete local temp file if present.
		$local_path = wp_upload_dir()['basedir'] . '/stryke-temp-backup/' . $entry['filename'];
		if ( file_exists( $local_path ) ) {
			@unlink( $local_path ); // phpcs:ignore WordPress.PHP.NoSilencedErrors
		}

		// Delete log entry.
		$wpdb->delete( $table, array( 'ID' => $log_id ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery

		wp_send_json_success(
			array(
				'message' => esc_html__( 'Backup erfolgreich gelöscht.', 'stryke-wp' ),
				'id'      => $log_id,
			)
		);
	}

	// -----------------------------------------------------------------------
	// Settings Page Rendering
	// -----------------------------------------------------------------------

	/**
	 * Renders the complete Backup settings UI.
	 * Called by BackupModule::render_settings().
	 */
	public function render_settings(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		$options      = BackupSettings::get_options();
		$is_connected = ! empty( $options['refresh_token'] );
		$nonce        = wp_create_nonce( 'stryke_backup_action' );
		$msg          = sanitize_key( wp_unslash( $_GET['stryke_msg'] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification
		$error        = sanitize_key( wp_unslash( $_GET['stryke-error'] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification

		if ( 'missing_credentials' === $error ) : ?>
			<div class="stryke-notice stryke-notice--warning">
				<span class="dashicons dashicons-warning" aria-hidden="true"></span>
				<?php esc_html_e( 'Client ID und Client Secret müssen zuerst gespeichert werden, bevor die Autorisierung gestartet werden kann.', 'stryke-wp' ); ?>
			</div>
		<?php endif;

		if ( 'started' === $msg ) : ?>
			<div class="stryke-notice stryke-notice--success">
				<span class="dashicons dashicons-yes-alt" aria-hidden="true"></span>
				<?php esc_html_e( 'Manuelles Backup gestartet. Überprüfen Sie den Log in Kürze.', 'stryke-wp' ); ?>
			</div>
		<?php elseif ( 'pending' === $msg ) : ?>
			<div class="stryke-notice stryke-notice--warning">
				<span class="dashicons dashicons-warning" aria-hidden="true"></span>
				<?php esc_html_e( 'Ein manuelles Backup ist bereits geplant oder läuft.', 'stryke-wp' ); ?>
			</div>
		<?php endif;

		settings_errors( 'stryke-backup' );
		?>

		<!-- === Google Drive Config === -->
		<div class="stryke-card">
			<h2><?php esc_html_e( '1. Google Drive Konfiguration', 'stryke-wp' ); ?></h2>

			<form method="post" action="options.php">
				<?php
				settings_fields( BackupSettings::get_settings_group() );
				do_settings_sections( BackupSettings::SETTINGS_PAGE );
				?>

				<table class="form-table" role="presentation">
					<tr>
						<th scope="row"><?php esc_html_e( 'Autorisierung', 'stryke-wp' ); ?></th>
						<td>
							<?php if ( $is_connected ) : ?>
								<div class="stryke-notice stryke-notice--success">
									<span class="dashicons dashicons-yes-alt" aria-hidden="true"></span>
									<?php esc_html_e( 'Verbunden mit Google Drive.', 'stryke-wp' ); ?>
								</div>
								<p class="stryke-text-muted"><?php esc_html_e( 'Der Refresh Token ist sicher gespeichert. Backups können hochgeladen werden.', 'stryke-wp' ); ?></p>
							<?php else : ?>
								<div class="stryke-notice stryke-notice--warning">
									<span class="dashicons dashicons-warning" aria-hidden="true"></span>
									<?php esc_html_e( 'Warten auf Autorisierung.', 'stryke-wp' ); ?>
								</div>
								<?php if ( ! empty( $options['client_id'] ) && ! empty( $options['client_secret'] ) ) : ?>
									<p class="stryke-text-muted"><?php esc_html_e( 'Klicken Sie auf den Button, um die App bei Google zu autorisieren.', 'stryke-wp' ); ?></p>
									<a href="<?php echo esc_url( admin_url( 'admin-post.php?action=stryke_start_auth' ) ); ?>" class="stryke-btn stryke-btn--primary">
										<?php esc_html_e( 'Mit Google Drive verbinden', 'stryke-wp' ); ?>
									</a>
								<?php else : ?>
									<p class="stryke-text-muted"><?php esc_html_e( 'Bitte geben Sie zuerst Client ID und Client Secret ein und speichern Sie.', 'stryke-wp' ); ?></p>
								<?php endif; ?>
							<?php endif; ?>
						</td>
					</tr>
				</table>

				<div class="stryke-form-actions">
					<button type="submit" class="stryke-btn stryke-btn--primary">
						<span class="dashicons dashicons-saved" aria-hidden="true"></span>
						<?php esc_html_e( 'Einstellungen speichern', 'stryke-wp' ); ?>
					</button>
				</div>
			</form>
		</div>

		<!-- === Backup Schedule === -->
		<div class="stryke-card" style="margin-top: 16px;">
			<h2><?php esc_html_e( '2. Backup-Zeitplan', 'stryke-wp' ); ?></h2>

			<?php
			$next_run = wp_next_scheduled( BackupSettings::CRON_HOOK );
			if ( $next_run ) :
				?>
				<div class="stryke-notice stryke-notice--info">
					<?php
					printf(
						/* translators: %s: date and time */
						esc_html__( 'Nächster geplanter Lauf: %s', 'stryke-wp' ),
						esc_html( date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $next_run ) )
					);
					?>
				</div>
			<?php else : ?>
				<div class="stryke-notice stryke-notice--warning">
					<span class="dashicons dashicons-warning" aria-hidden="true"></span>
					<?php esc_html_e( 'Kein Backup-Plan aktiv. Einstellungen speichern, um den Zeitplan zu aktivieren.', 'stryke-wp' ); ?>
				</div>
			<?php endif; ?>

			<div class="stryke-field-row" style="margin-top: 12px;">
				<a href="<?php echo esc_url( admin_url( 'admin.php?page=' . BackupSettings::SETTINGS_PAGE . '&action=run_now&_nonce=' . $nonce ) ); ?>"
				   class="stryke-btn stryke-btn--primary">
					<span class="dashicons dashicons-controls-play" aria-hidden="true"></span>
					<?php esc_html_e( 'Backup jetzt starten', 'stryke-wp' ); ?>
				</a>
			</div>
		</div>

		<!-- === Backup Log === -->
		<div class="stryke-card" style="margin-top: 16px;">
			<h2><?php esc_html_e( '3. Backup-Historie', 'stryke-wp' ); ?></h2>

			<?php
			if ( ! class_exists( \WP_List_Table::class ) ) {
				require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
			}

			$table = new LogListTable();
			$table->prepare_items();
			?>
			<form id="stryke-backup-log-form" method="get">
				<input type="hidden" name="page" value="<?php echo esc_attr( BackupSettings::SETTINGS_PAGE ); ?>" />
				<?php $table->display(); ?>
			</form>
		</div>
		<?php
	}
}
