<?php
/**
 * Shop-template and WooCommerce element discovery inside Bricks.
 *
 * @package LolaCoreForBricks
 */

declare(strict_types=1);

namespace LolaCoreForBricks\Gateways;

use LolaCoreForBricks\Support\BricksMetaKeys;
use LolaCoreForBricks\Support\WooProductCatalog;
use LolaCoreForBricks\Support\WooShopTemplates;

/**
 * Reads existing shop templates and which WooCommerce elements the site already uses.
 */
class WooSurfaceGateway
{
    /**
     * @return array<string, mixed>
     */
    public function getSurface(): array
    {
        $templates = $this->shopTemplates();
        $present   = [];
        $missing   = [];

        foreach (WooShopTemplates::kinds() as $kind => $spec) {
            $matches = $templates[$spec['bricks_type']] ?? [];
            if ($matches === []) {
                $missing[] = [
                    'kind'        => $kind,
                    'bricks_type' => $spec['bricks_type'],
                    'label'       => $spec['label'],
                ];
                continue;
            }

            foreach ($matches as $row) {
                $present[] = $row + ['kind' => $kind, 'label' => $spec['label']];
            }
        }

        $used = $this->usedElements();

        return [
            'templates' => [
                'present' => $present,
                'missing' => $missing,
            ],
            'extra_woo_templates' => $this->extraWooTemplates($templates),
            'elements_used'       => $used,
            'catalog_total'       => WooProductCatalog::count(),
        ];
    }

    /**
     * @return array<string, array<int, array<string, mixed>>>
     */
    private function shopTemplates(): array
    {
        $grouped = [];
        foreach ($this->templatePosts() as $post) {
            $id   = (int) ($post->ID ?? 0);
            $type = $this->templateType($id);
            if ($type === '' || !str_starts_with($type, 'wc_')) {
                continue;
            }

            $settings   = get_post_meta($id, BricksMetaKeys::TEMPLATE_SETTINGS, true);
            $conditions = is_array($settings) && is_array($settings['templateConditions'] ?? null)
                ? $settings['templateConditions']
                : [];

            $grouped[$type][] = [
                'template_id' => $id,
                'title'       => (string) get_the_title($id),
                'type'        => $type,
                'status'      => (string) ($post->post_status ?? 'publish'),
                'conditions'  => $conditions,
            ];
        }

        return $grouped;
    }

    /**
     * @param array<string, array<int, array<string, mixed>>> $grouped
     * @return array<int, array<string, mixed>>
     */
    private function extraWooTemplates(array $grouped): array
    {
        $required = WooShopTemplates::bricksTypes();
        $extra    = [];
        foreach ($grouped as $type => $rows) {
            if (in_array($type, $required, true)) {
                continue;
            }

            foreach ($rows as $row) {
                $extra[] = $row;
            }
        }

        return $extra;
    }

    /**
     * @return array<int, array<string, mixed>>
     */
    private function usedElements(): array
    {
        $catalog = WooProductCatalog::names();
        $counts  = [];
        $pages   = [];

        foreach ($this->candidatePostIds() as $postId) {
            foreach (BricksMetaKeys::pageMetaKeyToArea() as $metaKey => $area) {
                $elements = get_post_meta($postId, $metaKey, true);
                if (!is_array($elements)) {
                    continue;
                }

                foreach ($elements as $element) {
                    if (!is_array($element)) {
                        continue;
                    }

                    $name = (string) ($element['name'] ?? '');
                    if (!isset($catalog[$name])) {
                        continue;
                    }

                    $counts[$name] = ($counts[$name] ?? 0) + 1;
                    $pages[$name][$postId] = true;
                    unset($area);
                }
            }
        }

        $used = [];
        foreach ($counts as $name => $count) {
            $used[] = [
                'name'  => $name,
                'label' => $catalog[$name],
                'group' => WooProductCatalog::groupFor($name),
                'count' => $count,
                'pages' => count($pages[$name] ?? []),
            ];
        }

        usort($used, static fn (array $a, array $b): int => $b['count'] <=> $a['count']);

        return $used;
    }

    /**
     * @return array<int, object>
     */
    private function templatePosts(): array
    {
        if (function_exists('get_posts')) {
            return get_posts([
                'post_type'      => BricksMetaKeys::TEMPLATE_POST_TYPE,
                'post_status'    => ['publish', 'draft', 'private'],
                'posts_per_page' => -1,
                'orderby'        => 'title',
                'order'          => 'ASC',
            ]);
        }

        $items = [];
        foreach ($GLOBALS['_test_posts'] ?? [] as $id => $data) {
            if (!is_array($data) || ($data['post_type'] ?? '') !== BricksMetaKeys::TEMPLATE_POST_TYPE) {
                continue;
            }

            $items[] = (object) ($data + ['ID' => (int) $id]);
        }

        return $items;
    }

    /**
     * @return int[]
     */
    private function candidatePostIds(): array
    {
        $ids = [];
        if (function_exists('get_posts')) {
            foreach (get_posts([
                'post_type'      => 'any',
                'post_status'    => ['publish', 'draft', 'private'],
                'posts_per_page' => -1,
            ]) as $post) {
                $ids[] = (int) ($post->ID ?? 0);
            }
        }

        foreach (array_keys($GLOBALS['_test_posts'] ?? []) as $id) {
            $ids[] = (int) $id;
        }

        return array_values(array_unique(array_filter($ids)));
    }

    private function templateType(int $templateId): string
    {
        $type = get_post_meta($templateId, BricksMetaKeys::TEMPLATE_TYPE, true);

        return is_string($type) ? $type : '';
    }
}
