<?php
/**
 * Core + user template listing and CRUD (user via option).
 *
 * @package AuraBuilder
 */

declare(strict_types=1);

namespace AuraBuilder\Templates;

use AuraBuilder\Document\DocumentSanitizer;

final class TemplateRepository {

	/**
	 * @return list<array<string, mixed>>
	 */
	public function list( array $args = array() ): array {
		$type   = isset( $args['type'] ) ? sanitize_key( (string) $args['type'] ) : '';
		$source = isset( $args['source'] ) ? sanitize_key( (string) $args['source'] ) : '';
		$cat    = isset( $args['category'] ) ? sanitize_key( (string) $args['category'] ) : '';
		$q      = isset( $args['q'] ) ? mb_strtolower( trim( (string) $args['q'] ) ) : '';

		$items = array();
		if ( $source !== TemplateTypes::SOURCE_USER ) {
			$items = array_merge( $items, CoreLibrary::list_templates( $type ?: null ) );
		}
		if ( $source !== TemplateTypes::SOURCE_CORE ) {
			foreach ( $this->user_all() as $tpl ) {
				if ( $type && ( $tpl['type'] ?? '' ) !== $type ) {
					continue;
				}
				$items[] = $tpl;
			}
		}

		$out = array();
		foreach ( $items as $tpl ) {
			if ( $cat && sanitize_key( (string) ( $tpl['category'] ?? '' ) ) !== $cat ) {
				continue;
			}
			if ( $q !== '' ) {
				$hay = mb_strtolower(
					(string) ( $tpl['name'] ?? '' ) . ' ' .
					(string) ( $tpl['category'] ?? '' ) . ' ' .
					implode( ' ', is_array( $tpl['tags'] ?? null ) ? $tpl['tags'] : array() )
				);
				if ( mb_strpos( $hay, $q ) === false ) {
					continue;
				}
			}
			// Strip heavy document for list (except when requested).
			if ( empty( $args['with_document'] ) ) {
				$light = $tpl;
				unset( $light['document'], $light['_file'], $light['path'] );
				if ( isset( $light['manifest'] ) && is_array( $light['manifest'] ) ) {
					// keep manifest summary fields only in meta
				}
				$out[] = $light;
			} else {
				$out[] = $tpl;
			}
		}
		return $out;
	}

	/**
	 * @return array<string, mixed>|null
	 */
	public function get( string $id ): ?array {
		$id = sanitize_text_field( $id );
		if ( $id === '' ) {
			return null;
		}
		// User first (can override id collision carefully).
		foreach ( $this->user_all() as $tpl ) {
			if ( (string) ( $tpl['id'] ?? '' ) === $id ) {
				return $tpl;
			}
		}
		return CoreLibrary::get_template( $id );
	}

	/**
	 * @param array<string, mixed> $data
	 * @return array<string, mixed>|\WP_Error
	 */
	public function save_user( array $data ) {
		$name = sanitize_text_field( (string) ( $data['name'] ?? '' ) );
		$type = sanitize_key( (string) ( $data['type'] ?? TemplateTypes::COMPONENT ) );
		if ( $name === '' ) {
			return new \WP_Error( 'ab_tpl_name', 'Nome do template é obrigatório.', array( 'status' => 400 ) );
		}
		if ( ! TemplateTypes::is_valid( $type ) || $type === TemplateTypes::KIT ) {
			// Kits only from core files for now.
			if ( $type === TemplateTypes::KIT ) {
				return new \WP_Error( 'ab_tpl_type', 'Kits só via biblioteca core (MVP).', array( 'status' => 400 ) );
			}
			$type = TemplateTypes::COMPONENT;
		}

		$doc_in = $data['document'] ?? null;
		if ( ! is_array( $doc_in ) || empty( $doc_in['nodes'] ) ) {
			return new \WP_Error( 'ab_tpl_doc', 'Documento inválido.', array( 'status' => 400 ) );
		}
		$doc = DocumentSanitizer::sanitize( $doc_in )->to_array();

		$id = sanitize_key( (string) ( $data['id'] ?? '' ) );
		if ( $id === '' || str_starts_with( $id, 'core-' ) ) {
			$id = 'user_' . wp_generate_password( 10, false, false );
		}

		$tpl = array(
			'id'        => $id,
			'type'      => $type,
			'subtype'   => sanitize_key( (string) ( $data['subtype'] ?? '' ) ),
			'name'      => $name,
			'category'  => sanitize_key( (string) ( $data['category'] ?? 'custom' ) ),
			'tags'      => $this->sanitize_tags( $data['tags'] ?? array() ),
			'version'   => '1.0.0',
			'source'    => TemplateTypes::SOURCE_USER,
			'thumbnail' => esc_url_raw( (string) ( $data['thumbnail'] ?? '' ) ),
			'document'  => $doc,
			'meta'      => array(
				'author'     => wp_get_current_user()->display_name ?: 'User',
				'responsive' => true,
				'createdAt'  => gmdate( 'c' ),
				'updatedAt'  => gmdate( 'c' ),
			),
		);

		$all = $this->user_all();
		$found = false;
		foreach ( $all as $i => $existing ) {
			if ( (string) ( $existing['id'] ?? '' ) === $id ) {
				$tpl['meta']['createdAt'] = $existing['meta']['createdAt'] ?? $tpl['meta']['createdAt'];
				$all[ $i ] = $tpl;
				$found = true;
				break;
			}
		}
		if ( ! $found ) {
			$all[] = $tpl;
		}
		update_option( TemplateTypes::USER_OPTION, $all, false );
		return $tpl;
	}

	public function delete_user( string $id ): bool {
		$id  = sanitize_text_field( $id );
		$all = $this->user_all();
		$new = array();
		$ok  = false;
		foreach ( $all as $tpl ) {
			if ( (string) ( $tpl['id'] ?? '' ) === $id ) {
				$ok = true;
				continue;
			}
			$new[] = $tpl;
		}
		if ( $ok ) {
			update_option( TemplateTypes::USER_OPTION, $new, false );
		}
		return $ok;
	}

	/**
	 * @return list<array<string, mixed>>
	 */
	public function user_all(): array {
		$raw = get_option( TemplateTypes::USER_OPTION, null );
		if ( ! is_array( $raw ) ) {
			$raw = get_option( TemplateTypes::USER_OPTION_LEGACY, array() );
		}
		if ( ! is_array( $raw ) ) {
			return array();
		}
		$out = array();
		foreach ( $raw as $tpl ) {
			if ( ! is_array( $tpl ) || empty( $tpl['id'] ) ) {
				continue;
			}
			$tpl['source'] = TemplateTypes::SOURCE_USER;
			$out[]         = $tpl;
		}
		return $out;
	}

	/**
	 * @param mixed $tags
	 * @return list<string>
	 */
	private function sanitize_tags( $tags ): array {
		if ( is_string( $tags ) ) {
			$tags = preg_split( '/[\s,;]+/', $tags ) ?: array();
		}
		if ( ! is_array( $tags ) ) {
			return array();
		}
		$out = array();
		foreach ( $tags as $t ) {
			$s = sanitize_key( (string) $t );
			if ( $s !== '' ) {
				$out[] = $s;
			}
		}
		return array_values( array_unique( $out ) );
	}
}
