<?php
/**
 * Password admin — AJAX handlers for password CRUD, bulk gen, export/import.
 *
 * @package PrivexPasswordProtect
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class PPMSTR_Password_Admin
 */
class PPMSTR_Password_Admin {

	/**
	 * Register hooks.
	 */
	public function init() {
		add_action( 'wp_ajax_ppmstr_add_password', array( $this, 'ajax_add_password' ) );
		add_action( 'wp_ajax_ppmstr_delete_password', array( $this, 'ajax_delete_password' ) );
		add_action( 'wp_ajax_ppmstr_bulk_generate', array( $this, 'ajax_bulk_generate' ) );
		add_action( 'wp_ajax_ppmstr_export_csv', array( $this, 'ajax_export_csv' ) );
		add_action( 'wp_ajax_ppmstr_import_csv', array( $this, 'ajax_import_csv' ) );
	}

	/**
	 * Get all passwords across the site.
	 *
	 * @return array Array of password entries with post info.
	 */
	public static function get_all_passwords() {
		global $wpdb;

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$rows = $wpdb->get_results(
			$wpdb->prepare(
				"SELECT post_id, meta_value FROM {$wpdb->postmeta} WHERE meta_key = %s",
				'_ppmstr_passwords'
			)
		);

		$all = array();
		foreach ( $rows as $row ) {
			$passwords = maybe_unserialize( $row->meta_value );
			if ( ! is_array( $passwords ) ) {
				continue;
			}
			$post_title = get_the_title( $row->post_id );
			foreach ( $passwords as $entry ) {
				$entry['post_id']    = (int) $row->post_id;
				$entry['post_title'] = $post_title;
				$all[]               = $entry;
			}
		}

		// Sort by created date, newest first.
		usort( $all, function ( $a, $b ) {
			return ( $b['created'] ?? 0 ) - ( $a['created'] ?? 0 );
		} );

		return $all;
	}

	/**
	 * AJAX: Add a password to a post.
	 */
	public function ajax_add_password() {
		check_ajax_referer( 'ppmstr_admin_nonce', 'nonce' );

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( __( 'Permission denied.', 'privex-password-protect' ) );
		}

		$post_id  = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;
		$password = isset( $_POST['password'] ) ? sanitize_text_field( wp_unslash( $_POST['password'] ) ) : '';
		$label    = isset( $_POST['label'] ) ? sanitize_text_field( wp_unslash( $_POST['label'] ) ) : '';
		$expires  = isset( $_POST['expires_at'] ) ? sanitize_text_field( wp_unslash( $_POST['expires_at'] ) ) : '';
		$max_uses = isset( $_POST['max_uses'] ) ? absint( $_POST['max_uses'] ) : 0;

		if ( ! $post_id || ! $password ) {
			wp_send_json_error( __( 'Post ID and password are required.', 'privex-password-protect' ) );
		}

		$is_pro = function_exists( 'ppp_fs' ) && ppp_fs()->can_use_premium_code__premium_only();
		if ( ! $is_pro ) {
			$all_passwords = self::get_all_passwords();
			if ( count( $all_passwords ) >= 5 ) {
				$upgrade_url = function_exists( 'ppp_fs' ) ? ppp_fs()->get_upgrade_url() : '#';
				$msg         = sprintf(
					/* translators: %s: Upgrade URL */
					__( 'Free version limit reached (5 passwords). <a href="%s" target="_blank" style="color:#A855F7;text-decoration:underline;">Upgrade to PRO</a> for unlimited passwords.', 'privex-password-protect' ),
					esc_url( $upgrade_url )
				);
				wp_send_json_error( $msg );
			}
		}

		$expires_ts = 0;
		if ( ! empty( $expires ) ) {
			$expires_ts = strtotime( $expires );
			if ( false === $expires_ts ) {
				$expires_ts = 0;
			}
		}

		$entry     = PPMSTR_Password_Validator::create_entry( $password, $label, $expires_ts, $max_uses );
		$passwords = get_post_meta( $post_id, '_ppmstr_passwords', true );
		if ( ! is_array( $passwords ) ) {
			$passwords = array();
		}
		$passwords[] = $entry;
		update_post_meta( $post_id, '_ppmstr_passwords', $passwords );

		// Auto-enable protection.
		update_post_meta( $post_id, '_ppmstr_protected', '1' );
		
		// Attempt to clear caches so the new form type renders instead of a cached old form (like category/site).
		if ( function_exists( 'wp_cache_flush' ) ) {
			wp_cache_flush();
		}
		if ( function_exists( 'w3tc_flush_all' ) ) {
			w3tc_flush_all();
		}
		if ( function_exists( 'wpfc_clear_all_cache' ) ) {
			wpfc_clear_all_cache();
		}

		wp_send_json_success( array(
			'message' => __( 'Password added successfully.', 'privex-password-protect' ),
			'entry'   => array(
				'id'      => $entry['id'],
				'label'   => $entry['label'],
				'created' => gmdate( 'Y-m-d H:i', $entry['created'] ),
				'status'  => $entry['status'],
			),
		) );
	}

	/**
	 * AJAX: Delete a password from a post.
	 */
	public function ajax_delete_password() {
		check_ajax_referer( 'ppmstr_admin_nonce', 'nonce' );

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( __( 'Permission denied.', 'privex-password-protect' ) );
		}

		$post_id     = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;
		$password_id = isset( $_POST['password_id'] ) ? sanitize_key( $_POST['password_id'] ) : '';

		if ( ! $post_id || ! $password_id ) {
			wp_send_json_error( __( 'Missing parameters.', 'privex-password-protect' ) );
		}

		$passwords = get_post_meta( $post_id, '_ppmstr_passwords', true );
		if ( ! is_array( $passwords ) ) {
			wp_send_json_error( __( 'No passwords found.', 'privex-password-protect' ) );
		}

		$passwords = array_filter( $passwords, function ( $e ) use ( $password_id ) {
			return ( $e['id'] ?? '' ) !== $password_id;
		} );

		update_post_meta( $post_id, '_ppmstr_passwords', array_values( $passwords ) );

		wp_send_json_success( __( 'Password deleted.', 'privex-password-protect' ) );
	}

	/**
	 * AJAX: Bulk generate passwords for a post.
	 */
	public function ajax_bulk_generate() {
		check_ajax_referer( 'ppmstr_admin_nonce', 'nonce' );

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( __( 'Permission denied.', 'privex-password-protect' ) );
		}

		$post_id  = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;
		$count    = isset( $_POST['count'] ) ? min( absint( $_POST['count'] ), 100 ) : 5;
		$length   = isset( $_POST['length'] ) ? max( absint( $_POST['length'] ), 6 ) : 12;
		$max_uses = isset( $_POST['max_uses'] ) ? absint( $_POST['max_uses'] ) : 0;
		$expires  = isset( $_POST['expires_at'] ) ? sanitize_text_field( wp_unslash( $_POST['expires_at'] ) ) : '';

		if ( ! $post_id ) {
			wp_send_json_error( __( 'Post ID is required.', 'privex-password-protect' ) );
		}

		$expires_ts = 0;
		if ( ! empty( $expires ) ) {
			$expires_ts = strtotime( $expires );
			if ( false === $expires_ts ) {
				$expires_ts = 0;
			}
		}

		$passwords  = get_post_meta( $post_id, '_ppmstr_passwords', true );
		if ( ! is_array( $passwords ) ) {
			$passwords = array();
		}

		$generated = array();
		for ( $i = 0; $i < $count; $i++ ) {
			$plain       = PPMSTR_Password_Validator::generate_random( $length );
			$entry       = PPMSTR_Password_Validator::create_entry( $plain, 'Bulk #' . ( $i + 1 ), $expires_ts, $max_uses );
			$passwords[] = $entry;
			$generated[] = array(
				'password' => $plain,
				'id'       => $entry['id'],
				'label'    => $entry['label'],
			);
		}

		update_post_meta( $post_id, '_ppmstr_passwords', $passwords );
		update_post_meta( $post_id, '_ppmstr_protected', '1' );

		wp_send_json_success( array(
			'message'   => sprintf(
				/* translators: %d: number of passwords generated */
				__( '%d passwords generated.', 'privex-password-protect' ),
				$count
			),
			'passwords' => $generated,
		) );
	}

	/**
	 * AJAX: Export all passwords as CSV.
	 */
	public function ajax_export_csv() {
		check_ajax_referer( 'ppmstr_admin_nonce', 'nonce' );

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( __( 'Permission denied.', 'privex-password-protect' ) );
		}

		$all  = self::get_all_passwords();
		$rows = array();
		$rows[] = array( 'Post ID', 'Post Title', 'Label', 'Status', 'Uses', 'Max Uses', 'Created', 'Expires' );

		foreach ( $all as $entry ) {
			$rows[] = array(
				$entry['post_id'],
				$entry['post_title'],
				$entry['label'] ?? '',
				$entry['status'] ?? 'active',
				$entry['use_count'] ?? 0,
				$entry['max_uses'] ?? 0,
				! empty( $entry['created'] ) ? gmdate( 'Y-m-d H:i', $entry['created'] ) : '',
				! empty( $entry['expires_at'] ) ? gmdate( 'Y-m-d H:i', $entry['expires_at'] ) : 'Never',
			);
		}

		wp_send_json_success( array( 'csv' => $rows ) );
	}

	/**
	 * AJAX: Import passwords from CSV data.
	 */
	public function ajax_import_csv() {
		check_ajax_referer( 'ppmstr_admin_nonce', 'nonce' );

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( __( 'Permission denied.', 'privex-password-protect' ) );
		}

		$csv_data = isset( $_POST['csv_data'] ) ? sanitize_textarea_field( wp_unslash( $_POST['csv_data'] ) ) : '';
		if ( empty( $csv_data ) ) {
			wp_send_json_error( __( 'No CSV data provided.', 'privex-password-protect' ) );
		}

		$lines   = explode( "\n", trim( $csv_data ) );
		$imported = 0;

		// Skip header row.
		array_shift( $lines );

		foreach ( $lines as $line ) {
			$cols = str_getcsv( trim( $line ) );
			if ( count( $cols ) < 3 ) {
				continue;
			}

			$post_id  = absint( $cols[0] );
			$password = sanitize_text_field( $cols[1] );
			$label    = isset( $cols[2] ) ? sanitize_text_field( $cols[2] ) : '';
			$max_uses = isset( $cols[3] ) ? absint( $cols[3] ) : 0;

			if ( ! $post_id || ! $password || ! get_post( $post_id ) ) {
				continue;
			}

			$entry     = PPMSTR_Password_Validator::create_entry( $password, $label, 0, $max_uses );
			$passwords = get_post_meta( $post_id, '_ppmstr_passwords', true );
			if ( ! is_array( $passwords ) ) {
				$passwords = array();
			}
			$passwords[] = $entry;
			update_post_meta( $post_id, '_ppmstr_passwords', $passwords );
			update_post_meta( $post_id, '_ppmstr_protected', '1' );
			$imported++;
		}

		wp_send_json_success( sprintf(
			/* translators: %d: number of passwords imported */
			__( '%d passwords imported.', 'privex-password-protect' ),
			$imported
		) );
	}
}
