<?php

// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedNamespaceFound -- APD is the established namespace shared with the Pro add-on and retained for backward compatibility.
namespace APD\Repositories;

use APD\PostTypes\TemplatePostType;
use APD\Support\ConfigMetaSanitizer;
use APD\Support\MetaKeys;

defined('ABSPATH') || exit;

class TemplateRepository
{
    private array $metaKeys;

    public function __construct()
    {
        $this->metaKeys = array_values(array_unique(array_merge(
            MetaKeys::templateKeys(),
            ['_apd_ui']
        )));
    }

    public function allForSelect() : array
    {
        $posts = get_posts([
            'post_type' => TemplatePostType::TYPE,
            'post_status' => ['publish', 'draft', 'private'],
            'posts_per_page' => -1,
            'orderby' => 'title',
            'order' => 'ASC',
        ]);

        return array_map(static function ($post) : array {
            return [
                'id' => (int) $post->ID,
                'title' => $post->post_title ?: sprintf(/* translators: Placeholder values are populated from the current Asuka Designer record. */ __('Template #%d', 'asuka-product-designer'), (int) $post->ID),
            ];
        }, $posts);
    }

    public function getMetaPayload(int $id) : array
    {
        if ($id <= 0) {
            return [];
        }

        $post = get_post($id);
        if (! $post || $post->post_type !== TemplatePostType::TYPE) {
            return [];
        }

        $payload = [
            'ID' => (int) $post->ID,
            'title' => (string) $post->post_title,
            'slug' => (string) $post->post_name,
            'status' => (string) $post->post_status,
        ];

        foreach ($this->metaKeys as $key) {
            $payload[$key] = (string) get_post_meta($post->ID, $key, true);
        }

        return $payload;
    }

    public function metaKeys() : array
    {
        return $this->metaKeys;
    }

    public function export(int $id) : array
    {
        $template = $this->getMetaPayload($id);
        if ($template === []) {
            return [];
        }

        return [
            'schema' => 'apd-template',
            'version' => ASUKA_PRODUCT_DESIGNER_VERSION,
            'post' => [
                'id' => (int) $template['ID'],
                'title' => (string) $template['title'],
                'slug' => (string) $template['slug'],
                'status' => (string) $template['status'],
            ],
            'meta' => array_intersect_key($template, array_flip($this->metaKeys)),
        ];
    }

    public function import(array $payload, int $existingId = 0) : int
    {
        $postData = is_array($payload['post'] ?? null) ? $payload['post'] : [];
        $meta = is_array($payload['meta'] ?? null) ? $payload['meta'] : [];
        $postarr = [
            'post_type' => TemplatePostType::TYPE,
            'post_status' => $this->sanitizePostStatus((string) ($postData['status'] ?? 'draft')),
            'post_title' => sanitize_text_field((string) ($postData['title'] ?? __('Imported template', 'asuka-product-designer'))),
            'post_name' => sanitize_title((string) ($postData['slug'] ?? '')),
        ];
        if ($existingId > 0 && get_post_type($existingId) === TemplatePostType::TYPE) {
            $postarr['ID'] = $existingId;
            $result = wp_update_post(wp_slash($postarr), true);
        } else {
            $result = wp_insert_post(wp_slash($postarr), true);
        }
        if (is_wp_error($result) || (int) $result <= 0) {
            return 0;
        }

        foreach ($this->metaKeys as $key) {
            if (! array_key_exists($key, $meta)) {
                continue;
            }
            update_post_meta((int) $result, $key, wp_slash(ConfigMetaSanitizer::sanitize($key, $meta[$key])));
        }

        return (int) $result;
    }

    private function sanitizePostStatus(string $status) : string
    {
        $status = sanitize_key($status);
        return in_array($status, ['publish', 'draft', 'private'], true) ? $status : 'draft';
    }
}
