<?php

namespace Shm\ShmTypes\Utils;

use Shm\Collection\Collection;
use Shm\ShmDB\mDB;
use Shm\ShmTypes\PhoneType;
use Shm\ShmTypes\StringType;
use Shm\ShmTypes\StructureType;
use Shm\ShmUtils\ShmInit;
use Shm\ShmUtils\ShmManticore;

class SearchStringUpdate
{



    public static function runUpdate($limit = 10, $collection = null)
    {

        $classes = [];

        if (is_dir(ShmInit::$rootDir . '/app/Collections')) {



            $files = scandir(ShmInit::$rootDir . '/app/Collections');
            foreach ($files as $file) {
                if (!in_array($file, ['.', '..']) && pathinfo($file, PATHINFO_EXTENSION) === 'php') {
                    $className = str_replace('.php', '', $file);
                    $fullClassName = 'App\\Collections\\' . $className;

                    $class = new $fullClassName();

                    if ($class instanceof Collection) {
                        $classes[] = $class::structure();
                    }
                }
            }


            foreach ($classes as $class) {

                $structure = $class;

                if (!$structure->collection) {
                    echo 'Collection is not set for ' . get_class($structure) . PHP_EOL;
                    continue;
                }

                if ($collection && $structure->collection !== $collection) {
                    echo 'Ignoring search index for ' . $structure->collection . ' because collection is not ' . $collection . PHP_EOL;
                    continue;
                }

                if ($structure->ignoreSearchIndex) {
                    echo 'Ignoring search index for ' . $structure->collection . PHP_EOL;
                    continue;
                }

                echo 'Updating search index for ' . $structure->collection . PHP_EOL;

                $items = $structure->find([
                    "_needRecalculateSearch" => ['$ne' => false],
                ], [
                    'limit' => $limit,
                    'sort' => [
                        '_id' => -1
                    ]
                ]);



                foreach ($items as $item) {
                    self::update($class, $item);
                }
            }
        }
    }

    private static function getPathValues(array $path, mixed $value): array
    {

        $result = [];

        $firstSegment = array_shift($path);
        if (count($path) == 0) {

            if ($firstSegment === '[]') {
                if ($value) {
                    return is_array($value) ? $value : mDB::bsonDocumentToArray($value);
                }
                return [];
            } else {
                if (isset($value[$firstSegment])) {
                    return [$value[$firstSegment]];
                } else {
                    return [];
                }
            }
        }





        if ($firstSegment === '[]') {



            if (is_object($value) || is_array($value) || $value instanceof \Traversable) {
                foreach ($value as $item) {


                    $vals = self::getPathValues((array) $path, $item);
                    $result = [...$result, ...$vals];
                }
            }
        } else {



            if (isset($value[$firstSegment])) {

                $vals = self::getPathValues((array) $path, $value[$firstSegment]);


                $result = [...$result, ...$vals];
            }
        }


        return $result;
    }


    public static function update(StructureType $structure, mixed $value)
    {



        if (!$structure->collection) {
            echo 'Collection is not set for ' . get_class($structure) . PHP_EOL;
            return;
        }

        $structure->updateKeys();


        $structure->updatePath();




        if (!$value) {
            echo 'Value is not set for ' . get_class($structure) . PHP_EOL;
            return;
        }

        $searchItems = $structure->findItemsByCondition(function ($item) {
            if ($item instanceof StringType || $item instanceof PhoneType) {
                return true;
            }
            return false;
        });

        //    var_dump($searchItems);

        $searchValues = [];

        foreach ($searchItems as $searchItem) {


            $path = $searchItem->path;

            $val = self::getPathValues((array) $path, $value);

            if ($val) {
                $searchValues = array_merge($searchValues, $val);
            }
        }

        $search_string = implode(' ', $searchValues);

        echo 'Updating search index for ' . $structure->collection  . ' id ' .  $value->_id . ' with value ' . $search_string . PHP_EOL;

        ShmManticore::addItem($structure->collection, $value->_id, $search_string);

        $structure->_updateOne([
            '_id' => $value->_id,
        ], [
            '$set' => [
                "search_string" => $search_string,
                "_needRecalculateSearch" => false,
            ]
        ]);
    }
}
