<?php

$app = $this->app;

return [
    'name' => 'collection',
    'label' => 'Collection',
    'icon' => 'content:assets/icons/collection.svg',
    'group' => 'Content',
    'data' => function() use($app) {

        $models = array_filter($app->module('content')->models(), fn($model) => in_array($model['type'], ['collection', 'tree']));

        return [
            [
                'name' => 'collection',
                'type' => 'options-linkModel',
                'info' => 'Content collection to connect to',
                'opts' => [
                    'models' => $models,
                    'showGoto' => true
                ],
                'group' => 'Collection',
                'required' => true
            ],

            [
                'name' => 'slugField',
                'type' => 'text',
                'label' => 'Slug field',
                'info' => 'Slug field to resolve collection item',
                'opts' => [
                    'placeholder' => '_id'
                ],
                'group' => 'Collection'
            ],

            [
                'name' => 'limit',
                'type' => 'number',
                'label' => 'Items limit',
                'info' => 'Number of items to be returned by default',
                'opts' => [
                    'placeholder' => '20',
                ],
                'group' => 'Collection'
            ],

            [
                'name' => 'filter',
                'type' => 'object',
                'label' => 'Items filter',
                'info' => 'Filter returned collection items',
                'opts' => [
                    'asString' => true,
                ],
                'group' => 'Collection'
            ],

            [
                'name' => 'lstFields',
                'type' => 'object',
                'label' => 'List Fields',
                'info' => 'Returned fields for list page',
                'opts' => [
                    'asString' => true,
                    'height' => 100
                ],
                'group' => 'List page'
            ],

            [
                'name' => 'sort',
                'type' => 'object',
                'label' => 'Sort',
                'info' => 'Sort settings collection items',
                'opts' => [
                    'asString' => true,
                    'height' => 100
                ],
                'group' => 'Collection'
            ],

            [
                'name' => 'layoutList',
                'type' => 'set',
                'label' => 'List Layout',
                'info' => 'Additional layout components to display before and after list content',
                'i18n' => true,
                'group' => 'List page',
                'opts' => [
                    'fields' =>  [
                        [
                            'name' => 'before',
                            'type' => 'layout',
                            'label' => 'Before',
                            'info' => 'Layout before list content',
                        ],
                        [
                            'name' => 'after',
                            'type' => 'layout',
                            'label' => 'After',
                            'info' => 'Layout after list content',
                        ]
                    ],
                    'mode' => 'tabs'
                ]
            ],

            [
                'name' => 'layoutDetail',
                'type' => 'set',
                'label' => 'Detail Layout',
                'info' => 'Additional layout components to display before and after detail content',
                'i18n' => true,
                'group' => 'Detail page',
                'opts' => [
                    'fields' =>  [
                        [
                            'name' => 'before',
                            'type' => 'layout',
                            'label' => 'Before',
                            'info' => 'Layout before detail content',
                        ],
                        [
                            'name' => 'after',
                            'type' => 'layout',
                            'label' => 'After',
                            'info' => 'Layout after detail content',
                        ]
                    ],
                    'mode' => 'tabs'
                ]
            ],
        ];
    },

    'resolve' => function($page, array $options = []) use($app) {

        $collection = $page['data']['collection'] ?? null;
        $slugField  = $page['data']['slugField'] ?? null;

        if (!$collection || !$app->module('content')->exists($collection)) {
            return false;
        }

        if (!$slugField) {
            $slugField = '_id';
        }

        if ($slugField != '_id' && $options['locale'] != 'default') {

            $model = $app->module('content')->model($collection);
            $fields = $model['fields'] ?? [];

            foreach ($fields as $field) {

                if ($field['name'] == $slugField) {

                    if ($field['i18n']) {
                        $slugField = "{$slugField}_{$options['locale']}";
                    }

                    break;
                }
            }
        }

        $item = $app->module('content')->item($collection, [
            '_state' => 1,
            "{$slugField}" => $options['params'][0]
        ], null);

        if (!$item) {
            return false;
        }

        $page['data']['item'] = $item;

        return $page;
    },

    'process' => function($page, $locale = 'default', $options = []) use ($app) {

        $collection = $page['data']['collection'] ?? null;
        $model = $collection ? $app->module('content')->model($collection) : null;
        $slugField = isset($page['data']['slugField']) && $page['data']['slugField'] ? $page['data']['slugField'] : '_id';
        $limit = $page['data']['limit'] ?? 20;

        if (!$collection || !$model) {
            return $page;
        }

        $filter = isset($page['data']['filter']) && $page['data']['filter'] !== 'null'
                  ? $page['data']['filter']
                  : ($model['type'] == 'tree' ? ['_pid' => null] : []);

        if (is_string($filter)) {

            try {
                $filter = json5_decode($filter, true);
            } catch (\Exception $e) {
                $filter = [];
            }
        }

        $sort = isset($page['data']['sort']) && $page['data']['sort'] !== 'null'
                ? $page['data']['sort']
                : ($model['type'] == 'tree' ? ['_o' => 1] : ['_created' => -1]);

        if (is_string($sort)) {

            try {
                $sort = json5_decode($sort, true);
            } catch (\Exception $e) {
                $sort = $model['type'] == 'tree' ? ['_o' => 1] : ['_created' => -1];
            }
        }

        $fields = isset($page['data']['lstFields']) && $page['data']['lstFields'] !== 'null'
                  ? $page['data']['lstFields']
                  : null;

        if (is_string($fields)) {

            try {
                $fields = json5_decode($fields, true);
            } catch (\Exception $e) {
                $fields = null;
            }
        }

        if (isset($page['data']['item'])) {

            // set index page as parent
            $parent = array_merge([], $page);
            unset($parent['data'], $parent['_parents'], $parent['_locale'], $parent['_routes']);
            $page['_parents'][] = $parent;

            foreach ($page['_routes'] as $loc => $route) {

                $slug = $page['data']['item']['_id'];

                if (isset($page['data']['item']["{$slugField}_{$loc}"]) || isset($page['data']['item']["{$slugField}"])) {
                    $slug = $page['data']['item']["{$slugField}_{$loc}"] ?? $page['data']['item']["{$slugField}"];
                }

                $page['_routes'][$loc] = "{$route}/{$slug}";
            }

            $page['data']['item'] = $app->helper('locales')->applyLocales($page['data']['item'], $locale);

            // update seo data if available
            foreach(['title', 'keywords', 'description'] as $key) {

                if (isset($page['data']['item']['seo'][$key]) && $page['data']['item']['seo'][$key]) {
                    $page['seo'][$key] = $page['data']['item']['seo'][$key];
                }
            }

            if (isset($page['data']['item']['name']) || isset($page['data']['item']['title'])) {
                $page['title'] = $page['data']['item'][isset($page['data']['item']['name']) ? 'name' : 'title'];
            }

            return $page;
        }

        $opts = [
            'fields' => $fields,
            'sort' => $sort,
            'limit' => $limit ? $limit : 20
        ];

        foreach (['filter', 'sort', 'fields', 'limit', 'skip', 'populate'] as $key) {
            if (!isset($options[$key])) continue;

            $opts[$key] = $options[$key];

            if (in_array($key, ['filter', 'fields', 'sort']) && is_string($options[$key])) {
                try {
                    $opts[$key] = json5_decode($opts[$key], true);
                } catch(\Throwable $e) {
                    unset($opts[$key]);
                }
            } elseif (in_array($key, ['limit', 'skip', 'populate']) && is_string($options[$key])) {
                $opts[$key] = intval($opts[$key]);
            }
        }

        if (!isset($opts['filter']) || !is_array($opts['filter'])) {
            $opts['filter'] = [];
        }

        $_filter = [
            ['_state' => 1]
        ];

        if (is_array($filter) && count($filter)) $_filter[] = $filter;
        if (is_array($opts['filter']) && count($opts['filter'])) $_filter[] = $opts['filter'];

        $opts['filter'] = ['$and' => $_filter];

        // find only items where mapped slug exists
        if ($slugField != '_id') {

            if ($locale != 'default') {

                $fields = $model['fields'] ?? [];

                foreach ($fields as $field) {

                    if ($field['name'] == $slugField) {

                        if ($field['i18n']) {
                            $slugField = "{$slugField}_{$locale}";
                        }
                        break;
                    }
                }
            }

            if (!isset($opts['filter']['$and'])) {
                $opts['filter']['$and'] = [];
            }

            $opts['filter']['$and'][] = ["{$slugField}" => ['$exists' => true]];
            $opts['filter']['$and'][] = ["{$slugField}" => ['$ne' => null]];
            $opts['filter']['$and'][] = ["{$slugField}" => ['$ne' => '']];
        }

        $items = $app->module('content')->items($collection, $opts);

        $routeKey = $locale == 'default' ? '_r' : "_r_{$locale}";
        $list = [];

        if (count($items)) {

            if ($slugField != '_id' && $locale != 'default') {

                $model = $app->module('content')->model($collection);
                $fields = $model['fields'] ?? [];

                foreach ($fields as $field) {

                    if ($field['name'] == $slugField) {

                        if ($field['i18n']) {
                            $slugField = "{$slugField}_{$locale}";
                        }

                        break;
                    }
                }
            }

            foreach ($items as $item) {

                $list[] = [
                    'item' => $item,
                    'route' => isset($item[$slugField]) ? $page[$routeKey].'/'.$item[$slugField] : null
                ];
            }
        }

        $page['data']['items'] = $list;

        $page['_pagination'] = [];

        if (isset($opts['limit'])) {
            $page['_pagination']['total'] = $app->module('content')->count($collection, $opts['filter'] ?? []);
            $page['_pagination']['limit'] = $opts['limit'];
            $page['_pagination']['page']  = ceil(intval($opts['skip'] ?? 0) / $opts['limit']) + 1;
            $page['_pagination']['pages'] = ceil($page['_pagination']['total'] / $opts['limit']);
        } else {
            $page['_pagination']['total'] = count($list);
            $page['_pagination']['page'] = 1;
            $page['_pagination']['pages'] = 1;
        }

        return $page;
    }
];
