<?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
if ( ! defined( 'DROP_PRINT_PROOF_VERDICTS_META' ) ) {
	define( 'DROP_PRINT_PROOF_VERDICTS_META', 'drop_print_proof_verdicts' );
}
if ( ! function_exists( 'drop_print_proof_verdict_key' ) ) {
	function drop_print_proof_verdict_key( string $artwork_key, string $paper_key ): string {
		$a = sanitize_key( $artwork_key );
		$p = sanitize_key( $paper_key );
		if ( '' === $a || '' === $p ) {
			return '';
		}
		return $a . '|' . $p;
	}
}
if ( ! function_exists( 'drop_print_get_proof_verdicts' ) ) {
	function drop_print_get_proof_verdicts( int $user_id = 0 ): array {
		if ( 0 === $user_id ) {
			$user_id = get_current_user_id();
		}
		if ( $user_id <= 0 ) {
			return array();
		}
		$stored = get_user_meta( $user_id, DROP_PRINT_PROOF_VERDICTS_META, true );
		return is_array( $stored ) ? $stored : array();
	}
}
if ( ! function_exists( 'drop_print_get_proof_verdict' ) ) {
	function drop_print_get_proof_verdict( string $artwork_key, string $paper_key, int $user_id = 0 ): ?array {
		$key = drop_print_proof_verdict_key( $artwork_key, $paper_key );
		if ( '' === $key ) {
			return null;
		}
		$all = drop_print_get_proof_verdicts( $user_id );
		return isset( $all[ $key ] ) && is_array( $all[ $key ] ) ? $all[ $key ] : null;
	}
}
if ( ! function_exists( 'drop_print_store_proof_verdict' ) ) {
	function drop_print_store_proof_verdict( int $user_id, string $artwork_key, string $paper_key, array $verdict ): bool {
		$key = drop_print_proof_verdict_key( $artwork_key, $paper_key );
		if ( $user_id <= 0 || '' === $key ) {
			return false;
		}
		$all = drop_print_get_proof_verdicts( $user_id );
		$all[ $key ] = array(
			'verdict'    => in_array( $verdict['verdict'] ?? '', array( 'approved', 'declined' ), true )
				? $verdict['verdict']
				: '',
			'proof_ref'  => sanitize_text_field( (string) ( $verdict['proof_ref'] ?? '' ) ),
			'verdict_at' => sanitize_text_field( (string) ( $verdict['verdict_at'] ?? '' ) ),
			'note'       => sanitize_textarea_field( (string) ( $verdict['note'] ?? '' ) ),
			'mirrored_at' => gmdate( 'Y-m-d H:i:s' ),
		);
		return (bool) update_user_meta( $user_id, DROP_PRINT_PROOF_VERDICTS_META, $all );
	}
}
if ( ! function_exists( 'drop_print_register_proof_verdict_endpoint' ) ) {
	function drop_print_register_proof_verdict_endpoint(): void {
		register_rest_route(
			'drop-print-client/v1',
			'/proof-verdict',
			array(
				'methods'             => WP_REST_Server::EDITABLE,
				'callback'            => 'drop_print_handle_proof_verdict',
				'permission_callback' => 'drop_print_check_proof_verdict_permissions',
				'args'                => array(
					'client_wp_user_id' => array(
						'required'          => true,
						'validate_callback' => function ( $param ) {
							return is_numeric( $param ) && $param > 0;
						},
						'sanitize_callback' => 'absint',
					),
					'proof_ref'   => array( 'required' => true, 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field' ),
					'artwork_key' => array( 'required' => true, 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field' ),
					'paper_key'   => array( 'required' => true, 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field' ),
					'verdict'     => array( 'required' => true, 'type' => 'string', 'sanitize_callback' => 'sanitize_key' ),
					'verdict_at'  => array( 'required' => false, 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field' ),
					'note'        => array( 'required' => false, 'type' => 'string', 'sanitize_callback' => 'sanitize_textarea_field' ),
				),
			)
		);
	}
	add_action( 'rest_api_init', 'drop_print_register_proof_verdict_endpoint' );
}
if ( ! function_exists( 'drop_print_check_proof_verdict_permissions' ) ) {
	function drop_print_check_proof_verdict_permissions( WP_REST_Request $request ) {
		$client_wp_user_id = $request->get_param( 'client_wp_user_id' );
		if ( empty( $client_wp_user_id ) || ! is_numeric( $client_wp_user_id ) || $client_wp_user_id <= 0 ) {
			return new WP_Error( 'rest_invalid_client_user_id_proof', __( 'Client WordPress User ID is missing or invalid.', 'drop-print' ), array( 'status' => 400 ) );
		}
		$api_key_prefix = $request->get_header( 'X-Drop-Print-Client-Public-Key-Prefix' );
		if ( empty( $api_key_prefix ) ) {
			return new WP_Error( 'rest_missing_auth_header_proof', __( 'Missing required authentication header.', 'drop-print' ), array( 'status' => 401 ) );
		}
		$user_settings = drop_print_get_user_settings( absint( $client_wp_user_id ) );
		if ( empty( $user_settings['public_key_pem_b64'] ) || ! is_string( $user_settings['public_key_pem_b64'] ) ) {
			return new WP_Error( 'rest_client_user_auth_config_missing_proof', __( 'This user is not configured with a server public key.', 'drop-print' ), array( 'status' => 403 ) );
		}
		$stored_prefix = substr( $user_settings['public_key_pem_b64'], 0, 42 );
		if ( hash_equals( $stored_prefix, $api_key_prefix ) ) {
			return true;
		}
		return new WP_Error( 'rest_forbidden_proof_verdict', __( 'Invalid authentication credentials.', 'drop-print' ), array( 'status' => 403 ) );
	}
}
if ( ! function_exists( 'drop_print_handle_proof_verdict' ) ) {
	function drop_print_handle_proof_verdict( WP_REST_Request $request ) {
		$user_id = absint( $request->get_param( 'client_wp_user_id' ) );
		$user    = get_userdata( $user_id );
		if ( ! $user || ! $user->exists() ) {
			return new WP_Error( 'rest_user_not_found', __( 'Specified client WordPress user not found.', 'drop-print' ), array( 'status' => 404 ) );
		}
		$verdict = (string) $request->get_param( 'verdict' );
		if ( ! in_array( $verdict, array( 'approved', 'declined' ), true ) ) {
			return new WP_Error( 'rest_invalid_verdict', __( 'Verdict must be approved or declined.', 'drop-print' ), array( 'status' => 400 ) );
		}
		$artwork_key = (string) $request->get_param( 'artwork_key' );
		$paper_key   = (string) $request->get_param( 'paper_key' );
		$stored = drop_print_store_proof_verdict(
			$user_id,
			$artwork_key,
			$paper_key,
			array(
				'verdict'    => $verdict,
				'proof_ref'  => (string) $request->get_param( 'proof_ref' ),
				'verdict_at' => (string) ( $request->get_param( 'verdict_at' ) ?? '' ),
				'note'       => (string) ( $request->get_param( 'note' ) ?? '' ),
			)
		);
		if ( ! $stored ) {
			$check = drop_print_get_proof_verdict( $artwork_key, $paper_key, $user_id );
			if ( null === $check || ( $check['verdict'] ?? '' ) !== $verdict ) {
				return new WP_Error( 'rest_proof_verdict_not_stored', __( 'Could not store the verdict.', 'drop-print' ), array( 'status' => 500 ) );
			}
		}
		return new WP_REST_Response(
			array(
				'success'   => true,
				'proof_ref' => (string) $request->get_param( 'proof_ref' ),
				'verdict'   => $verdict,
			),
			200
		);
	}
}
