<?php
/**
 * Profile Picture Handler
 *
 * Manages profile picture uploads, storage, and display for ambassadors.
 *
 * @package AmbassadorHub\Accounts
 */

namespace AmbassadorHub\Accounts;

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

use function add_action;
use function rest_ensure_response;
use function current_user_can;
use function delete_user_meta;
use function get_current_user_id;
use function get_user_meta;
use function is_user_logged_in;
use function is_wp_error;
use function update_post_meta;
use function update_user_meta;
use function wp_get_attachment_image;
use function wp_get_attachment_url;
use function get_avatar;
use function esc_url;
use function wp_verify_nonce;

/**
 * Handles profile picture uploads and management.
 */
final class ProfilePicture {
	/**
	 * User meta key for storing profile picture attachment ID.
	 */
	private const META_KEY = 'ambh_profile_attachment_id';

	/**
	 * Maximum file size in bytes (2MB).
	 */
	private const MAX_FILE_SIZE = 2 * 1024 * 1024;

	/**
	 * Allowed MIME types for profile pictures.
	 */
	private const ALLOWED_TYPES = array(
		'image/jpeg',
		'image/jpg',
		'image/png',
		'image/gif',
		'image/webp',
	);

	/**
	 * Initialize profile picture hooks.
	 *
	 * @return void
	 */
	public static function init(): void {
		// wp-admin profile integration.
		add_action( 'show_user_profile', array( self::class, 'render_admin_field' ) );
		add_action( 'edit_user_profile', array( self::class, 'render_admin_field' ) );
		add_action( 'personal_options_update', array( self::class, 'save_admin_field' ) );
		add_action( 'edit_user_profile_update', array( self::class, 'save_admin_field' ) );
	}

	/**
	 * Check nonce permission for REST endpoints.
	 *
	 * @param \WP_REST_Request $request The request object.
	 *
	 * @return bool|WP_Error True if permission is granted, WP_Error otherwise.
	 */
	public static function check_nonce_permission( $request ) {

		// Get nonce from header.
		$nonce = $request->get_header( 'X-WP-Nonce' );

		if ( ! $nonce ) {
			return new \WP_Error( 'missing_nonce', 'Missing nonce', array( 'status' => 403 ) );
		}

		// Verify against the core REST nonce.
		if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
			return new \WP_Error( 'invalid_nonce', 'Invalid nonce', array( 'status' => 403 ) );
		}

		return true;
	}

	/**
	 * Handle profile picture upload (REST endpoint).
	 *
	 * @param \WP_REST_Request $request REST request object.
	 *
	 * @return \WP_REST_Response Response object.
	 */
	public static function handle_upload_rest( $request ): \WP_REST_Response|\WP_Error {

		// Nonce already verified in permission_callback

		// Verify user is logged in.
		if ( ! is_user_logged_in() ) {
			return rest_ensure_response(
				new \WP_Error( 'not_logged_in', 'You must be logged in to upload a profile picture.', array( 'status' => 403 ) )
			);
		}

		$user_id = get_current_user_id();

		// Get the uploaded file from request.
		$files = $request->get_file_params();
		if ( empty( $files['file'] ) ) {
			return rest_ensure_response(
				new \WP_Error( 'no_file', 'No file was uploaded.', array( 'status' => 400 ) )
			);
		}

		$file = $files['file'];

		// Validate file type.
		if ( ! in_array( $file['type'], self::ALLOWED_TYPES, true ) ) {
			return rest_ensure_response(
				new \WP_Error( 'invalid_type', 'Invalid file type. Only JPG, PNG, GIF, and WebP are allowed.', array( 'status' => 400 ) )
			);
		}

		// Validate file size.
		if ( $file['size'] > self::MAX_FILE_SIZE ) {
			return rest_ensure_response(
				new \WP_Error( 'file_too_large', 'File is too large. Maximum size is 2MB.', array( 'status' => 400 ) )
			);
		}

		// Validate upload error.
		if ( UPLOAD_ERR_OK !== $file['error'] ) {
			return rest_ensure_response(
				new \WP_Error( 'upload_error', 'An error occurred during upload.', array( 'status' => 400 ) )
			);
		}

		// Load WordPress media functions.
		require_once ABSPATH . 'wp-admin/includes/file.php';
		require_once ABSPATH . 'wp-admin/includes/media.php';
		require_once ABSPATH . 'wp-admin/includes/image.php';

		// Remove old profile picture if exists.
		$old_attachment_id = get_user_meta( $user_id, self::META_KEY, true );
		if ( $old_attachment_id ) {
			wp_delete_attachment( $old_attachment_id, true );
		}

		// Upload file.
		$attachment_id = media_handle_upload( 'file', 0 );

		if ( is_wp_error( $attachment_id ) ) {
			return rest_ensure_response(
				new \WP_Error( 'upload_failed', 'Failed to upload file. Please try again.', array( 'status' => 500 ) )
			);
		}

		// Stamp scope metadata (CRITICAL).
		update_post_meta( $attachment_id, '_ambh_scope_type', 'user' );
		update_post_meta( $attachment_id, '_ambh_scope_id', $user_id );

		// Store attachment ID in user meta.
		update_user_meta( $user_id, self::META_KEY, $attachment_id );

		return rest_ensure_response(
			array(
				'success'       => true,
				'message'       => 'Profile picture uploaded successfully.',
				'attachment_id' => $attachment_id,
			)
		);
	}

	/**
	 * Handle profile picture removal (REST endpoint).
	 *
	 * @param \WP_REST_Request $request REST request object.
	 *
	 * @return \WP_REST_Response Response object.
	 */
	public static function handle_remove_rest( $request ): \WP_REST_Response|\WP_Error { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found -- required by REST route callback signature.

		// Nonce already verified in permission_callback

		// Verify user is logged in.
		if ( ! is_user_logged_in() ) {
			return rest_ensure_response(
				new \WP_Error( 'not_logged_in', 'You must be logged in to remove your profile picture.', array( 'status' => 403 ) )
			);
		}

		$user_id       = get_current_user_id();
		$attachment_id = get_user_meta( $user_id, self::META_KEY, true );

		if ( $attachment_id ) {
			delete_user_meta( $user_id, self::META_KEY );
			wp_delete_attachment( $attachment_id, true );
		}

		return rest_ensure_response(
			array(
				'success' => true,
				'message' => 'Profile picture removed successfully.',
			)
		);
	}

	/**
	 * Get profile picture HTML for a user.
	 *
	 * @param int    $user_id User ID.
	 * @param string $size    Image size.
	 * @param array  $attr    Additional HTML attributes.
	 *
	 * @return string Profile picture HTML or default avatar.
	 */
	public static function get_profile_picture( int $user_id, string $size = 'thumbnail', array $attr = array() ): string {
		$attachment_id = get_user_meta( $user_id, self::META_KEY, true );

		if ( $attachment_id ) {
			$default_attr = array( 'class' => 'ambh-profile-picture' );
			$attr         = array_merge( $default_attr, $attr );
			return wp_get_attachment_image( $attachment_id, $size, false, $attr );
		}

		// Fallback to default avatar. External service call (Gravatar) — see
		// readme.txt's "External Services" section: sends the user's email
		// (hashed by WordPress core's get_avatar()) only when no custom
		// profile picture has been uploaded.
		$size_px = 'thumbnail' === $size ? 150 : 300;
		return get_avatar( $user_id, $size_px, '', '', array( 'class' => 'ambh-profile-picture ambh-profile-picture-default' ) );
	}

	/**
	 * Get profile picture URL for a user.
	 *
	 * @param int $user_id User ID.
	 *
	 * @return string|false Profile picture URL or false if not set.
	 */
	public static function get_profile_picture_url( int $user_id ) {
		$attachment_id = get_user_meta( $user_id, self::META_KEY, true );

		if ( $attachment_id ) {
			return wp_get_attachment_url( $attachment_id );
		}

		return false;
	}

	/**
	 * Check if user has a profile picture.
	 *
	 * @param int $user_id User ID.
	 *
	 * @return bool True if user has uploaded a profile picture.
	 */
	public static function has_profile_picture( int $user_id ): bool {
		return (bool) get_user_meta( $user_id, self::META_KEY, true );
	}

	/**
	 * Render profile picture field in wp-admin user profile.
	 *
	 * @param \WP_User $user User object.
	 *
	 * @return void
	 */
	public static function render_admin_field( \WP_User $user ): void {
		// Only show for ambassadors or if current user can edit this user.
		if ( ! in_array( Roles::ROLE_AMBASSADOR, $user->roles, true ) && ! current_user_can( 'edit_user', $user->ID ) ) {
			return;
		}

		?>
		<h2><?php esc_html_e( 'Profile Picture', 'ambassadorhub' ); ?></h2>
		<table class="form-table">
			<tr>
				<th><?php esc_html_e( 'Profile Picture', 'ambassadorhub' ); ?></th>
				<td>
					<div class="ambh-profile-picture-admin">
						<?php echo wp_kses_post( self::get_profile_picture( $user->ID, 'thumbnail' ) ); ?>
						<p class="description">
							<?php esc_html_e( 'Profile pictures can be uploaded from the account portal.', 'ambassadorhub' ); ?>
							<br>
							<?php esc_html_e( 'Maximum file size: 2MB. Allowed formats: JPG, PNG, GIF, WebP.', 'ambassadorhub' ); ?>
						</p>
						<?php if ( self::has_profile_picture( $user->ID ) ) : ?>
							<p>
								<a href="<?php echo esc_url( self::get_profile_picture_url( $user->ID ) ); ?>" target="_blank">
									<?php esc_html_e( 'View full size', 'ambassadorhub' ); ?>
								</a>
							</p>
						<?php endif; ?>
					</div>
				</td>
			</tr>
		</table>
		<?php
	}

	/**
	 * Save profile picture field from wp-admin user profile.
	 *
	 * Currently read-only in wp-admin - uploads must be done via frontend.
	 * This method is a placeholder for potential future admin upload functionality.
	 *
	 * @param int $user_id User ID.
	 *
	 * @return void
	 */
	public static function save_admin_field( int $user_id ): void {
		// Currently no-op - uploads via frontend only.
		// Could be extended to allow admin uploads in the future.
	}
}
