<?php
/**
 * @package Hafenstudios\Kurato
 */

namespace Hafenstudios\Kurato\Rest;

use Hafenstudios\Kurato\Db\ContactRepository;
use Hafenstudios\Kurato\Db\TaskRepository;

defined( 'ABSPATH' ) || exit;

/**
 * REST: Wiedervorlagen (`kurato/v1/contacts/{id}/tasks`, `.../tasks/{id}/done`).
 * Lesen hs_view_contacts, Aendern hs_manage_contacts.
 */
final class TasksController extends AbstractController {

	public const REST_NAMESPACE = 'kurato/v1';

	private ContactRepository $contacts;

	private TaskRepository $tasks;

	/**
	 * @param ContactRepository $contacts Kontakt-Repository.
	 * @param TaskRepository    $tasks    Task-Repository.
	 */
	public function __construct( ContactRepository $contacts, TaskRepository $tasks ) {
		$this->contacts = $contacts;
		$this->tasks    = $tasks;
	}

	/**
	 * Registriert die Routen.
	 *
	 * @return void
	 */
	public function register_routes(): void {
		// CP3-Entscheidung: globale offene Wiedervorlagen fuer die Bruecke
		// (kurato/v1 kennt sonst nur Aufgaben je Kontakt). Filter overdue.
		register_rest_route(
			self::REST_NAMESPACE,
			'/tasks',
			array(
				'methods'             => \WP_REST_Server::READABLE,
				'callback'            => array( $this, 'list_open' ),
				'permission_callback' => array( $this, 'can_view' ),
				'args'                => array(
					'overdue' => array( 'type' => 'boolean', 'default' => false ),
				),
			)
		);

		register_rest_route(
			self::REST_NAMESPACE,
			'/contacts/(?P<id>\d+)/tasks',
			array(
				array(
					'methods'             => \WP_REST_Server::READABLE,
					'callback'            => array( $this, 'list_tasks' ),
					'permission_callback' => array( $this, 'can_view' ),
				),
				array(
					'methods'             => \WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'create_task' ),
					'permission_callback' => array( $this, 'can_manage' ),
					'args'                => array(
						'title'    => array( 'type' => 'string', 'required' => true, 'sanitize_callback' => 'sanitize_text_field' ),
						'due_date' => array( 'type' => 'string', 'default' => '', 'sanitize_callback' => 'sanitize_text_field' ),
					),
				),
			)
		);

		register_rest_route(
			self::REST_NAMESPACE,
			'/tasks/(?P<id>\d+)/done',
			array(
				'methods'             => \WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'set_done' ),
				'permission_callback' => array( $this, 'can_manage' ),
				'args'                => array(
					'done' => array( 'type' => 'boolean', 'default' => true ),
				),
			)
		);
	}

	/**
	 * GET /tasks - offene Wiedervorlagen ueber alle Kontakte (Bruecke).
	 *
	 * @param \WP_REST_Request $request Request.
	 * @return \WP_REST_Response
	 */
	public function list_open( \WP_REST_Request $request ): \WP_REST_Response {
		$overdue = (bool) $request->get_param( 'overdue' );
		return new \WP_REST_Response( $this->tasks->open( $overdue ), 200 );
	}

	/**
	 * GET /contacts/{id}/tasks.
	 *
	 * @param \WP_REST_Request $request Request.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public function list_tasks( \WP_REST_Request $request ) {
		$id = (int) $request->get_param( 'id' );
		if ( null === $this->contacts->get( $id ) ) {
			return $this->not_found();
		}
		return new \WP_REST_Response( $this->tasks->for_contact( $id ), 200 );
	}

	/**
	 * POST /contacts/{id}/tasks.
	 *
	 * @param \WP_REST_Request $request Request.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public function create_task( \WP_REST_Request $request ) {
		$id = (int) $request->get_param( 'id' );
		if ( null === $this->contacts->get( $id ) ) {
			return $this->not_found();
		}
		$due     = (string) $request->get_param( 'due_date' );
		$task_id = $this->tasks->create( $id, (string) $request->get_param( 'title' ), '' !== $due ? $due : null );
		if ( 0 === $task_id ) {
			return new \WP_Error(
				'kurato_task_failed',
				__( 'Die Wiedervorlage konnte nicht angelegt werden. Bitte geben Sie einen Titel an.', 'kurato' ),
				array( 'status' => 400 )
			);
		}
		return new \WP_REST_Response( $this->tasks->for_contact( $id ), 201 );
	}

	/**
	 * POST /tasks/{id}/done.
	 *
	 * @param \WP_REST_Request $request Request.
	 * @return \WP_REST_Response|\WP_Error
	 */
	public function set_done( \WP_REST_Request $request ) {
		$id   = (int) $request->get_param( 'id' );
		$task = $this->tasks->get( $id );
		if ( null === $task ) {
			return new \WP_Error(
				'kurato_task_not_found',
				__( 'Die Wiedervorlage wurde nicht gefunden.', 'kurato' ),
				array( 'status' => 404 )
			);
		}
		$this->tasks->set_done( $id, (bool) $request->get_param( 'done' ) );
		return new \WP_REST_Response( $this->tasks->for_contact( (int) $task['contact_id'] ), 200 );
	}

	/**
	 * @return \WP_Error
	 */
	private function not_found() {
		return new \WP_Error(
			'kurato_contact_not_found',
			__( 'Der Kontakt wurde nicht gefunden.', 'kurato' ),
			array( 'status' => 404 )
		);
	}
}
