<?php
/**
 * Media action business logic — pure functions, no AJAX / nonce / response concerns.
 *
 * @package CoffeeWP_Media_Cleanup
 */

namespace CWPM\Service;

use CWPM\Core\Db;
use CWPM\Core\Logger;
use CWPM\Core\Trash;

defined( 'ABSPATH' ) || exit;

class MediaService {

	/**
	 * Register an orphan file as a new WordPress Media Library attachment.
	 *
	 * @param string $rel_path  Path relative to the uploads basedir.
	 * @param string $uploads_base Absolute path to the uploads directory.
	 * @return array{rel_path:string,new_id:int} On success.
	 * @throws \RuntimeException On any failure — caller should catch and send JSON error.
	 */
	public static function add_to_media( $rel_path, $uploads_base ) {
		$abs_path = $uploads_base . '/' . ltrim( $rel_path, '/' );

		$real_abs  = realpath( $abs_path );
		$real_base = realpath( $uploads_base );

		if (
			false === $real_abs ||
			false === $real_base ||
			(
				0 !== strpos(
					wp_normalize_path( $real_abs ),
					trailingslashit( wp_normalize_path( $real_base ) )
				) &&
				wp_normalize_path( $real_abs ) !== wp_normalize_path( $real_base )
			)
		) {
			throw new \RuntimeException( 'Path is outside uploads directory' );
		}

		$wp_abs_path = $uploads_base . '/' . ltrim( $rel_path, '/' );

		if ( ! is_file( $wp_abs_path ) ) {
			throw new \RuntimeException( 'File not found' );
		}

		$filetype = wp_check_filetype( basename( $wp_abs_path ), null );

		if ( empty( $filetype['type'] ) ) {
			throw new \RuntimeException( 'Unsupported file type' );
		}

		$upload_dir = wp_upload_dir();
		$attachment = array(
			'guid'           => $upload_dir['baseurl'] . '/' . $rel_path,
			'post_mime_type' => $filetype['type'],
			'post_title'     => preg_replace( '/\.[^.]+$/', '', basename( $wp_abs_path ) ),
			'post_content'   => '',
			'post_status'    => 'inherit',
		);

		$new_attachment_id = wp_insert_attachment( $attachment, $wp_abs_path );

		if ( is_wp_error( $new_attachment_id ) || ! $new_attachment_id ) {
			throw new \RuntimeException( 'Failed to create attachment' );
		}

		require_once ABSPATH . 'wp-admin/includes/image.php';
		$metadata = wp_generate_attachment_metadata( $new_attachment_id, $wp_abs_path );
		wp_update_attachment_metadata( $new_attachment_id, $metadata );

		Db::update_result_action( $rel_path, 'add-to-media', 'added_to_media' );

		$meta  = wp_get_attachment_metadata( $new_attachment_id );
		$sizes = array();
		if ( is_array( $meta ) && ! empty( $meta['sizes'] ) ) {
			foreach ( $meta['sizes'] as $size_name => $size_data ) {
				$sizes[] = array(
					'name'      => $size_name,
					'label'     => ucwords( str_replace( '-', ' ', $size_name ) ),
					'status'    => 'ok',
					'width'     => isset( $size_data['width'] ) ? (int) $size_data['width'] : 0,
					'height'    => isset( $size_data['height'] ) ? (int) $size_data['height'] : 0,
					'file_size' => 0,
				);
			}
		}

		$thumb_url = wp_get_attachment_image_url( $new_attachment_id, 'thumbnail' ) ?: '';
		$edit_url  = get_edit_post_link( $new_attachment_id, 'raw' ) ?: '';

		Db::update_result_data(
			$rel_path,
			array(
				'attachment_id'      => $new_attachment_id,
				'in_media'           => 1,
				'thumb_url'          => $thumb_url,
				'edit_url'           => $edit_url,
				'sizes_json'         => wp_json_encode( $sizes ),
				'orphan_thumbs_json' => wp_json_encode( array() ),
			)
		);

		Logger::info( 'File added to Media Library: ' . $rel_path . ' (new ID #' . $new_attachment_id . ')' );

		return array(
			'rel_path' => $rel_path,
			'new_id'   => $new_attachment_id,
		);
	}

	/**
	 * Soft-delete an unused attachment: move file to trash and flip post_type to 'cwpm-trash'.
	 *
	 * @param int $attachment_id Attachment post ID.
	 * @return array{item_id:int}
	 * @throws \RuntimeException On validation or file-move failure.
	 */
	public static function delete_unused( $attachment_id ) {

		global $wpdb;

		$post = get_post( $attachment_id );

		if ( ! $post || 'attachment' !== $post->post_type ) {
			throw new \RuntimeException( 'Invalid attachment' );
		}

		$file_path = get_attached_file( $attachment_id );
		$rel_path  = get_post_meta( $attachment_id, '_wp_attached_file', true );

		if ( $file_path && file_exists( $file_path ) ) {
			$rel_dir = dirname( $rel_path );
			if ( '.' === $rel_dir ) {
				$rel_dir = '';
			}

			$moved = Trash::move_to_trash( $file_path, $rel_dir );

			if ( ! $moved ) {
				Logger::error( 'Failed to trash unused file: ' . $rel_path . ' (attachment #' . $attachment_id . ')' );
				throw new \RuntimeException( 'Failed to move file to trash' );
			}

			$meta = wp_get_attachment_metadata( $attachment_id );
			if ( is_array( $meta ) && ! empty( $meta['sizes'] ) ) {
				$file_dir = dirname( $file_path );
				foreach ( $meta['sizes'] as $size_data ) {
					if ( empty( $size_data['file'] ) ) {
						continue;
					}
					$thumb_path = $file_dir . '/' . $size_data['file'];
					if ( file_exists( $thumb_path ) ) {
						Trash::move_to_trash( $thumb_path, $rel_dir );
					}
				}
			}
		} elseif ( $rel_path ) {

			Db::insert_trash_record(
				array(
					'rel_path'      => $rel_path,
					'original_path' => $rel_path,
					'file_name'     => basename( $rel_path ),
					'file_size'     => 0,
				)
			);
		}

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery -- tier-2 soft-delete via post_type swap; no WP API equivalent that bypasses trash-bin meta.
		$wpdb->update(
			$wpdb->posts,
			array( 'post_type' => 'cwpm-trash' ),
			array( 'ID' => $attachment_id ),
			array( '%s' ),
			array( '%d' )
		);

		clean_post_cache( $attachment_id );

		Db::update_result_action( $rel_path, 'delete-unused', 'trashed' );

		Logger::info( 'Unused file trashed: ' . $rel_path . ' (attachment #' . $attachment_id . ')' );

		return array( 'item_id' => $attachment_id );
	}
}
