<?php
/**
 * REST API for the Niwa template library and generated snippets.
 *
 * @package Niwa_AI
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class Niwa_AI_Template_Library_REST_Controller {
	private $templates;
	private $snippets;
	private $generator;
	private $validator;
	private $filesystem;

	public function __construct(
		Niwa_AI_Template_Repository $templates,
		Niwa_AI_Snippet_Repository $snippets,
		Niwa_AI_Template_AI_Generator $generator,
		Niwa_AI_Snippet_Validator $validator,
		Niwa_AI_Snippet_Filesystem $filesystem
	) {
		$this->templates  = $templates;
		$this->snippets   = $snippets;
		$this->generator  = $generator;
		$this->validator  = $validator;
		$this->filesystem = $filesystem;
	}

	public function register_hooks() {
		add_action( 'rest_api_init', array( $this, 'register_routes' ) );
	}

	public function register_routes() {
		register_rest_route(
			'niwa-ai/v1',
			'/template-library/templates',
			array(
				array(
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => array( $this, 'list_templates' ),
					'permission_callback' => array( $this, 'can_manage' ),
				),
				array(
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'create_template' ),
					'permission_callback' => array( $this, 'can_manage' ),
				),
			)
		);

		register_rest_route(
			'niwa-ai/v1',
			'/template-library/snippets',
			array(
				array(
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => array( $this, 'list_snippets' ),
					'permission_callback' => array( $this, 'can_manage' ),
				),
				array(
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'create_snippet' ),
					'permission_callback' => array( $this, 'can_manage' ),
				),
			)
		);

		register_rest_route(
			'niwa-ai/v1',
			'/template-library/snippets/(?P<id>\d+)/validate',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'validate_snippet' ),
				'permission_callback' => array( $this, 'can_manage' ),
			)
		);

		register_rest_route(
			'niwa-ai/v1',
			'/template-library/snippets/(?P<id>\d+)/publish',
			array(
				'methods'             => WP_REST_Server::CREATABLE,
				'callback'            => array( $this, 'publish_snippet' ),
				'permission_callback' => array( $this, 'can_manage' ),
			)
		);
	}

	public function can_manage() {
		return current_user_can( 'manage_options' );
	}

	public function list_templates( WP_REST_Request $request ) {
		return rest_ensure_response(
			array(
				'templates' => $this->templates->list_templates( $request->get_param( 'type' ), $request->get_param( 'limit' ) ? intval( $request->get_param( 'limit' ) ) : 60 ),
				'types'     => Niwa_AI_Template_Library_Types::labels(),
			)
		);
	}

	public function create_template( WP_REST_Request $request ) {
		$template = $this->templates->create_custom_template( $request->get_json_params() );
		if ( is_wp_error( $template ) ) {
			return $template;
		}
		return rest_ensure_response( array( 'template' => $template ) );
	}

	public function list_snippets( WP_REST_Request $request ) {
		return rest_ensure_response(
			array(
				'snippets' => $this->snippets->list_snippets( $request->get_param( 'type' ), $request->get_param( 'limit' ) ? intval( $request->get_param( 'limit' ) ) : 60, false ),
				'types'    => Niwa_AI_Template_Library_Types::labels(),
			)
		);
	}

	public function create_snippet( WP_REST_Request $request ) {
		$params      = $request->get_json_params();
		$template_id = intval( isset( $params['template_id'] ) ? $params['template_id'] : 0 );
		$template    = $template_id > 0 ? $this->templates->get_template( $template_id ) : null;
		if ( ! $template ) {
			$template = array(
				'id'          => 0,
				'title'       => sanitize_text_field( isset( $params['title'] ) ? $params['title'] : __( 'Custom Niwa Snippet', 'niwa-ai' ) ),
				'type'        => Niwa_AI_Template_Library_Types::TYPE_WEBSITE_SNIPPET,
				'output_mode' => 'shortcode',
				'prompt'      => sanitize_textarea_field( isset( $params['instructions'] ) ? $params['instructions'] : '' ),
				'agent_prompt' => sanitize_textarea_field( isset( $params['instructions'] ) ? $params['instructions'] : '' ),
				'elementor_schema' => array(),
				'manifest'    => array(),
			);
		}

		$artifact = $this->generator->generate_artifact( $template, isset( $params['instructions'] ) ? (string) $params['instructions'] : '', ! empty( $params['force_shortcode'] ) );
		$files = isset( $artifact['files'] ) && is_array( $artifact['files'] ) ? $artifact['files'] : array();
		if ( $this->artifact_has_unresolved_template( $files ) ) {
			return new WP_Error(
				'template_needs_agent_context',
				__( 'Use this template through Niwa chat on a target Elementor page, or add concrete shortcode instructions. Niwa will not create a blind placeholder snippet.', 'niwa-ai' ),
				array( 'status' => 400 )
			);
		}
		$type  = $this->snippet_type_for_template( $template );
		$result = $this->snippets->create_snippet(
			array(
				'title'       => sanitize_text_field( isset( $params['title'] ) && '' !== $params['title'] ? $params['title'] : $template['title'] ),
				'description' => sanitize_textarea_field( isset( $params['instructions'] ) ? $params['instructions'] : ( isset( $artifact['agent_notes'] ) ? (string) $artifact['agent_notes'] : '' ) ),
				'type'        => ! empty( $params['force_shortcode'] ) ? Niwa_AI_Template_Library_Types::TYPE_SHORTCODE : $type,
				'template_id' => $template_id,
				'files'       => $files,
			)
		);
		if ( is_wp_error( $result ) ) {
			return $result;
		}
		return rest_ensure_response(
			array(
				'snippet'  => $result,
				'artifact' => array(
					'llm_used'    => ! empty( $artifact['llm_used'] ),
					'llm_error'   => isset( $artifact['llm_error'] ) ? (string) $artifact['llm_error'] : '',
					'agent_notes' => isset( $artifact['agent_notes'] ) ? (string) $artifact['agent_notes'] : '',
				),
			)
		);
	}

	private function artifact_has_unresolved_template( $files ) {
		foreach ( is_array( $files ) ? $files : array() as $file ) {
			$name    = isset( $file['name'] ) ? strtolower( (string) $file['name'] ) : '';
			$content = isset( $file['content'] ) ? (string) $file['content'] : '';
			if ( 'template.html' === $name && ( false !== strpos( $content, 'data-niwa-template-unresolved="1"' ) || false !== strpos( $content, "data-niwa-template-unresolved='1'" ) ) ) {
				return true;
			}
		}
		return false;
	}

	public function validate_snippet( WP_REST_Request $request ) {
		$snippet = $this->snippets->get_snippet( intval( $request['id'] ), true );
		if ( ! $snippet ) {
			return new WP_Error( 'not_found', __( 'Snippet not found.', 'niwa-ai' ), array( 'status' => 404 ) );
		}
		$result = $this->validator->validate( $snippet );
		if ( is_wp_error( $result ) ) {
			$this->snippets->mark_error( $snippet['id'], $result->get_error_message() );
			return $result;
		}
		return rest_ensure_response( $result );
	}

	public function publish_snippet( WP_REST_Request $request ) {
		$snippet = $this->snippets->get_snippet( intval( $request['id'] ), true );
		if ( ! $snippet ) {
			return new WP_Error( 'not_found', __( 'Snippet not found.', 'niwa-ai' ), array( 'status' => 404 ) );
		}
		$valid = $this->validator->validate( $snippet );
		if ( is_wp_error( $valid ) ) {
			$this->snippets->mark_error( $snippet['id'], $valid->get_error_message() );
			return $valid;
		}
		$written = $this->filesystem->write_snippet( $snippet, 'prod' );
		if ( is_wp_error( $written ) ) {
			$this->snippets->mark_error( $snippet['id'], $written->get_error_message() );
			return $written;
		}

		return rest_ensure_response(
			array(
				'snippet' => $this->snippets->mark_published( $snippet['id'] ),
				'path'    => isset( $written['path'] ) ? $written['path'] : '',
			)
		);
	}

	private function snippet_type_for_template( $template ) {
		$mode = isset( $template['output_mode'] ) ? sanitize_key( (string) $template['output_mode'] ) : 'shortcode';
		if ( 'admin_snippet' === $mode ) {
			return Niwa_AI_Template_Library_Types::TYPE_WORDPRESS_ADMIN_SNIPPET;
		}
		if ( 'elementor_widget' === $mode ) {
			return Niwa_AI_Template_Library_Types::TYPE_ELEMENTOR_WIDGET;
		}
		if ( 'visual_app' === $mode ) {
			return Niwa_AI_Template_Library_Types::TYPE_VISUAL_APP;
		}
		return Niwa_AI_Template_Library_Types::TYPE_SHORTCODE;
	}
}
