<?php
/**
 * Campaigns REST Controller
 *
 * REST API endpoints for campaign management.
 *
 * @package DonorCore\API
 */

namespace DonorCore\API;

defined( 'ABSPATH' ) || exit;

/**
 * Campaigns Controller Class
 */
class Campaigns_Controller extends REST_Controller_Base {

	/**
	 * Route base.
	 *
	 * @var string
	 */
	protected $rest_base = 'campaigns';

	/**
	 * Donation log repository.
	 *
	 * @var \DonorCore\Database\Donation_Log_Repository
	 */
	private $donation_repo;

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->donation_repo = new \DonorCore\Database\Donation_Log_Repository();
	}

	/**
	 * Register routes.
	 */
	public function register_routes() {
		// List campaigns.
		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base,
			array(
				array(
					'methods'             => \WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_items' ),
					'permission_callback' => array( $this, 'check_admin_permissions' ),
				),
				array(
					'methods'             => \WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'create_item' ),
					'permission_callback' => array( $this, 'check_write_permissions' ),
				),
			)
		);

		// Single campaign.
		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/(?P<id>[\d]+)',
			array(
				array(
					'methods'             => \WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_item' ),
					'permission_callback' => array( $this, 'check_admin_permissions' ),
				),
				array(
					'methods'             => \WP_REST_Server::EDITABLE,
					'callback'            => array( $this, 'update_item' ),
					'permission_callback' => array( $this, 'check_write_permissions' ),
				),
				array(
					'methods'             => \WP_REST_Server::DELETABLE,
					'callback'            => array( $this, 'delete_item' ),
					'permission_callback' => array( $this, 'check_delete_permissions' ),
				),
			)
		);

		// Public campaign progress (no auth required).
		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/(?P<id>[\d]+)/progress',
			array(
				'methods'             => \WP_REST_Server::READABLE,
				'callback'            => array( $this, 'get_progress' ),
				'permission_callback' => '__return_true', // Public endpoint.
			)
		);
	}

	/**
	 * Get campaigns list.
	 *
	 * @param \WP_REST_Request $request Request object.
	 * @return \WP_REST_Response
	 */
	public function get_items( $request ) {
		$pagination = $this->get_pagination_params( $request );

		$args = array(
			'post_type'      => 'donorcore_campaign',
			'post_status'    => 'publish',
			'posts_per_page' => $pagination['per_page'],
			'paged'          => $pagination['page'],
		);

		$query = new \WP_Query( $args );

		$campaigns = array();
		foreach ( $query->posts as $post ) {
			$campaigns[] = $this->prepare_item( $post );
		}

		$response = $this->success( $campaigns );
		return $this->add_pagination_headers( $response, $query->found_posts, $pagination['page'], $pagination['per_page'] );
	}

	/**
	 * Get single campaign.
	 *
	 * @param \WP_REST_Request $request Request object.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public function get_item( $request ) {
		$campaign_id = $request->get_param( 'id' );
		$campaign    = get_post( $campaign_id );

		if ( ! $campaign || 'donorcore_campaign' !== $campaign->post_type ) {
			return $this->error( 'campaign_not_found', __( 'Campaign not found.', 'donorcore-donations' ), 404 );
		}

		return $this->success( $this->prepare_item( $campaign, true ) );
	}

	/**
	 * Create campaign.
	 *
	 * @param \WP_REST_Request $request Request object.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public function create_item( $request ) {
		$title = $this->sanitize_input( $request->get_param( 'title' ) );

		if ( empty( $title ) ) {
			return $this->error( 'missing_title', __( 'Campaign title is required.', 'donorcore-donations' ) );
		}

		$campaign_id = wp_insert_post(
			array(
				'post_title'   => $title,
				'post_content' => $request->get_param( 'content' ) ?: '',
				'post_status'  => 'draft',
				'post_type'    => 'donorcore_campaign',
			)
		);

		if ( is_wp_error( $campaign_id ) ) {
			return $this->error( 'create_failed', $campaign_id->get_error_message() );
		}

		// Update meta fields.
		$this->update_campaign_meta( $campaign_id, $request );

		return $this->success( $this->prepare_item( get_post( $campaign_id ), true ), 201 );
	}

	/**
	 * Update campaign.
	 *
	 * @param \WP_REST_Request $request Request object.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public function update_item( $request ) {
		$campaign_id = $request->get_param( 'id' );
		$campaign    = get_post( $campaign_id );

		if ( ! $campaign || 'donorcore_campaign' !== $campaign->post_type ) {
			return $this->error( 'campaign_not_found', __( 'Campaign not found.', 'donorcore-donations' ), 404 );
		}

		$update_data = array( 'ID' => $campaign_id );

		if ( $request->has_param( 'title' ) ) {
			$update_data['post_title'] = $this->sanitize_input( $request->get_param( 'title' ) );
		}

		if ( $request->has_param( 'content' ) ) {
			$update_data['post_content'] = $request->get_param( 'content' );
		}

		wp_update_post( $update_data );
		$this->update_campaign_meta( $campaign_id, $request );

		return $this->success( $this->prepare_item( get_post( $campaign_id ), true ) );
	}

	/**
	 * Delete campaign.
	 *
	 * @param \WP_REST_Request $request Request object.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public function delete_item( $request ) {
		$campaign_id = $request->get_param( 'id' );
		$campaign    = get_post( $campaign_id );

		if ( ! $campaign || 'donorcore_campaign' !== $campaign->post_type ) {
			return $this->error( 'campaign_not_found', __( 'Campaign not found.', 'donorcore-donations' ), 404 );
		}

		$result = wp_delete_post( $campaign_id, true );

		if ( ! $result ) {
			return $this->error( 'delete_failed', __( 'Failed to delete campaign.', 'donorcore-donations' ) );
		}

		return $this->success( array( 'deleted' => true ) );
	}

	/**
	 * Get campaign progress (public endpoint).
	 *
	 * @param \WP_REST_Request $request Request object.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public function get_progress( $request ) {
		$campaign_id = $request->get_param( 'id' );
		$campaign    = get_post( $campaign_id );

		if ( ! $campaign || 'donorcore_campaign' !== $campaign->post_type || 'publish' !== $campaign->post_status ) {
			return $this->error( 'campaign_not_found', __( 'Campaign not found.', 'donorcore-donations' ), 404 );
		}

		$goal   = get_post_meta( $campaign_id, '_donorcore_campaign_goal', true );
		$raised = $this->donation_repo->get_campaign_total( $campaign_id );

		return $this->success(
			array(
				'campaign_id' => $campaign_id,
				'title'       => $campaign->post_title,
				'goal'        => floatval( $goal ),
				'raised'      => floatval( $raised ),
				'progress'    => $goal > 0 ? round( ( $raised / $goal ) * 100, 1 ) : 0,
			)
		);
	}

	/**
	 * Prepare campaign item for response.
	 *
	 * @param \WP_Post $campaign    Campaign post object.
	 * @param bool     $full_details Include full details.
	 * @return array
	 */
	private function prepare_item( $campaign, $full_details = false ) {
		$goal   = floatval( get_post_meta( $campaign->ID, '_donorcore_campaign_goal', true ) );
		$raised = floatval( $this->donation_repo->get_campaign_total( $campaign->ID ) );

		$data = array(
			'id'         => absint( $campaign->ID ),
			'title'      => sanitize_text_field( $campaign->post_title ),
			'goal'       => $goal,
			'raised'     => $raised,
			'progress'   => $goal > 0 ? round( ( $raised / $goal ) * 100, 1 ) : 0,
			'status'     => sanitize_text_field( $campaign->post_status ),
			'start_date' => sanitize_text_field( get_post_meta( $campaign->ID, '_donorcore_campaign_start_date', true ) ),
			'end_date'   => sanitize_text_field( get_post_meta( $campaign->ID, '_donorcore_campaign_end_date', true ) ),
		);

		if ( $full_details ) {
			$data['content']      = wp_kses_post( $campaign->post_content );
			$data['min_donation'] = floatval( get_post_meta( $campaign->ID, '_donorcore_campaign_min_donation', true ) );

			$suggested_raw = get_post_meta( $campaign->ID, '_donorcore_campaign_suggested_amounts', true );
			$suggested     = is_string( $suggested_raw ) && ! empty( $suggested_raw ) ? json_decode( $suggested_raw, true ) : null;
			if ( is_array( $suggested ) ) {
				$suggested = array_filter( array_map( 'floatval', $suggested ) );
			}
			if ( empty( $suggested ) || ! is_array( $suggested ) ) {
				$global_suggested = get_option( 'donorcore_suggested_amounts', '50,100,250,500' );
				$suggested        = array_map( 'floatval', array_filter( array_map( 'trim', explode( ',', $global_suggested ) ) ) );
				if ( empty( $suggested ) ) {
					$suggested = array( 50, 100, 250, 500 );
				}
			}
			$data['suggested_amounts'] = array_values( $suggested );
			$data['product_id']        = absint( get_post_meta( $campaign->ID, '_donorcore_campaign_product_id', true ) );
		}

		return $data;
	}

	/**
	 * Update campaign meta fields.
	 *
	 * @param int              $campaign_id Campaign ID.
	 * @param \WP_REST_Request $request     Request object.
	 */
	private function update_campaign_meta( $campaign_id, $request ) {
		if ( $request->has_param( 'goal' ) ) {
			update_post_meta( $campaign_id, '_donorcore_campaign_goal', $this->sanitize_input( $request->get_param( 'goal' ), 'float' ) );
		}

		if ( $request->has_param( 'min_donation' ) ) {
			update_post_meta( $campaign_id, '_donorcore_campaign_min_donation', $this->sanitize_input( $request->get_param( 'min_donation' ), 'float' ) );
		}

		if ( $request->has_param( 'suggested_amounts' ) ) {
			update_post_meta( $campaign_id, '_donorcore_campaign_suggested_amounts', wp_json_encode( $request->get_param( 'suggested_amounts' ) ) );
		}

		if ( $request->has_param( 'start_date' ) ) {
			update_post_meta( $campaign_id, '_donorcore_campaign_start_date', $this->sanitize_input( $request->get_param( 'start_date' ) ) );
		}

		if ( $request->has_param( 'end_date' ) ) {
			update_post_meta( $campaign_id, '_donorcore_campaign_end_date', $this->sanitize_input( $request->get_param( 'end_date' ) ) );
		}
	}
}
