<?php
/**
 * Member document uploads (identity, bank receipt, payment receipt).
 *
 * @package TonItaliaRegistration
 */

defined( 'ABSPATH' ) || exit;

/**
 * Class TON_Reg_Documents
 */
class TON_Reg_Documents {

	const BASE_FOLDER = 'Documenti Iscritti';
	const TYPE_IDENTITA  = 'identita';
	const TYPE_BONIFICO  = 'bonifico';
	const TYPE_PAGAMENTO = 'pagamento';

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

	/**
	 * @return array<string, array{column:string, label:string, title:string}>
	 */
	public static function get_type_config() {
		return array(
			self::TYPE_IDENTITA  => array(
				'column' => 'doc_identita_id',
				'label'  => __( 'Documento di identità', 'ton-italia-registration' ),
				'title'  => __( 'Documento identità', 'ton-italia-registration' ),
			),
			self::TYPE_BONIFICO  => array(
				'column' => 'doc_bonifico_id',
				'label'  => __( 'Ricevuta bonifico', 'ton-italia-registration' ),
				'title'  => __( 'Ricevuta bonifico', 'ton-italia-registration' ),
			),
			self::TYPE_PAGAMENTO => array(
				'column' => 'doc_pagamento_id',
				'label'  => __( 'Ricevuta pagamento', 'ton-italia-registration' ),
				'title'  => __( 'Ricevuta pagamento', 'ton-italia-registration' ),
			),
		);
	}

	/**
	 * @return array<int, string>
	 */
	public static function get_types() {
		return array_keys( self::get_type_config() );
	}

	/**
	 * @param string $type Document type.
	 * @return array{column:string, label:string, title:string}|null
	 */
	public static function get_config( $type ) {
		$config = self::get_type_config();
		return $config[ $type ] ?? null;
	}

	/**
	 * @param string $type Document type.
	 * @return string
	 */
	public static function get_column( $type ) {
		$config = self::get_config( $type );
		return $config ? $config['column'] : '';
	}

	/**
	 * Install base media folder.
	 */
	public static function install_folders() {
		$path = self::get_base_path();
		wp_mkdir_p( $path );
		self::write_index_file( $path );
	}

	/**
	 * Remove entire documents tree from uploads.
	 */
	public static function uninstall_folders() {
		$path = self::get_base_path();
		if ( is_dir( $path ) ) {
			self::delete_directory( $path );
		}
	}

	/**
	 * @return string
	 */
	public static function get_base_path() {
		$upload = wp_upload_dir();
		return trailingslashit( $upload['basedir'] ) . self::BASE_FOLDER;
	}

	/**
	 * @return string
	 */
	public static function get_base_url() {
		$upload = wp_upload_dir();
		$folder = str_replace( ' ', '%20', self::BASE_FOLDER );
		return trailingslashit( $upload['baseurl'] ) . $folder;
	}

	/**
	 * @param object $row Registration row.
	 * @return string
	 */
	public static function member_folder_slug( $row ) {
		$cf = strtoupper( preg_replace( '/\s+/', '', (string) $row->codice_fiscale ) );
		return sanitize_title( $row->nome . '-' . $row->cognome . '-' . $cf );
	}

	/**
	 * @param object $row Registration row.
	 * @return string
	 */
	public static function get_member_path( $row ) {
		return trailingslashit( self::get_base_path() ) . self::member_folder_slug( $row );
	}

	/**
	 * @param object $row Registration row.
	 */
	public static function ensure_member_folder( $row ) {
		self::install_folders();
		$path = self::get_member_path( $row );
		wp_mkdir_p( $path );
		self::write_index_file( $path );
	}

	/**
	 * @param int    $registration_id Registration ID.
	 * @param string $type            Document type.
	 * @param array<string,mixed> $file $_FILES item.
	 * @return int|WP_Error Attachment ID.
	 */
	public static function upload( $registration_id, $type, $file ) {
		$row = TON_Reg_Database::get( $registration_id );
		if ( ! $row ) {
			return new WP_Error( 'not_found', __( 'Iscrizione non trovata.', 'ton-italia-registration' ) );
		}

		$config = self::get_config( $type );
		if ( ! $config ) {
			return new WP_Error( 'invalid_type', __( 'Tipo documento non valido.', 'ton-italia-registration' ) );
		}

		if ( empty( $file['name'] ) || ! empty( $file['error'] ) ) {
			return new WP_Error( 'no_file', __( 'Nessun file selezionato o errore nel caricamento.', 'ton-italia-registration' ) );
		}

		self::ensure_member_folder( $row );

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

		$allowed = array(
			'pdf'  => 'application/pdf',
			'jpg'  => 'image/jpeg',
			'jpeg' => 'image/jpeg',
			'png'  => 'image/png',
		);

		$check = wp_check_filetype( $file['name'], $allowed );
		if ( empty( $check['ext'] ) || empty( $check['type'] ) ) {
			return new WP_Error( 'mime', __( 'Formato non consentito. Usa PDF, JPG o PNG.', 'ton-italia-registration' ) );
		}

		self::$upload_member_slug = self::member_folder_slug( $row );
		add_filter( 'upload_dir', array( __CLASS__, 'filter_upload_dir' ) );

		$attachment_id = media_handle_sideload(
			$file,
			0,
			sprintf(
				/* translators: 1: document type, 2: full name */
				__( '%1$s — %2$s', 'ton-italia-registration' ),
				$config['title'],
				$row->nome . ' ' . $row->cognome
			)
		);

		remove_filter( 'upload_dir', array( __CLASS__, 'filter_upload_dir' ) );
		self::$upload_member_slug = null;

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

		update_post_meta( $attachment_id, '_ton_reg_registration_id', (int) $registration_id );
		update_post_meta( $attachment_id, '_ton_reg_document_type', $type );

		$column = $config['column'];
		$old_id = (int) ( $row->$column ?? 0 );
		if ( $old_id && $old_id !== $attachment_id ) {
			wp_delete_attachment( $old_id, true );
		}

		TON_Reg_Database::update(
			$registration_id,
			array( $column => $attachment_id )
		);

		return $attachment_id;
	}

	/**
	 * @param int    $registration_id Registration ID.
	 * @param string $type            Document type.
	 * @return bool|WP_Error
	 */
	public static function delete_document( $registration_id, $type ) {
		$row = TON_Reg_Database::get( $registration_id );
		if ( ! $row ) {
			return new WP_Error( 'not_found', __( 'Iscrizione non trovata.', 'ton-italia-registration' ) );
		}

		$column = self::get_column( $type );
		if ( ! $column ) {
			return new WP_Error( 'invalid_type', __( 'Tipo documento non valido.', 'ton-italia-registration' ) );
		}

		$attachment_id = (int) ( $row->$column ?? 0 );

		if ( $attachment_id ) {
			wp_delete_attachment( $attachment_id, true );
		}

		TON_Reg_Database::update( $registration_id, array( $column => null ) );

		return true;
	}

	/**
	 * Delete all documents for a registration and optionally its folder.
	 *
	 * @param int  $registration_id Registration ID.
	 * @param bool $remove_folder   Remove member folder.
	 */
	public static function delete_all_for_registration( $registration_id, $remove_folder = true ) {
		$row = TON_Reg_Database::get( $registration_id );
		if ( ! $row ) {
			return;
		}

		foreach ( self::get_types() as $type ) {
			self::delete_document( $registration_id, $type );
		}

		if ( $remove_folder ) {
			$path = self::get_member_path( $row );
			if ( is_dir( $path ) ) {
				self::delete_directory( $path );
			}
		}
	}

	/**
	 * @param array<string,mixed> $dirs Upload dirs.
	 * @return array<string,mixed>
	 */
	public static function filter_upload_dir( $dirs ) {
		if ( ! self::$upload_member_slug ) {
			return $dirs;
		}

		$subdir = '/' . self::BASE_FOLDER . '/' . self::$upload_member_slug;
		$dirs['subdir'] = $subdir;
		$dirs['path']   = $dirs['basedir'] . $subdir;
		$dirs['url']    = $dirs['baseurl'] . $subdir;

		if ( ! is_dir( $dirs['path'] ) ) {
			wp_mkdir_p( $dirs['path'] );
			self::write_index_file( $dirs['path'] );
		}

		return $dirs;
	}

	/**
	 * @param int $attachment_id Attachment ID.
	 * @return array{url:string,name:string,id:int}|null
	 */
	public static function get_file_info( $attachment_id ) {
		if ( ! $attachment_id ) {
			return null;
		}
		$url = wp_get_attachment_url( $attachment_id );
		if ( ! $url ) {
			return null;
		}
		return array(
			'id'   => (int) $attachment_id,
			'url'  => $url,
			'name' => basename( get_attached_file( $attachment_id ) ),
		);
	}

	/**
	 * @param string $type Document type key.
	 * @return string
	 */
	public static function type_label( $type ) {
		$config = self::get_config( $type );
		return $config ? $config['label'] : $type;
	}

	/**
	 * @param string $path Directory path.
	 */
	private static function write_index_file( $path ) {
		$file = trailingslashit( $path ) . 'index.php';
		if ( ! file_exists( $file ) ) {
			// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents
			file_put_contents( $file, "<?php\n// Silence is golden.\n" );
		}
	}

	/**
	 * @param string $dir Directory path.
	 */
	private static function delete_directory( $dir ) {
		if ( ! is_dir( $dir ) ) {
			return;
		}

		$items = scandir( $dir );
		if ( ! is_array( $items ) ) {
			return;
		}

		foreach ( $items as $item ) {
			if ( '.' === $item || '..' === $item ) {
				continue;
			}
			$path = $dir . DIRECTORY_SEPARATOR . $item;
			if ( is_dir( $path ) ) {
				self::delete_directory( $path );
			} else {
				wp_delete_file( $path );
			}
		}

		// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_rmdir
		rmdir( $dir );
	}
}
