<?php
/**
 * Template service class.
 *
 * Handles fetching, caching, and listing both bundled and cloud templates.
 *
 * @package    100Prints
 */

class Hundred_Prints_Template_Service {

	/**
	 * Get bundled templates only.
	 *
	 * @return array List of bundled templates.
	 */
	public function get_bundled_templates() {
		$bundled = hundred_prints_get_bundled_templates();
		foreach ( $bundled as &$b ) {
			$b['source'] = 'bundled';
			
			// Ensure thumbnail is a full URL
			if ( ! empty( $b['thumbnail'] ) && ! wp_http_validate_url( $b['thumbnail'] ) ) {
				// Clean up leading slashes in case they put "/assets/..."
				$path = ltrim( $b['thumbnail'], '/' );
				
				// If they just put the filename, point it to the thumbnails folder
				if ( strpos( $path, '/' ) === false ) {
					$path = 'assets/images/thumbnails/' . $path;
				}
				
				$b['thumbnail'] = HUNDRED_PRINTS_URL . $path;
			}
		}
		return $bundled;
	}

	/**
	 * Get synced cloud templates only.
	 *
	 * @return array List of cloud templates.
	 */
	public function get_cloud_templates() {
		$cloud = get_option( '100p_template_index', [] );
		if ( ! is_array( $cloud ) ) {
			$cloud = [];
		}
		foreach ( $cloud as &$c ) {
			$c['source'] = 'cloud';
		}
		return $cloud;
	}

	/**
	 * Get all templates (merged bundled and cloud).
	 *
	 * @return array List of all templates with metadata.
	 */
	public function get_all_templates() {
		$bundled = $this->get_bundled_templates();
		$cloud = $this->get_cloud_templates();

		// Merge lists (cloud templates overwrite bundled templates of the same ID)
		$merged = [];
		foreach ( $bundled as $b_item ) {
			$merged[ $b_item['id'] ] = $b_item;
		}
		foreach ( $cloud as $c_item ) {
			$merged[ $c_item['id'] ] = $c_item;
		}

		return array_values( $merged );
	}

	/**
	 * Get a specific template by ID.
	 *
	 * @param string $id Template ID.
	 * @return array|false Template details or false on failure.
	 */
	public function get_template( $id ) {
		$id = preg_replace( '/[^a-zA-Z0-9_-]/', '', $id );
		
		// 1. Check if it is a bundled template
		$bundled_data = hundred_prints_get_bundled_template_data( $id );
		if ( $bundled_data ) {
			$bundled_data['source'] = 'bundled';
			return $bundled_data;
		}

		// 2. Check if API Key exists before trying cloud fetching
		$conn_service = new Hundred_Prints_Connection_Service();
		$api_key = $conn_service->get_key();

		if ( empty( $api_key ) ) {
			return new WP_Error( '100prints_no_api_key', 'API Secret Key not connected.', [ 'status' => 401 ] );
		}

		// 3. Check fresh transient cache
		$transient_key = "100p_template_{$id}";
		$cached = get_transient( $transient_key );
		if ( $cached !== false ) {
			$cached['source'] = 'cloud';
			return $cached;
		}

		// 3. Check persistent option cache (stale fallback)
		$option_key = "100p_template_cache_{$id}";
		$stale = get_option( $option_key, false );
		if ( $stale ) {
			// Trigger background refresh in single cron event
			wp_schedule_single_event( time(), 'hundred_prints_refresh_template', [ $id ] );
			$stale['source'] = 'cloud';
			return $stale;
		}

		// 4. Fallback to immediate live API fetch
		$live_data = $this->fetch_template_from_api( $id );
		if ( $live_data ) {
			$live_data['source'] = 'cloud';
			return $live_data;
		}

		return false;
	}

	/**
	 * Sync cloud templates index and options cache.
	 *
	 * @return array Synchronized template count or error string.
	 */
	public function sync_cloud_templates() {
		$conn_service = new Hundred_Prints_Connection_Service();
		$api_key = $conn_service->get_key();

		if ( empty( $api_key ) ) {
			return [ 'error' => 'API Secret Key not connected.' ];
		}

		$api_url = $conn_service->get_api_base_url() . '/templates';

		$response = wp_remote_get( $api_url, [
			'headers' => [
				'Authorization' => 'Bearer ' . $api_key,
				'Content-Type'  => 'application/json',
			],
			'timeout' => 20,
		] );

		if ( is_wp_error( $response ) ) {
			update_option( '100p_last_sync_error', $response->get_error_message() );
			return [ 'error' => 'Sync failed: ' . $response->get_error_message() ];
		}

		$status = wp_remote_retrieve_response_code( $response );
		if ( $status !== 200 ) {
			$msg = 'Sync failed with API status ' . $status;
			update_option( '100p_last_sync_error', $msg );
			return [ 'error' => $msg ];
		}

		$body = wp_remote_retrieve_body( $response );
		$templates = json_decode( $body, true );

		if ( ! is_array( $templates ) ) {
			update_option( '100p_last_sync_error', 'Invalid API response format' );
			return [ 'error' => 'Invalid templates manifest format.' ];
		}

		// Build templates index
		$index = [];
		foreach ( $templates as $t ) {
			$index[] = [
				'id'        => sanitize_key( $t['id'] ),
				'name'      => sanitize_text_field( $t['name'] ),
				'category'  => sanitize_key( $t['category'] ),
				'variables' => is_array( $t['variables'] ) ? array_map( 'sanitize_text_field', $t['variables'] ) : [],
				'source'    => 'cloud',
			];
		}

		// Update option index
		update_option( '100p_template_index', $index );
		update_option( '100p_last_sync_time', current_time( 'timestamp' ) );
		delete_option( '100p_last_sync_error' );

		// Clear stale/corrupted template detail cache during sync
		foreach ( $templates as $t ) {
			$t_id = isset( $t['id'] ) ? sanitize_key( $t['id'] ) : '';
			if ( '' === $t_id ) {
				continue;
			}
			delete_option( '100p_template_cache_' . $t_id );
			delete_transient( '100p_template_' . $t_id );
		}

		return [ 'count' => count( $index ) ];
	}

	/**
	 * Fetch template JSON from the API.
	 *
	 * @param string $id Template ID.
	 * @return array|false The template details, or false.
	 */
	public function fetch_template_from_api( $id ) {
		$conn_service = new Hundred_Prints_Connection_Service();
		$api_key = $conn_service->get_key();

		if ( empty( $api_key ) ) {
			return false;
		}

		$api_url = $conn_service->get_api_base_url() . "/template/{$id}";

		$response = wp_remote_get( $api_url, [
			'headers' => [
				'Authorization' => 'Bearer ' . $api_key,
				'Content-Type'  => 'application/json',
			],
			'timeout' => 15,
		] );

		if ( is_wp_error( $response ) ) {
			return false;
		}

		$status = wp_remote_retrieve_response_code( $response );
		if ( $status !== 200 ) {
			return false;
		}

		$body = wp_remote_retrieve_body( $response );
		$template = json_decode( $body, true );

		if ( ! is_array( $template ) ) {
			return false;
		}

		// Cache template data
		update_option( "100p_template_cache_{$id}", $template );
		$settings = hundred_prints_get_settings();
		$ttl = min( 168, max( 1, absint( $settings['cache_ttl_hours'] ) ) ) * HOUR_IN_SECONDS;
		set_transient( "100p_template_{$id}", $template, $ttl );

		return $template;
	}
}
