<?php
/**
 * Media Library uploads for subscription: file-utenti / {user slug} / bonifico | certificato
 */
if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class WP_OJS_SSO_Subscription_Media {

    public const KIND_BONIFICO   = 'bonifico';
    public const KIND_CERTIFICATO = 'certificato';

    private const BASE_DIR = 'file-utenti';

    private static $max_size = 10485760; // 10 MB
    private static $allowed_mimes = [ 'application/pdf', 'image/jpeg', 'image/png' ];

	/** @var string|null */
	private static $filter_subdir = null;

	/** @var bool */
	private static $bypass_upload_cap = false;

    public static function max_size() {
        return self::$max_size;
    }

    public static function allowed_mimes() {
        return self::$allowed_mimes;
    }

	/**
	 * Public folder under wp-content/uploads: file-utenti/{slug}/bonifico|certificato
	 */
	public static function get_user_folder_slug( $user_id ) {
		$user = get_userdata( (int) $user_id );
		if ( ! $user ) {
			return 'user-' . (int) $user_id;
		}
		$slug = sanitize_file_name( $user->user_nicename );
		if ( $slug === '' ) {
			$slug = 'user-' . (int) $user_id;
		}
		return $slug;
	}

	/**
	 * Relative subdir under basedir, no leading/trailing slash issues (leading slash for subdir in WP is ok).
	 */
	public static function get_subdir( $user_id, $kind ) {
		$slug = self::get_user_folder_slug( $user_id );
		return self::BASE_DIR . '/' . $slug . '/' . $kind;
	}

	/**
	 * @param string $kind self::KIND_*
	 */
	public static function handle_upload( $user_id, $file_key, $kind ) {
		$user_id = (int) $user_id;
		if ( $user_id < 1 || ( self::KIND_BONIFICO !== $kind && self::KIND_CERTIFICATO !== $kind ) ) {
			return new WP_Error( 'invalid_args', __( 'Invalid upload request.', 'wp-ojs-sso-bridge' ) );
		}

		if ( empty( $_FILES[ $file_key ]['name'] ) ) {
			return null;
		}

		$file = $_FILES[ $file_key ];
		if ( $file['error'] !== UPLOAD_ERR_OK ) {
			return new WP_Error( 'upload_error', __( 'File upload failed.', 'wp-ojs-sso-bridge' ) );
		}
		if ( $file['size'] > self::$max_size ) {
			return new WP_Error( 'file_too_large', __( 'The file exceeds the maximum size of 10 MB.', 'wp-ojs-sso-bridge' ) );
		}
		$finfo    = finfo_open( FILEINFO_MIME_TYPE );
		$mimetype = finfo_file( $finfo, $file['tmp_name'] );
		finfo_close( $finfo );
		if ( ! in_array( $mimetype, self::$allowed_mimes, true ) ) {
			return new WP_Error( 'invalid_type', __( 'Only PDF, JPG and PNG files are allowed.', 'wp-ojs-sso-bridge' ) );
		}

		if ( ! function_exists( 'media_handle_upload' ) ) {
			require_once ABSPATH . 'wp-admin/includes/file.php';
			require_once ABSPATH . 'wp-admin/includes/image.php';
			require_once ABSPATH . 'wp-admin/includes/media.php';
		}

		$old_attachment_id = self::get_attachment_id( $user_id, $kind );
		$old_legacy_path   = ( self::KIND_CERTIFICATO === $kind ) ? self::get_legacy_path( $user_id ) : '';

		$upload_dir     = wp_upload_dir();
		$subdir         = self::get_subdir( $user_id, $kind );
		$abs_target_dir = $upload_dir['basedir'] . '/' . $subdir;
		if ( ! is_dir( $abs_target_dir ) ) {
			wp_mkdir_p( $abs_target_dir );
		}

		self::$filter_subdir = $subdir;
		add_filter( 'upload_dir', [ __CLASS__, 'filter_upload_dir' ] );

		self::$bypass_upload_cap = true;
		add_filter( 'user_has_cap', [ __CLASS__, 'filter_user_has_cap' ], 10, 4 );

		$prev = get_current_user_id();
		wp_set_current_user( $user_id );

		// Use default $overrides (test_form => false) so registration without admin POST still works.
		$attach_id = media_handle_upload( $file_key, 0 );

		wp_set_current_user( $prev );

		remove_filter( 'user_has_cap', [ __CLASS__, 'filter_user_has_cap' ], 10 );
		self::$bypass_upload_cap = false;

		remove_filter( 'upload_dir', [ __CLASS__, 'filter_upload_dir' ] );
		self::$filter_subdir = null;

		if ( is_wp_error( $attach_id ) ) {
			if ( is_array( $file ) && ! empty( $file['name'] ) ) {
				// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
				error_log( '[wp-ojs-sso-bridge] media upload failed: ' . $attach_id->get_error_message() );
			}
			return $attach_id;
		}

		wp_update_post(
			[
				'ID'          => (int) $attach_id,
				'post_author' => $user_id,
			]
		);

		if ( $old_attachment_id && (int) $old_attachment_id !== (int) $attach_id ) {
			wp_delete_attachment( (int) $old_attachment_id, true );
		} elseif ( $old_legacy_path && file_exists( $old_legacy_path ) ) {
			@unlink( $old_legacy_path );
		}

		if ( self::KIND_BONIFICO === $kind ) {
			update_user_meta( $user_id, 'ojs_bonifico_attachment_id', (string) (int) $attach_id );
		} else {
			update_user_meta( $user_id, 'ojs_student_document', (string) (int) $attach_id );
		}

		return (int) $attach_id;
	}

	public static function filter_upload_dir( $dirs ) {
		if ( ! self::$filter_subdir ) {
			return $dirs;
		}
		$subdir    = self::$filter_subdir;
		$dirs['subdir'] = '/' . ltrim( $subdir, '/' );
		$dirs['path']   = $dirs['basedir'] . $dirs['subdir'];
		$dirs['url']    = $dirs['baseurl'] . $dirs['subdir'];
		return $dirs;
	}

	public static function filter_user_has_cap( $allcaps, $caps, $args, $user ) {
		if ( ! self::$bypass_upload_cap || empty( $caps ) ) {
			return $allcaps;
		}
		if ( in_array( 'upload_files', (array) $caps, true ) || ( isset( $args[0] ) && 'upload_files' === $args[0] ) ) {
			$allcaps['upload_files'] = true;
		}
		return $allcaps;
	}

	/**
	 * @return int|string path for legacy, int attachment id, or empty
	 */
	public static function get_student_meta_value( $user_id ) {
		return get_user_meta( (int) $user_id, 'ojs_student_document', true );
	}

	/**
	 * @return int|string
	 */
	public static function get_legacy_path( $user_id ) {
		$v = self::get_student_meta_value( $user_id );
		if ( $v && is_string( $v ) && false !== strpos( $v, 'ojs-sso-bridge' ) ) {
			return $v;
		}
		if ( $v && is_string( $v ) && ! is_numeric( $v ) && ( ( false !== strpos( $v, '/' ) && file_exists( $v ) ) || ( false !== strpos( $v, '\\' ) && file_exists( $v ) ) ) ) {
			return $v;
		}
		return '';
	}

	/**
	 * @param string $kind KIND_BONIFICO|KIND_CERTIFICATO
	 */
	public static function get_attachment_id( $user_id, $kind ) {
		$user_id = (int) $user_id;
		if ( self::KIND_BONIFICO === $kind ) {
			$v = get_user_meta( $user_id, 'ojs_bonifico_attachment_id', true );
			return ( $v && (int) $v > 0 ) ? (int) $v : 0;
		}
		$v = self::get_student_meta_value( $user_id );
		if ( $v && is_numeric( $v ) && (int) $v > 0 && 'attachment' === get_post_type( (int) $v ) ) {
			return (int) $v;
		}
		return 0;
	}

	/**
	 * @param string $kind KIND_*
	 */
	public static function has_stored_file( $user_id, $kind ) {
		if ( self::KIND_BONIFICO === $kind ) {
			$id = self::get_attachment_id( $user_id, $kind );
			if ( $id > 0 && get_post( $id ) ) {
				return true;
			}
			return false;
		}
		if ( self::get_attachment_id( $user_id, $kind ) > 0 ) {
			return true;
		}
		$legacy = self::get_legacy_path( $user_id );
		return $legacy && is_readable( $legacy );
	}

	/**
	 * @param string $kind KIND_*
	 */
	public static function get_edit_link( $user_id, $kind ) {
		$id = self::get_attachment_id( $user_id, $kind );
		if ( $id < 1 ) {
			return '';
		}
		if ( current_user_can( 'edit_post', $id ) ) {
			$link = get_edit_post_link( $id, 'raw' );
			return $link ? $link : '';
		}
		$url = wp_get_attachment_url( $id );
		return $url ? $url : '';
	}

	/**
	 * @param string $kind KIND_*
	 */
	public static function get_file_label( $user_id, $kind ) {
		$id = self::get_attachment_id( $user_id, $kind );
		if ( $id > 0 ) {
			$p = get_post( $id );
			return $p ? $p->post_title : (string) $id;
		}
		if ( self::KIND_CERTIFICATO === $kind ) {
			$legacy = self::get_legacy_path( $user_id );
			if ( $legacy ) {
				return basename( $legacy );
			}
		}
		return '';
	}

	/**
	 * @param int[] $user_ids
	 */
	public static function on_delete_user( $user_id ) {
		$user_id = (int) $user_id;
		$b       = self::get_attachment_id( $user_id, self::KIND_BONIFICO );
		if ( $b > 0 ) {
			wp_delete_attachment( $b, true );
		}
		$s = self::get_attachment_id( $user_id, self::KIND_CERTIFICATO );
		if ( $s > 0 ) {
			wp_delete_attachment( $s, true );
		}
		$legacy = self::get_legacy_path( $user_id );
		if ( $legacy && is_file( $legacy ) ) {
			@unlink( $legacy );
		}
		$old_dir = WP_OJS_SSO_File_Upload::get_upload_dir( $user_id );
		if ( is_dir( $old_dir ) ) {
			$files = glob( $old_dir . '/*' );
			if ( $files ) {
				array_map( 'unlink', array_filter( $files, 'is_file' ) );
			}
			@rmdir( $old_dir );
		}
	}
}
