<?php

class basic_user_avatars {

	/**
	 * User ID
	 *
	 * @since 1.0.0
	 * @var int
	 */
	private $user_id_being_edited;

	/**
	 * Initialize all the things
	 *
	 * @since 1.0.0
	 */
	/**
	 * Initialize all the things
	 *
	 * @since 1.0.0
	 */
	public function __construct() {
		// Actions
		add_action( 'admin_init', [ $this, 'admin_init' ] );
		add_action( 'show_user_profile', [ $this, 'edit_user_profile' ] );
		add_action( 'edit_user_profile', [ $this, 'edit_user_profile' ] );
		add_action( 'personal_options_update', [ $this, 'edit_user_profile_update' ] );
		add_action( 'edit_user_profile_update', [ $this, 'edit_user_profile_update' ] );
		add_action( 'personal_options_update', [ $this, 'edit_user_profile_update2' ] );
		add_action( 'edit_user_profile_update', [ $this, 'edit_user_profile_update2' ] );

		// Filters
		add_filter( 'get_avatar_data', [ $this, 'get_avatar_data' ], 10, 2 );
		add_filter( 'get_avatar', [ $this, 'get_avatar' ], 10, 6 );
		add_filter( 'avatar_defaults', [ $this, 'avatar_defaults' ] );
	}


	/**
	 * Start the admin engine.
	 *
	 * @since 1.0.0
	 */
	/**
	 * Start the admin engine.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	public function admin_init() {
		// Register/add the Discussion setting to restrict avatar upload capabilities
		register_setting( 'discussion', 'basic_user_avatars_caps', [ $this, 'sanitize_options' ] );
		add_settings_field( 
			'basic-user-avatars-caps', 
			esc_html__( 'Local Avatar Permissions', 'basic-user-avatars' ), 
			[ $this, 'avatar_settings_field' ], 
			'discussion', 
			'avatars' 
		);
	}

	/**
	 * Discussion settings option
	 *
	 * @since 1.0.0
	 * @param array $args Settings field arguments
	 * @return void
	 */
	public function avatar_settings_field( $args ) {
		$options = get_option( 'basic_user_avatars_caps' );
		?>
		<label for="basic_user_avatars_caps">
			<input type="checkbox" name="basic_user_avatars_caps" id="basic_user_avatars_caps" value="1" <?php checked( $options['basic_user_avatars_caps'] ?? 0, 1 ); ?>/>
			<?php esc_html_e( 'Only allow users with file upload capabilities to upload local avatars (Authors and above)', 'basic-user-avatars' ); ?>
		</label>
		<?php
	}

	/**
	 * Sanitize the Discussion settings option
	 *
	 * @since 1.0.0
	 * @param array|string $input Input value
	 * @return array
	 */
	public function sanitize_options( $input ) {
		return [
			'basic_user_avatars_caps' => empty( $input ) ? 0 : 1,
		];
	}

	/**
	 * Filter the normal avatar data and show our avatar if set.
	 *
	 * @since 1.0.6
	 * @param array $args        Arguments passed to get_avatar_data(), after processing.
	 * @param mixed $id_or_email The avatar to retrieve. Accepts a user_id, Gravatar MD5 hash,
	 *                           user email, WP_User object, WP_Post object, or WP_Comment object.
	 * @return array             The filtered avatar data.
	 */
	public function get_avatar_data( $args, $id_or_email ) {
		if ( ! empty( $args['force_default'] ) ) {
			return $args;
		}

		global $wpdb;

		$return_args = $args;

		// Determine if we received an ID or string. Then, set the $user_id variable.
		if ( is_numeric( $id_or_email ) && 0 < $id_or_email ) {
			$user_id = (int) $id_or_email;
		} elseif ( is_object( $id_or_email ) && isset( $id_or_email->user_id ) && 0 < $id_or_email->user_id ) {
			$user_id = $id_or_email->user_id;
		} elseif ( is_object( $id_or_email ) && isset( $id_or_email->ID ) && isset( $id_or_email->user_login ) && 0 < $id_or_email->ID ) {
			$user_id = $id_or_email->ID;
		} elseif ( is_string( $id_or_email ) && str_contains( $id_or_email, '@' ) ) {
			$_user = get_user_by( 'email', $id_or_email );

			if ( ! empty( $_user ) ) {
				$user_id = $_user->ID;
			}
		}

		if ( empty( $user_id ) ) {
			return $args;
		}

		// Get the user's local avatar from usermeta.
		$local_avatars = get_user_meta( $user_id, 'basic_user_avatar', true );

		if ( empty( $local_avatars ) || empty( $local_avatars['full'] ) ) {
			// Try to pull avatar from WP User Avatar.
			$wp_user_avatar_id = get_user_meta( $user_id, $wpdb->get_blog_prefix() . 'user_avatar', true );
			if ( ! empty( $wp_user_avatar_id ) ) {
				$wp_user_avatar_url = wp_get_attachment_url( (int) $wp_user_avatar_id );
				$local_avatars = [ 'full' => $wp_user_avatar_url ];
				update_user_meta( $user_id, 'basic_user_avatar', $local_avatars );
			} else {
				// We don't have a local avatar, just return.
				return $args;
			}
		}

		$size = (int) $args['size'];

		// Generate a new size
		if ( empty( $local_avatars[ $size ] ) ) {
			$upload_path      = wp_upload_dir();
			$avatar_full_path = str_replace( $upload_path['baseurl'], $upload_path['basedir'], $local_avatars['full'] );
			$image            = wp_get_image_editor( $avatar_full_path );
			$image_sized      = null;

			if ( ! is_wp_error( $image ) ) {
				$image->resize( $size, $size, true );
				$image_sized = $image->save();
			}

			// Deal with original being >= to original image (or lack of sizing ability).
			if ( empty( $image_sized ) || is_wp_error( $image_sized ) ) {
				$local_avatars[ $size ] = $local_avatars['full'];
			} else {
				$local_avatars[ $size ] = str_replace( $upload_path['basedir'], $upload_path['baseurl'], $image_sized['path'] );
			}

			// Save updated avatar sizes
			update_user_meta( $user_id, 'basic_user_avatar', $local_avatars );
		} elseif ( ! str_starts_with( $local_avatars[ $size ], 'http' ) ) {
			$local_avatars[ $size ] = home_url( $local_avatars[ $size ] );
		}

		if ( is_ssl() ) {
			$local_avatars[ $size ] = str_replace( 'http:', 'https:', $local_avatars[ $size ] );
		}

		$user_avatar_url = $local_avatars[ $size ];

		if ( $user_avatar_url ) {
			$return_args['url'] = $user_avatar_url;
			$return_args['found_avatar'] = true;
		}

		/**
		 * Allow filtering the avatar data that we are overriding.
		 *
		 * @since 1.0.6
		 *
		 * @param array $return_args The list of user avatar data arguments.
		 */
		return apply_filters( 'basic_user_avatar_data', $return_args );
	}

	/**
	 * Add a backwards compatible hook to further filter our customized avatar HTML.
	 *
	 * @since 1.0.0
	 * 
	 * @param string $avatar      HTML for the user's avatar.
	 * @param mixed  $id_or_email The avatar to retrieve. Accepts a user_id, Gravatar MD5 hash,
	 *                            user email, WP_User object, WP_Post object, or WP_Comment object.
	 * @param int    $size        Square avatar width and height in pixels to retrieve.
	 * @param string $default     URL for the default image or a default type. Accepts '404', 'retro', 'monsterid',
	 *                            'wavatar', 'indenticon', 'mystery', 'mm', 'mysteryman', 'blank', or 'gravatar_default'.
	 * @param string $alt         Alternative text to use in the avatar image tag.
	 * @param array  $args        Arguments passed to get_avatar_data(), after processing.
	 * @return string             The filtered avatar HTML.
	 */
	public function get_avatar( $avatar, $id_or_email, $size, $default, $alt, $args ) {
		/**
		 * Filter to further customize the avatar HTML.
		 * 
		 * @since 1.0.0
		 * @param string $avatar HTML for the user's avatar.
		 * @param mixed  $id_or_email The avatar to retrieve. Accepts a user_id, Gravatar MD5 hash,
	 	 *                            user email, WP_User object, WP_Post object, or WP_Comment object.
	 	 * @return string The filtered avatar HTML.
		 * @deprecated since 1.0.6
		 */
		return apply_filters( 'basic_user_avatar', $avatar, $id_or_email );
	}

	/**
	 * Form to display on the user profile edit screen
	 *
	 * @since 1.0.0
	 * @param object $profileuser
	 * @return
	 */
	public function edit_user_profile( $profileuser ) {

		// bbPress will try to auto-add this to user profiles - don't let it.
		// Instead we hook our own proper function that displays cleaner.
		if ( function_exists( 'is_bbpress' ) && is_bbpress() ) {
			return;
		}
		?>

		<div class="profile-photo-section">
			<?php if ( is_admin() ) : ?>
			<h3><?php esc_html_e( 'Profil Fotoğrafı', 'kanews' ); ?></h3>
			<?php endif; ?>

			<div class="avatar-upload-container">
				<div class="current-avatar">
					<?php echo get_avatar( $profileuser->ID, 150 ); ?>
				</div>
				
				<div class="avatar-controls">
					<?php
					$options = get_option( 'basic_user_avatars_caps' );
					if ( empty( $options['basic_user_avatars_caps'] ) || current_user_can( 'upload_files' ) ) {
						wp_nonce_field( 'basic_user_avatar_nonce', '_basic_user_avatar_nonce', false );
						?>
						<div class="upload-controls">
							<label class="custom-upload-btn kanews-btn kanews-btn-block kanews-btn-sm <?php echo is_admin() ? 'button' : ''; ?>">
								<span class="button-text"><?php esc_html_e( 'Fotoğraf Seç', 'kanews' ); ?></span>
								<input type="file" name="basic-user-avatar" id="basic-local-avatar" class="hidden-file-input" />
							</label>
							
							

							<?php if ( ! empty( $profileuser->basic_user_avatar ) ) : ?>
								<label class="remove-avatar-option">
									<input type="checkbox" name="basic-user-avatar-erase" id="basic-user-avatar-erase" value="1" />
									<?php esc_html_e( 'Avatarımı Kaldır', 'kanews' ); ?>
								</label>
							<?php endif; ?>
						</div>
						<?php
					} else {
						if ( ! empty( $profileuser->basic_user_avatar ) ) {
							echo '<p class="description error-message">' . esc_html__( 'Medya yönetimi izinleriniz yok. Yerel avatarınızı değiştirmek için site yöneticisiyle iletişime geçin.', 'kanews' ) . '</p>';
						}	
					}
					?>
				</div>
			</div>

			<div class="upload-requirements">
				<p class="description">
					<?php esc_html_e( 'Önerilen boyut: 250x250px • Maksimum boyut: 512x512px, 2MB • Desteklenen formatlar: JPG, PNG, GIF, WEBP', 'kanews' ); ?>
				</p>
			</div>
		</div>

		<style>
		.profile-photo-section {

			margin-bottom: 30px;
		}
		
		.avatar-upload-container {
			display: flex;
			align-items: flex-start;
			gap: 30px;
			margin-top: 15px;
		}
		
		.current-avatar {
			flex-shrink: 0;
		}
		
		.current-avatar img {
			border-radius: 50%;
			width: 100px;
			height: 100px;
		}
		
		.avatar-controls {
			flex-grow: 1;
		}
		
		
		.hidden-file-input {
			display: none;
		}
		
		.description {
			color: #666;
			margin-top: 10px;
			font-size: 13px;
		}
		
		.remove-avatar-option {
			display: block;
			cursor: pointer;
			margin-top: 15px;
		}
  
		.error-message {
			color: #d63638;
			background: #fcf0f1;
			padding: 10px;
			border-radius: 4px;
		}
		</style>
		<?php if ( is_admin() ) : ?>
		<h3><?php esc_html_e( 'Profil Arkaplanı', 'kanews' ); ?></h3>
		<?php endif; ?>

		<div class="cover-upload-container">
			<?php if ( ! empty( $profileuser->cover_bg['url'] ) ) : ?>
				<div class="current-cover-bg" style="background-image: url('<?php echo esc_url( $profileuser->cover_bg['url'] ); ?>');"></div>
			<?php endif; ?>
			
			<div class="cover-controls">
				<?php
				$options = get_option( 'basic_user_avatars_caps' );
				if ( empty( $options['basic_user_avatars_caps'] ) || current_user_can( 'upload_files' ) ) {
					wp_nonce_field( 'cover_bg_nonce', '_cover_bg_nonce', false );
					?>
					<div class="upload-controls">
						<label class="kanews-btn kanews-btn-block kanews-btn-sm <?php echo is_admin() ? 'button' : ''; ?>">
							<span class="button-text"><?php esc_html_e( 'Arkaplan Seç', 'kanews' ); ?></span>
							<input type="file" name="cover_bg" id="cover_bg" class="hidden-file-input" />
						</label>
						
						<div class="upload-requirements">
							<p class="description">
								<?php esc_html_e( 'Maksimum boyut: 2000x2000px, 5MB • Desteklenen formatlar: JPG, PNG, GIF, WEBP', 'kanews' ); ?>
							</p>
						</div>
						
						<?php if ( ! empty( $profileuser->cover_bg ) ) : ?>
							<label class="remove-cover-option">
								<input type="checkbox" name="cover_bg-erase" id="cover_bg-erase" value="1" />
								<?php esc_html_e( 'Arkaplanı Kaldır', 'kanews' ); ?>
							</label>
						<?php endif; ?>
					</div>
					<?php
				} else {
					if ( ! empty( $profileuser->cover_bg ) ) {
						echo '<p class="description error-message">' . esc_html__( 'Medya yönetimi izinleriniz yok. Yerel arkaplanınızı değiştirmek için site yöneticisiyle iletişime geçin.', 'kanews' ) . '</p>';
					}   
				}
				?>
			</div>
		</div>

		<style>
		.cover-upload-container {
			position: relative;
			margin-top: 15px;
			margin-bottom: 30px;
			padding: 20px;
			border-radius: 8px;
			background-color: rgba(0, 0, 0, 0.03);
			overflow: hidden;
		}

		.current-cover-bg {
			position: absolute;
			top: 0;
			left: 0;
			right: 0;
			bottom: 0;
			background-size: cover;
			background-position: center;
			opacity: 0.25;
			z-index: 0;
		}

		.cover-controls {
			position: relative;
			z-index: 1;
			margin-bottom: 15px;
		}

		.remove-cover-option {
			display: block;
			cursor: pointer;
			margin-top: 15px;
		}

		.upload-requirements {
			margin-top: 10px;
			padding: 8px 12px;
			background: rgba(0, 0, 0, 0.03);
			border-radius: 4px;
		}

		.upload-requirements .description {
			margin: 0;
			line-height: 1.5;
			font-size: 12px;
			color: #666;
		}
		</style>

		<script type="text/javascript">
		var form = document.getElementById('your-profile');
		form.encoding = 'multipart/form-data';
		form.setAttribute('enctype', 'multipart/form-data');
		</script>
		<?php
	}

	/**
	 * Update the user's avatar setting
	 *
	 * @since 1.0.0
	 * @param int $user_id User ID
	 * @return void
	 */
	public function edit_user_profile_update( $user_id ) {
		// Check for nonce otherwise bail
		if ( ! isset( $_POST['_basic_user_avatar_nonce'] ) 
			|| ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_basic_user_avatar_nonce'] ) ), 'basic_user_avatar_nonce' ) 
		) {
			return;
		}

		if ( ! empty( $_FILES['basic-user-avatar']['name'] ) ) {
			$result = $this->handle_file_upload( 
				$user_id, 
				'basic-user-avatar', 
				'basic_user_avatar',
				[ 'max_width' => 512, 'max_height' => 512 ],
				[ $this, 'unique_filename_callback' ],
				'avatar'
			);

			if ( $result && kanews_get_option( 'scoring_system' ) ) {
				$this->award_upload_score( $user_id, 'avatar', 'kan_avatar_scored' );
			}
		} elseif ( ! empty( $_POST['basic-user-avatar-erase'] ) ) {
			// Nuke the current avatar
			$this->avatar_delete( $user_id );
		}
	}
	
	/**
	 * Update the user's cover background setting
	 *
	 * @since 1.0.0
	 * @param int $user_id User ID
	 * @return void
	 */
	public function edit_user_profile_update2( $user_id ) {
		// Check for nonce otherwise bail
		if ( ! isset( $_POST['_cover_bg_nonce'] ) 
			|| ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_cover_bg_nonce'] ) ), 'cover_bg_nonce' ) 
		) {
			return;
		}

		if ( ! empty( $_FILES['cover_bg']['name'] ) ) {
			$result = $this->handle_file_upload( 
				$user_id, 
				'cover_bg', 
				'cover_bg',
				[ 'max_width' => 2000, 'max_height' => 2000 ],
				'kan_filename',
				'cover'
			);

			if ( $result && kanews_get_option( 'scoring_system' ) ) {
				$this->award_upload_score( $user_id, 'cover', 'kan_cover_scored' );
			}
		} elseif ( ! empty( $_POST['cover_bg-erase'] ) ) {
			$this->cover_delete( $user_id );
		}
	}

	/**
	 * Remove the custom get_avatar hook for the default avatar list output on 
	 * the Discussion Settings page.
	 *
	 * @since 1.0.0
	 * @param array $avatar_defaults
	 * @return array
	 */
	public function avatar_defaults( $avatar_defaults ) {
		remove_action( 'get_avatar', array( $this, 'get_avatar' ) );
		return $avatar_defaults;
	}

	/**
	 * Delete avatars based on user_id
	 *
	 * @since 1.0.0
	 * @param int $user_id
	 */
	public function avatar_delete( $user_id ) {
		$old_avatars = get_user_meta( $user_id, 'basic_user_avatar', true );
		$upload_path = wp_upload_dir();

		if ( is_array( $old_avatars ) ) {
			foreach ( $old_avatars as $old_avatar ) {
				$old_avatar_path = str_replace( $upload_path['baseurl'], $upload_path['basedir'], $old_avatar );
				@unlink( $old_avatar_path );
			}
		}

		delete_user_meta( $user_id, 'basic_user_avatar' );
	}
	
	/**
	 * Delete cover based on user_id
	 *
	 * @since 1.0.0
	 * @param int $user_id User ID
	 * @return void
	 */
	public function cover_delete( $user_id ) {
		$old_covers = get_user_meta( $user_id, 'cover_bg', true );
		$upload_path = wp_upload_dir();

		if ( is_array( $old_covers ) ) {
			foreach ( $old_covers as $old_cover ) {
				if ( is_string( $old_cover ) ) {
					$old_cover_path = str_replace( $upload_path['baseurl'], $upload_path['basedir'], $old_cover );
					@unlink( $old_cover_path );
				} elseif ( isset( $old_cover['file'] ) ) {
					@unlink( $old_cover['file'] );
				}
			}
		}

		delete_user_meta( $user_id, 'cover_bg' );
	}

	/**
	 * File names are magic
	 *
	 * @since 1.0.0
	 * @param string $dir Directory path
	 * @param string $name File name
	 * @param string $ext File extension
	 * @return string Unique filename
	 */
	public function unique_filename_callback( $dir, $name, $ext ) {
		$user = get_user_by( 'id', (int) $this->user_id_being_edited );
		if ( ! $user ) {
			return $name . $ext;
		}

		$base_name = sanitize_file_name( strtolower( $user->display_name ) . '_avatar' );
		$name = $base_name;
		$number = 1;

		while ( file_exists( $dir . '/' . $name . $ext ) ) {
			$name = $base_name . '_' . $number;
			$number++;
		}

		return $name . $ext;
	}

	/**
	 * Handle file upload with validation
	 *
	 * @param int $user_id User ID
	 * @param string $file_key File key in $_FILES
	 * @param string $meta_key Meta key to save
	 * @param array $dimensions Max dimensions ['max_width' => int, 'max_height' => int]
	 * @param callable|string $filename_callback Filename callback
	 * @param string $type Upload type ('avatar' or 'cover')
	 * @return bool|array Upload result or false on failure
	 */
	private function handle_file_upload( $user_id, $file_key, $meta_key, $dimensions, $filename_callback, $type = 'avatar' ) {
		if ( empty( $_FILES[ $file_key ]['name'] ) ) {
			return false;
		}

		// Allowed file extensions/types
		$mimes = [
			'webp'         => 'image/webp',
			'jpg|jpeg|jpe' => 'image/jpeg',
			'gif'          => 'image/gif',
			'png'          => 'image/png',
		];

		// Front end support - shortcode, bbPress, etc
		if ( ! function_exists( 'wp_handle_upload' ) ) {
			require_once ABSPATH . 'wp-admin/includes/file.php';
		}

		// Security check
		if ( str_contains( $_FILES[ $file_key ]['name'], '.php' ) ) {
			wp_die( esc_html__( 'For security reasons, the extension ".php" cannot be in your file name.', 'kanews' ) );
			return false;
		}

		// Validate image dimensions
		$image_info = @getimagesize( $_FILES[ $file_key ]['tmp_name'] );
		if ( $image_info === false ) {
			wp_die( esc_html__( 'Invalid image file.', 'kanews' ) );
			return false;
		}

		$image_width = $image_info[0];
		$image_height = $image_info[1];

		if ( $image_width > $dimensions['max_width'] || $image_height > $dimensions['max_height'] ) {
			wp_die( 
				sprintf( 
					esc_html__( 'Yüklediğiniz görselin çözünürlüğü %dx%d\'den düşük olmalıdır.', 'kanews' ),
					$dimensions['max_width'],
					$dimensions['max_height']
				)
			);
			return false;
		}

		// Validate file size (1 MB)
		if( $type === 'avatar' ) {
			$max_size = 2097152;
		} else {
			$max_size = 5242880;
		}
		if ( isset( $_FILES[ $file_key ]['size'] ) && $_FILES[ $file_key ]['size'] > $max_size ) {
			wp_die( esc_html__( 'Yüklediğiniz görselin boyutu maksimum ' . $max_size / 1024 / 1024 . ' MB olmalıdır.', 'kanews' ) );
			return false;
		}

		// Delete old files if avatar
		if ( $type === 'avatar' ) {
			$this->avatar_delete( $user_id );
		}

		// Make user_id known to unique_filename_callback function
		$this->user_id_being_edited = $user_id;

		$upload_args = [
			'mimes'                  => $mimes,
			'test_form'              => false,
			'unique_filename_callback' => $filename_callback,
		];

		$uploaded_file = wp_handle_upload( $_FILES[ $file_key ], $upload_args );

		// Handle failures
		if ( empty( $uploaded_file['file'] ) ) {
			$error_message = isset( $uploaded_file['error'] ) ? $uploaded_file['error'] : esc_html__( 'Unknown error', 'kanews' );
			wp_die( 
				'<strong>' . esc_html__( 'There was an error uploading the file:', 'kanews' ) . '</strong> ' . esc_html( $error_message )
			);
			return false;
		}

		// Save user information
		if ( $type === 'avatar' ) {
			update_user_meta( $user_id, $meta_key, [ 'full' => $uploaded_file['url'] ] );
		} else {
			update_user_meta( $user_id, $meta_key, $uploaded_file );
		}

		return $uploaded_file;
	}

	/**
	 * Award score for uploading avatar/cover
	 *
	 * @param int $user_id User ID
	 * @param string $type Score type ('avatar' or 'cover')
	 * @param string $scored_meta_key Meta key to check if already scored
	 * @return void
	 */
	private function award_upload_score( $user_id, $type, $scored_meta_key ) {
		if ( get_the_author_meta( $scored_meta_key, $user_id ) === '1' ) {
			return;
		}

		$points = get_user_meta( $user_id, 'kan_user_score', true ) ?: 0;
		$score_option = $type . '_score';
		$points += kanews_get_option( $score_option, 15 );

		update_user_meta( $user_id, 'kan_user_score', $points );
		update_user_meta( $user_id, $scored_meta_key, '1' );

		date_default_timezone_set( 'Europe/Istanbul' );
		Kanews\Members\Notifications::message( 
			$user_id, 
			[
				'points' => $type,
				'date'   => current_time( 'timestamp', 1 ),
			],
			false
		);
	}
}

$basic_user_avatars = new basic_user_avatars();