<?php
/**
 * Export Profile — CRUD for saved export configurations.
 */

namespace RawTypeOE\Free;

// Prevent direct access.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Manages saved export profiles stored as a custom post type.
 */
class Export_Profile {

	/** Custom post type slug. */
	const POST_TYPE = 'rawtype_oe_profile';

	/** Register lifecycle hooks for profile metadata. */
	public function register_hooks() {
		add_action( 'rawtype_oe_after_export', array( $this, 'handle_after_export' ), 20, 2 );
	}

	/**
	 * Get all profiles.
	 *
	 * @param array $args Optional WP_Query args.
	 * @return array Array of formatted profiles.
	 */
	public function get_all( $args = array() ) {
		$defaults = array(
			'post_type'      => self::POST_TYPE,
			'posts_per_page' => 50,
			'post_status'    => 'publish',
			'orderby'        => 'modified',
			'order'          => 'DESC',
		);

		$query = new \WP_Query( array_merge( $defaults, $args ) );

		return array_map( array( $this, 'format_profile' ), $query->posts );
	}

	/**
	 * Get a single profile by ID.
	 *
	 * @param int $profile_id Profile post ID.
	 * @return array|null Formatted profile or null.
	 */
	public function get( $profile_id ) {
		$post = get_post( absint( $profile_id ) );

		if ( ! $post || self::POST_TYPE !== $post->post_type ) {
			return null;
		}

		return $this->format_profile( $post );
	}

	/**
	 * Create a new profile.
	 *
	 * @param string $name   Profile name.
	 * @param array  $config Export configuration.
	 * @return int|\WP_Error Post ID or error.
	 */
	public function create( $name, $config ) {
		$post_id = wp_insert_post(
			array(
				'post_type'    => self::POST_TYPE,
				'post_title'   => sanitize_text_field( $name ),
				'post_content' => wp_json_encode( $config ),
				'post_status'  => 'publish',
				'post_author'  => get_current_user_id(),
			),
			true
		);

		if ( ! is_wp_error( $post_id ) ) {
			update_post_meta( $post_id, '_rawtype_oe_created_by', get_current_user_id() );

			/**
			 * Fires after an export profile is saved.
			 *
			 * @param int   $post_id Profile post ID.
			 * @param array $config  Export configuration.
			 */
			do_action( 'rawtype_oe_profile_saved', $post_id, $config );
		}

		return $post_id;
	}

	/**
	 * Update an existing profile.
	 *
	 * @param int    $profile_id Profile post ID.
	 * @param string $name       Profile name.
	 * @param array  $config     Updated export configuration.
	 * @return int|\WP_Error Post ID or error.
	 */
	public function update( $profile_id, $name, $config ) {
		$post = get_post( absint( $profile_id ) );

		if ( ! $post || self::POST_TYPE !== $post->post_type ) {
			return new \WP_Error(
				'profile_not_found',
				__( 'Profile not found.', 'rawtype-order-exporter-woocommerce' )
			);
		}

		$result = wp_update_post(
			array(
				'ID'           => absint( $profile_id ),
				'post_title'   => sanitize_text_field( $name ),
				'post_content' => wp_json_encode( $config ),
			),
			true
		);

		if ( ! is_wp_error( $result ) ) {
			/**
			 * Fires after an export profile is saved.
			 *
			 * @param int   $profile_id Profile post ID.
			 * @param array $config     Export configuration.
			 */
			do_action( 'rawtype_oe_profile_saved', $profile_id, $config );
		}

		return $result;
	}

	/**
	 * Delete a profile.
	 *
	 * @param int $profile_id Profile post ID.
	 * @return bool True if deleted.
	 */
	public function delete( $profile_id ) {
		$post = get_post( absint( $profile_id ) );

		if ( ! $post || self::POST_TYPE !== $post->post_type ) {
			return false;
		}

		return (bool) wp_delete_post( absint( $profile_id ), true );
	}

	/**
	 * Execute a profile export.
	 *
	 * @param int           $profile_id    Profile post ID.
	 * @param Export_Engine $export_engine Export engine instance.
	 * @return array|\WP_Error Export result or error.
	 */
	public function run( $profile_id, Export_Engine $export_engine ) {
		$profile = $this->get( $profile_id );

		if ( ! $profile ) {
			return new \WP_Error(
				'profile_not_found',
				__( 'Profile not found.', 'rawtype-order-exporter-woocommerce' )
			);
		}

		$config               = is_array( $profile['config'] ) ? $profile['config'] : array();
		$config['profile_id'] = absint( $profile_id );
		$config['source']     = 'profile';

		return $export_engine->export( $config );
	}

	/**
	 * Update profile run metadata after an export completes.
	 *
	 * @param array $export_result Export result payload.
	 * @param array $config        Export configuration.
	 */
	public function handle_after_export( $export_result, $config ) {
		if ( ! is_array( $config ) || empty( $config['profile_id'] ) ) {
			return;
		}

		$profile_id = absint( $config['profile_id'] );
		$post       = get_post( $profile_id );

		if ( ! $post || self::POST_TYPE !== $post->post_type ) {
			return;
		}

		update_post_meta( $profile_id, '_rawtype_oe_last_run_date', current_time( 'mysql' ) );

		if ( is_array( $export_result ) && isset( $export_result['count'] ) ) {
			update_post_meta( $profile_id, '_rawtype_oe_last_run_count', absint( $export_result['count'] ) );
		}
	}

	/**
	 * Format a profile post into a standard array.
	 *
	 * @param \WP_Post $post Profile post object.
	 * @return array Formatted profile data.
	 */
	private function format_profile( $post ) {
		$config  = json_decode( $post->post_content, true );
		$profile = array(
			'id'             => $post->ID,
			'name'           => $post->post_title,
			'config'         => is_array( $config ) ? $config : array(),
			'entity'         => isset( $config['entity'] ) ? $config['entity'] : '',
			'format'         => isset( $config['format'] ) ? $config['format'] : '',
			'created_at'     => $post->post_date,
			'modified_at'    => $post->post_modified,
			'last_run_date'  => get_post_meta( $post->ID, '_rawtype_oe_last_run_date', true ),
			'last_run_count' => (int) get_post_meta( $post->ID, '_rawtype_oe_last_run_count', true ),
			'created_by'     => (int) get_post_meta( $post->ID, '_rawtype_oe_created_by', true ),
		);

		/**
		 * Filter a formatted profile payload before it is returned over REST.
		 *
		 * @param array   $profile Formatted profile data.
		 * @param \WP_Post $post   Profile post object.
		 * @param array   $config  Decoded profile export configuration.
		 */
		return apply_filters( 'rawtype_oe_profile_response', $profile, $post, is_array( $config ) ? $config : array() );
	}
}
