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

namespace Hafenstudios\Kurato\Rest;

use Hafenstudios\Kurato\Db\ContactRepository;
use Hafenstudios\Kurato\Db\StageRepository;

defined( 'ABSPATH' ) || exit;

/**
 * REST: das komplette Kanban-Board (`kurato/v1/pipeline`).
 *
 * Liefert Stufen samt ihren Kontakten in EINEM Request (statt einer Abfrage je
 * Spalte), damit das Board schnell laedt. Cap hs_view_contacts.
 */
final class PipelineController {

	public const REST_NAMESPACE = 'kurato/v1';

	/**
	 * Maximale Karten je Spalte (Rest ist ueber die Kontaktliste erreichbar).
	 */
	private const PER_STAGE = 100;

	private ContactRepository $contacts;

	private StageRepository $stages;

	/**
	 * @param ContactRepository $contacts Kontakt-Repository.
	 * @param StageRepository   $stages   Stufen-Repository.
	 */
	public function __construct( ContactRepository $contacts, StageRepository $stages ) {
		$this->contacts = $contacts;
		$this->stages   = $stages;
	}

	/**
	 * Registriert die Route.
	 *
	 * @return void
	 */
	public function register_routes(): void {
		register_rest_route(
			self::REST_NAMESPACE,
			'/pipeline',
			array(
				'methods'             => \WP_REST_Server::READABLE,
				'callback'            => array( $this, 'get_board' ),
				'permission_callback' => static function () {
					if ( current_user_can( 'hs_view_contacts' ) ) {
						return true;
					}
					return new \WP_Error(
						'kurato_forbidden',
						__( 'Sie haben keine Berechtigung, die Pipeline einzusehen.', 'kurato' ),
						array( 'status' => rest_authorization_required_code() )
					);
				},
			)
		);
	}

	/**
	 * GET /pipeline - Stufen mit Karten.
	 *
	 * @return \WP_REST_Response
	 */
	public function get_board(): \WP_REST_Response {
		$counts = $this->stages->contact_counts();
		$board  = array();

		foreach ( $this->stages->all() as $stage ) {
			$cards = array_map(
				array( $this, 'card' ),
				$this->contacts->by_stage( (int) $stage['id'], self::PER_STAGE )
			);

			$board[] = array(
				'id'       => (int) $stage['id'],
				'label'    => (string) $stage['label'],
				'is_won'   => (bool) $stage['is_won'],
				'is_lost'  => (bool) $stage['is_lost'],
				'count'    => $counts[ $stage['id'] ] ?? 0,
				'contacts' => $cards,
			);
		}

		return new \WP_REST_Response( $board, 200 );
	}

	/**
	 * Reduziert einen Kontakt auf die Kartendarstellung.
	 *
	 * @param array<string, mixed> $contact Kontakt.
	 * @return array<string, mixed>
	 */
	private function card( array $contact ): array {
		$name = (string) $contact['display_name'];
		if ( '' === $name ) {
			$name = (string) $contact['email'];
		}
		return array(
			'id'    => (int) $contact['id'],
			'name'  => $name,
			'email' => (string) $contact['email'],
		);
	}
}
