<?php

declare(strict_types=1);

namespace FormConnector\API\Endpoints;

use FormConnector\Features\Attribution\AttributionQuery;
use FormConnector\Features\Attribution\AttributionTracker;

/**
 * Attribution REST API endpoints.
 *
 * Provides marketing attribution analytics: summary aggregation,
 * time-series data, KPI totals, and drill-down submission lists.
 */
class AttributionEndpoints {

	private const NAMESPACE = 'fc/v1';

	/**
	 * Register attribution routes.
	 */
	public static function register(): void {
		register_rest_route(self::NAMESPACE, '/attribution/summary', [
			'methods'             => \WP_REST_Server::READABLE,
			'callback'            => [self::class, 'get_summary'],
			'permission_callback' => [self::class, 'permission_check'],
		]);

		register_rest_route(self::NAMESPACE, '/attribution/timeseries', [
			'methods'             => \WP_REST_Server::READABLE,
			'callback'            => [self::class, 'get_timeseries'],
			'permission_callback' => [self::class, 'permission_check'],
		]);

		register_rest_route(self::NAMESPACE, '/attribution/submissions', [
			'methods'             => \WP_REST_Server::READABLE,
			'callback'            => [self::class, 'get_submissions'],
			'permission_callback' => [self::class, 'permission_check'],
		]);

		register_rest_route(self::NAMESPACE, '/attribution/kpis', [
			'methods'             => \WP_REST_Server::READABLE,
			'callback'            => [self::class, 'get_kpis'],
			'permission_callback' => [self::class, 'permission_check'],
		]);

		register_rest_route(self::NAMESPACE, '/attribution/lead-status', [
			'methods'             => \WP_REST_Server::CREATABLE,
			'callback'            => [self::class, 'update_lead_status'],
			'permission_callback' => [self::class, 'permission_check'],
		]);
	}

	/**
	 * Permission check for admin-only endpoints.
	 */
	public static function permission_check(): bool {
		return current_user_can('manage_options');
	}

	/**
	 * Get attribution summary.
	 */
	public static function get_summary(\WP_REST_Request $request): \WP_REST_Response {
		[$from, $to] = self::parse_date_range($request);
		$group_by = sanitize_text_field($request->get_param('group_by') ?? 'campaign');

		$data = AttributionQuery::summary($from, $to, $group_by);

		return new \WP_REST_Response([
			'success' => true,
			'data'    => $data,
		], 200);
	}

	/**
	 * Get time-series data.
	 */
	public static function get_timeseries(\WP_REST_Request $request): \WP_REST_Response {
		[$from, $to] = self::parse_date_range($request);
		$metric   = sanitize_text_field($request->get_param('metric') ?? 'submissions');
		$group_by = sanitize_text_field($request->get_param('group_by') ?? '');

		$data = AttributionQuery::timeseries($from, $to, $metric, $group_by);

		return new \WP_REST_Response([
			'success' => true,
			'data'    => $data,
		], 200);
	}

	/**
	 * Get paginated submissions list.
	 */
	public static function get_submissions(\WP_REST_Request $request): \WP_REST_Response {
		[$from, $to] = self::parse_date_range($request);

		$filters = [];
		foreach (['utm_campaign', 'utm_source', 'utm_medium', 'form_plugin', 'lead_status', 'location_id'] as $key) {
			$val = $request->get_param($key);
			if (!empty($val)) {
				$filters[$key] = $val;
			}
		}

		$page     = max(1, (int) ($request->get_param('page') ?? 1));
		$per_page = max(1, min(100, (int) ($request->get_param('per_page') ?? 25)));

		$data = AttributionQuery::submissions($from, $to, $filters, $page, $per_page);

		return new \WP_REST_Response([
			'success' => true,
			'data'    => $data,
		], 200);
	}

	/**
	 * Get KPI totals.
	 */
	public static function get_kpis(\WP_REST_Request $request): \WP_REST_Response {
		[$from, $to] = self::parse_date_range($request);

		$data = AttributionQuery::kpis($from, $to);

		return new \WP_REST_Response([
			'success' => true,
			'data'    => $data,
		], 200);
	}

	/**
	 * Update lead status for a CareHQ contact.
	 */
	public static function update_lead_status(\WP_REST_Request $request): \WP_REST_Response {
		$contact_id = sanitize_text_field($request->get_param('contact_id') ?? '');
		$status     = sanitize_text_field($request->get_param('status') ?? '');
		$value      = $request->get_param('value');

		if (empty($contact_id) || empty($status)) {
			return new \WP_REST_Response([
				'success' => false,
				'message' => __('contact_id and status are required.', 'form-connector'),
			], 400);
		}

		if (!in_array($status, AttributionTracker::LEAD_STATUSES, true)) {
			return new \WP_REST_Response([
				'success' => false,
				'message' => __('Invalid lead status.', 'form-connector'),
			], 400);
		}

		$tracker = AttributionTracker::get_instance();
		$updated = $tracker->update_lead_status(
			$contact_id,
			$status,
			$value !== null ? (float) $value : null
		);

		return new \WP_REST_Response([
			'success' => true,
			'data'    => ['updated' => $updated],
		], 200);
	}

	/**
	 * Parse from/to date range from request params with defaults.
	 *
	 * @return array [from_date, to_date]
	 */
	private static function parse_date_range(\WP_REST_Request $request): array {
		$to   = $request->get_param('to');
		$from = $request->get_param('from');

		// Default to last 30 days
		if (empty($to)) {
			$to = gmdate('Y-m-d');
		} else {
			$to = sanitize_text_field($to);
		}

		if (empty($from)) {
			$from = gmdate('Y-m-d', strtotime('-30 days'));
		} else {
			$from = sanitize_text_field($from);
		}

		// Validate format
		if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $from)) {
			$from = gmdate('Y-m-d', strtotime('-30 days'));
		}
		if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $to)) {
			$to = gmdate('Y-m-d');
		}

		// Cap range to 1 year
		$from_ts = strtotime($from);
		$to_ts   = strtotime($to);
		if ($to_ts - $from_ts > 365 * 86400) {
			$from = gmdate('Y-m-d', $to_ts - 365 * 86400);
		}

		return [$from, $to];
	}
}
