<?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\Contracts\ConfigRepositoryInterface;
use APD\PostTypes\ProductConfigPostType;
use APD\Support\ConfigMetaSanitizer;
use APD\Support\MetaKeys;

defined('ABSPATH') || exit;

class ProductConfigRepository implements ConfigRepositoryInterface
{
    private array $metaKeys;

    public function __construct()
    {
        // Keep the legacy UI payload exportable while covering every v2 state key.
        $this->metaKeys = array_values(array_unique(array_merge(
            MetaKeys::productConfigKeys(),
            ['_apd_ui']
        )));
    }

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

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

        $meta = [
            'ID' => $post->ID,
            'title' => $post->post_title,
            'slug' => $post->post_name,
            'status' => $post->post_status,
            'linkedProducts' => $this->linkedProducts($post->ID),
        ];
        foreach ($this->metaKeys as $key) {
            $meta[$key] = (string) get_post_meta($post->ID, $key, true);
        }

        return $meta;
    }

    public function allForSelect() : array
    {
        $posts = get_posts([
            'post_type' => ProductConfigPostType::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. */ __('Config #%d', 'asuka-product-designer'), (int) $post->ID),
            ];
        }, $posts);
    }

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

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

        return [
            'schema' => 'apd-product-config',
            'version' => ASUKA_PRODUCT_DESIGNER_VERSION,
            'generatedAt' => current_time('mysql'),
            'post' => [
                'id' => $config['ID'],
                'title' => $config['title'],
                'slug' => $config['slug'],
                'status' => $config['status'],
            ],
            'meta' => array_intersect_key($config, array_flip($this->metaKeys)),
        ];
    }

    public function import(array $payload, int $existingId = 0) : int
    {
        $postData = $payload['post'] ?? [];
        $meta = is_array($payload['meta'] ?? null) ? $payload['meta'] : [];

        $postarr = [
            'post_type' => ProductConfigPostType::TYPE,
            'post_status' => $this->sanitizePostStatus((string) ($postData['status'] ?? 'draft')),
            'post_title' => sanitize_text_field((string) ($postData['title'] ?? __('Imported config', 'asuka-product-designer'))),
            'post_name' => sanitize_title((string) ($postData['slug'] ?? '')),
        ];

        if ($existingId > 0) {
            $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) || ! $result) {
            return 0;
        }

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

        return (int) $result;
    }

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

        $query = new \WP_Query([
            'post_type' => 'product',
            'post_status' => ['publish', 'draft', 'private'],
            'posts_per_page' => 12,
            'meta_key' => '_apd_custom_product_id', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- Product bindings are stored as post metadata by the WooCommerce integration contract.
            'meta_value' => $configId, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value -- The bounded query returns at most twelve linked products.
            'fields' => 'ids',
            'no_found_rows' => true,
        ]);

        $items = [];
        foreach ($query->posts as $productId) {
            $items[] = [
                'id' => (int) $productId,
                'title' => get_the_title((int) $productId),
                'editUrl' => get_edit_post_link((int) $productId, ''),
            ];
        }

        return $items;
    }

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

}
