<?php

/**
 * MediaHandler — Domain handler for media library read/write actions.
 *
 * Owns: get_media, upload_media, delete_media
 *
 * @package LolaCore\Actions\Handlers
 * @license GPL-2.0-or-later
 */

declare( strict_types=1 );

namespace LolaCore\Actions\Handlers;

use LolaCore\Actions\Contracts\ActionHandlerInterface;

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

/**
 * Handles get_media, upload_media, and delete_media actions.
 */
class MediaHandler implements ActionHandlerInterface {

	private const MAX_BULK = 50;

	/** @inheritDoc */
	public function getSupportedActions(): array {
		return array( 'get_media', 'upload_media', 'delete_media' );
	}

	/** @inheritDoc */
	public function handle( string $actionId, array $params, bool $dryRun ): array {
		return match ( $actionId ) {
			'get_media'    => $this->getMedia( $params ),
			'upload_media' => $this->uploadMedia( $params, $dryRun ),
			'delete_media' => $this->deleteMedia( $params, $dryRun ),
			default        => throw new \Exception( esc_html( "MediaHandler: unknown action '{$actionId}'." ) ),
		};
	}

	private function getMedia( array $params ): array {
		$mime_type = $params['mime_type'] ?? '';
		$search    = $params['search'] ?? '';
		$limit     = isset( $params['limit'] ) ? (int) $params['limit'] : 20;

		$args = array(
			'post_type'      => 'attachment',
			'post_status'    => 'inherit',
			'posts_per_page' => $limit,
		);

		if ( ! empty( $mime_type ) ) {
			$args['post_mime_type'] = sanitize_text_field( $mime_type );
		}
		if ( ! empty( $search ) ) {
			$args['s'] = sanitize_text_field( $search );
		}

		$attachments = get_posts( $args );
		$data        = array();

		foreach ( $attachments as $a ) {
			$meta   = wp_get_attachment_metadata( $a->ID );
			$data[] = array(
				'id'        => $a->ID,
				'title'     => $a->post_title,
				'mime_type' => $a->post_mime_type,
				'url'       => wp_get_attachment_url( $a->ID ),
				'date'      => $a->post_date,
				'width'     => $meta['width'] ?? null,
				'height'    => $meta['height'] ?? null,
				'alt_text'  => get_post_meta( $a->ID, '_wp_attachment_image_alt', true ),
			);
		}

		return array( 'media' => $data, 'count' => count( $data ) );
	}

	private function uploadMedia( array $params, bool $dryRun ): array {
		$url      = $params['url'] ?? '';
		$title    = $params['title'] ?? '';
		$alt_text = $params['alt_text'] ?? '';
		$caption  = $params['caption'] ?? '';

		if ( empty( $url ) || ! filter_var( $url, FILTER_VALIDATE_URL ) ) {
			throw new \Exception( 'A valid URL is required.' );
		}

		if ( $dryRun ) {
			return array(
				'action'   => 'Will sideload media',
				'url'      => $url,
				'title'    => $title,
				'alt_text' => $alt_text,
				'caption'  => $caption,
			);
		}

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

		$attachment_id = media_sideload_image( $url, 0, $title, 'id' );
		if ( is_wp_error( $attachment_id ) ) {
			// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
			throw new \Exception( 'Upload failed: ' . $attachment_id->get_error_message() );
		}

		if ( ! empty( $alt_text ) ) {
			update_post_meta( $attachment_id, '_wp_attachment_image_alt', sanitize_text_field( $alt_text ) );
		}
		if ( ! empty( $caption ) ) {
			wp_update_post( array(
				'ID'           => $attachment_id,
				'post_excerpt' => $caption,
			) );
		}

		return array(
			'success' => true,
			'id'      => $attachment_id,
			'url'     => wp_get_attachment_url( $attachment_id ),
		);
	}

	private function deleteMedia( array $params, bool $dryRun ): array {
		$attachment_ids = $params['attachment_ids'] ?? array();

		if ( empty( $attachment_ids ) || ! is_array( $attachment_ids ) ) {
			throw new \Exception( 'attachment_ids array is required.' );
		}
		if ( count( $attachment_ids ) > self::MAX_BULK ) {
			throw new \Exception( 'Maximum 50 attachments per operation.' );
		}

		$details = array();
		foreach ( $attachment_ids as $id ) {
			$id   = (int) $id;
			$post = get_post( $id );
			if ( $post && $post->post_type === 'attachment' ) {
				$details[] = array(
					'id'       => $id,
					'title'    => $post->post_title,
					'filename' => wp_basename( get_attached_file( $id ) ),
				);
			}
		}

		if ( $dryRun ) {
			return array(
				'action'      => 'Will permanently delete media files',
				'count'       => count( $details ),
				'attachments' => $details,
				'warning'     => 'This will PERMANENTLY remove the files from the server. This cannot be undone.',
			);
		}

		$deleted = 0;
		$failed  = 0;
		foreach ( $details as $item ) {
			wp_delete_attachment( $item['id'], true ) ? $deleted++ : $failed++;
		}

		return array(
			'success' => $deleted > 0,
			'message' => "{$deleted} media file(s) permanently deleted. Failed: {$failed}.",
			'deleted' => $deleted,
			'failed'  => $failed,
		);
	}
}
