<?php

namespace Limb_Chatbot\Includes\Services\Actions\Parameter_Types;

use Limb_Chatbot\Includes\Data_Objects\Parameter;

/**
 * Class Attachment_Parameter_Type
 *
 * Handles attachment parameter validation and sanitization.
 * Value is stored as JSON array of attachment metadata.
 *
 * @package Limb_Chatbot\Includes\Services\Actions\Parameter_Types
 * @since 1.0.0
 */
class Attachment_Parameter_Type extends Abstract_Parameter_Type {

	/**
	 * @inheritDoc
	 */
	public function get_type(): string {
		return Parameter::TYPE_ATTACHMENT;
	}

	/**
	 * @inheritDoc
	 */
	public function get_config_schema(): array {
		return [
			'allowed_mime_types' => [
				'type'        => 'array',
				'description' => 'Allowed MIME types for uploaded files',
				'required'    => false,
			],
			'max_file_size' => [
				'type'        => 'integer',
				'description' => 'Maximum file size in bytes per file',
				'required'    => false,
			],
			'max_files_count' => [
				'type'        => 'integer',
				'description' => 'Maximum number of files allowed',
				'required'    => false,
			],
			'multiple' => [
				'type'        => 'boolean',
				'description' => 'Whether multiple files are allowed',
				'required'    => false,
			],
			'lead_capture_map_field' => [
				'type'        => 'integer',
				'description' => 'Lead capture map field',
				'required'    => false,
			],
		];
	}

	/**
	 * @inheritDoc
	 */
	public function sanitize( string $value, Parameter $parameter ): string {
		$attachments = json_decode( $value, true );
		if ( ! is_array( $attachments ) ) {
			return '[]';
		}

		$normalized = [];
		foreach ( $attachments as $item ) {
			if ( ! is_array( $item ) ) {
				continue;
			}

			$normalized[] = [
				'title'      => isset( $item['title'] ) ? sanitize_text_field( (string) $item['title'] ) : '',
				'mime_type'  => isset( $item['mime_type'] ) ? sanitize_mime_type( (string) $item['mime_type'] ) : '',
				'value'      => isset( $item['value'] ) ? esc_url_raw( (string) $item['value'] ) : '',
				'media_id'   => isset( $item['media_id'] ) ? absint( $item['media_id'] ) : 0,
				'file_size'  => isset( $item['file_size'] ) ? absint( $item['file_size'] ) : 0,
				'file_name'  => isset( $item['file_name'] ) ? sanitize_file_name( (string) $item['file_name'] ) : '',
			];
		}

		return wp_json_encode( $normalized );
	}

	/**
	 * @inheritDoc
	 */
	public function validate( string $value, Parameter $parameter ): bool {
		$this->clear_errors();

		$trimmed = trim( $value );
		if ( $trimmed === '' || $trimmed === '[]' ) {
			if ( $this->is_required( $parameter ) ) {
				$this->add_error( sprintf( __( '%s is required.', 'limb-chatbot' ), $this->get_label( $parameter ) ) );

				return false;
			}

			return true;
		}

		$attachments = json_decode( $trimmed, true );
		if ( ! is_array( $attachments ) ) {
			$this->add_error( __( 'Invalid attachment payload.', 'limb-chatbot' ) );

			return false;
		}

		$config            = $parameter->get_config() ?? [];
		$multiple          = isset( $config['multiple'] ) ? in_array( $config['multiple'], [ 1, '1', true ], true ) : true;
		$max_files_count   = isset( $config['max_files_count'] ) ? max( 1, (int) $config['max_files_count'] ) : 5;
		$max_file_size     = isset( $config['max_file_size'] ) ? max( 1, (int) $config['max_file_size'] ) : ( 20 * 1024 * 1024 );
		$allowed_mime_type = isset( $config['allowed_mime_types'] ) && is_array( $config['allowed_mime_types'] )
			? array_values( array_filter( array_map( 'sanitize_mime_type', $config['allowed_mime_types'] ) ) )
			: [];

		if ( ! $multiple && count( $attachments ) > 1 ) {
			$this->add_error( __( 'Only one attachment is allowed.', 'limb-chatbot' ) );

			return false;
		}
		if ( count( $attachments ) > $max_files_count ) {
			$this->add_error( sprintf( __( 'Maximum %d file(s) allowed.', 'limb-chatbot' ), $max_files_count ) );

			return false;
		}

		foreach ( $attachments as $item ) {
			if ( ! is_array( $item ) ) {
				$this->add_error( __( 'Invalid attachment item.', 'limb-chatbot' ) );

				return false;
			}

			$url       = isset( $item['value'] ) ? esc_url_raw( (string) $item['value'] ) : '';
			$mime_type = isset( $item['mime_type'] ) ? sanitize_mime_type( (string) $item['mime_type'] ) : '';
			$media_id  = isset( $item['media_id'] ) ? absint( $item['media_id'] ) : 0;

			if ( empty( $url ) || empty( $mime_type ) || ! filter_var( $url, FILTER_VALIDATE_URL ) ) {
				$this->add_error( __( 'Attachment URL or mime type is invalid.', 'limb-chatbot' ) );

				return false;
			}

			if ( ! empty( $allowed_mime_type ) && ! in_array( $mime_type, $allowed_mime_type, true ) ) {
				$this->add_error( sprintf( __( 'File type "%s" is not allowed.', 'limb-chatbot' ), $mime_type ) );

				return false;
			}

			if ( $media_id <= 0 ) {
				$this->add_error( __( 'Attachment media identifier is missing.', 'limb-chatbot' ) );

				return false;
			}

			$media_post = get_post( $media_id );
			if ( ! $media_post || $media_post->post_type !== 'attachment' ) {
				$this->add_error( __( 'Attachment media item is invalid.', 'limb-chatbot' ) );

				return false;
			}

			$media_url  = wp_get_attachment_url( $media_id );
			$media_mime = get_post_mime_type( $media_id );
			$media_path = get_attached_file( $media_id );
			$media_size = ( $media_path && file_exists( $media_path ) ) ? filesize( $media_path ) : 0;

			if ( empty( $media_url ) || empty( $media_mime ) || empty( $media_size ) ) {
				$this->add_error( __( 'Attachment media file is not accessible.', 'limb-chatbot' ) );

				return false;
			}

			if ( esc_url_raw( $media_url ) !== $url ) {
				$this->add_error( __( 'Attachment URL does not match media item.', 'limb-chatbot' ) );

				return false;
			}
			if ( sanitize_mime_type( $media_mime ) !== $mime_type ) {
				$this->add_error( __( 'Attachment mime type mismatch.', 'limb-chatbot' ) );

				return false;
			}
			if ( (int) $media_size > $max_file_size ) {
				$this->add_error( __( 'Attachment exceeds allowed file size.', 'limb-chatbot' ) );

				return false;
			}
		}

		return true;
	}

	/**
	 * @inheritDoc
	 */
	public function is_valid_config( string $config_key, $config_value ): bool {
		if ( $config_key === 'allowed_mime_types' ) {
			if ( ! is_array( $config_value ) ) {
				return false;
			}
			foreach ( $config_value as $mime_type ) {
				$mime_type = sanitize_mime_type( (string) $mime_type );
				if ( empty( $mime_type ) || ! in_array( $mime_type, array_values( get_allowed_mime_types() ), true ) ) {
					return false;
				}
			}

			return true;
		}

		if ( in_array( $config_key, [ 'max_file_size', 'max_files_count' ], true ) ) {
			return is_numeric( $config_value ) && (int) $config_value > 0;
		}

		return parent::is_valid_config( $config_key, $config_value );
	}

	/**
	 * @inheritDoc
	 */
	public function get_hint( Parameter $parameter ): ?string {
		return __( 'Attach file(s) and submit.', 'limb-chatbot' );
	}
}

