<?php
/**
 * Export current page / section / theme part as user template.
 *
 * @package AuraBuilder
 */

declare(strict_types=1);

namespace AuraBuilder\Templates;

use AuraBuilder\Document\DocumentSanitizer;
use AuraBuilder\Storage\DocumentRepository;
use AuraBuilder\Theme\ThemeBuilder;

final class TemplateExporter {

	/**
	 * @param array<string, mixed> $args
	 * @return array<string, mixed>|\WP_Error
	 */
	public function export( array $args ) {
		$scope = sanitize_key( (string) ( $args['scope'] ?? 'page' ) );
		$name  = sanitize_text_field( (string) ( $args['name'] ?? '' ) );
		if ( $name === '' ) {
			$name = 'Meu template ' . gmdate( 'Y-m-d H:i' );
		}

		$repo = new TemplateRepository();

		if ( $scope === 'header' || $scope === 'footer' ) {
			$part = ThemeBuilder::get_part( $scope );
			$doc  = is_array( $part['document'] ?? null ) ? $part['document'] : null;
			if ( ! $doc ) {
				return new \WP_Error( 'ab_export', 'Header/Footer vazio.', array( 'status' => 400 ) );
			}
			return $repo->save_user(
				array(
					'name'     => $name,
					'type'     => $scope,
					'category' => 'custom',
					'document' => $doc,
					'subtype'  => $scope,
				)
			);
		}

		if ( $scope === 'page' ) {
			$post_id = (int) ( $args['postId'] ?? $args['post_id'] ?? 0 );
			if ( $post_id <= 0 || ! current_user_can( 'edit_post', $post_id ) ) {
				// Allow raw document from editor body.
				$doc = is_array( $args['document'] ?? null ) ? $args['document'] : null;
				if ( ! $doc ) {
					return new \WP_Error( 'ab_export', 'Página inválida.', array( 'status' => 400 ) );
				}
			} else {
				$doc = ( new DocumentRepository() )->get( $post_id )->to_array();
			}
			if ( is_array( $args['document'] ?? null ) ) {
				$doc = $args['document'];
			}
			return $repo->save_user(
				array(
					'name'     => $name,
					'type'     => TemplateTypes::PAGE,
					'category' => 'custom',
					'document' => $doc,
					'subtype'  => 'page',
				)
			);
		}

		// Section / component: document fragment or full doc + nodeId subtree.
		$doc_in  = is_array( $args['document'] ?? null ) ? $args['document'] : null;
		$node_id = sanitize_text_field( (string) ( $args['nodeId'] ?? $args['node_id'] ?? '' ) );
		if ( ! $doc_in ) {
			return new \WP_Error( 'ab_export', 'Documento da seção ausente.', array( 'status' => 400 ) );
		}
		if ( $node_id !== '' ) {
			$doc_in = $this->extract_subtree( $doc_in, $node_id );
			if ( is_wp_error( $doc_in ) ) {
				return $doc_in;
			}
		}
		return $repo->save_user(
			array(
				'name'     => $name,
				'type'     => TemplateTypes::COMPONENT,
				'category' => sanitize_key( (string) ( $args['category'] ?? 'section' ) ),
				'document' => $doc_in,
				'subtype'  => sanitize_key( (string) ( $args['subtype'] ?? 'section' ) ),
			)
		);
	}

	/**
	 * @param array<string, mixed> $doc
	 * @return array<string, mixed>|\WP_Error
	 */
	private function extract_subtree( array $doc, string $node_id ) {
		$nodes = $doc['nodes'] ?? null;
		if ( ! is_array( $nodes ) || ! isset( $nodes[ $node_id ] ) ) {
			return new \WP_Error( 'ab_export_node', 'Elemento não encontrado.', array( 'status' => 400 ) );
		}
		$keep = array();
		$stack = array( $node_id );
		while ( $stack ) {
			$id = array_pop( $stack );
			if ( isset( $keep[ $id ] ) || ! isset( $nodes[ $id ] ) ) {
				continue;
			}
			$keep[ $id ] = $nodes[ $id ];
			$children    = $nodes[ $id ]['children'] ?? array();
			if ( is_array( $children ) ) {
				foreach ( $children as $cid ) {
					$stack[] = (string) $cid;
				}
			}
		}
		// Wrap in a root so DocumentSanitizer accepts it.
		$root_id = 'root_export';
		$root    = array(
			'id'       => $root_id,
			'type'     => 'root',
			'parentId' => null,
			'children' => array( $node_id ),
			'settings' => array(
				'content_width' => 'full',
				'max_width'     => '1200px',
			),
			'styles'   => array(
				'desktop' => array(),
				'tablet'  => array(),
				'mobile'  => array(),
			),
			'attributes' => array(),
			'classes'    => array(),
			'locked'     => false,
			'hidden'     => false,
		);
		// Detach subtree root from old parent.
		if ( isset( $keep[ $node_id ] ) && is_array( $keep[ $node_id ] ) ) {
			$keep[ $node_id ]['parentId'] = $root_id;
		}
		$keep[ $root_id ] = $root;
		return array(
			'id'       => 'export_' . wp_generate_password( 6, false, false ),
			'type'     => 'page',
			'version'  => '1',
			'settings' => array(
				'showHeader' => false,
				'showFooter' => false,
			),
			'rootId'   => $root_id,
			'nodes'    => $keep,
			'metadata' => array(
				'kind' => 'component',
			),
		);
	}
}
