<?php

namespace AuthStack\Driver\LDAP;

use Buckhill\LDAP\Entry;
use Illuminate\Support\Str;
use Buckhill\LDAP\EntryCollection;
use Illuminate\Support\Collection;

class Attributes
{
    const SOURCE_RECORD = 1;
    const SOURCE_FILTER = 2;

    /** @var $attributes array|Collection */
    protected array|Collection $attributes;

    public static function fromArray(array $model): self
    {
        $me = new static;

        $me->attributes = collect($model);

        return $me;
    }

    /**
     * @param array $ldap_attrs
     * @param EntryCollection $collection
     * @return EntryCollection
     */
    public function rename(array $ldap_attrs, EntryCollection $collection): EntryCollection
    {
        $attributes = $this->getCollection()->where("source_id", static::SOURCE_RECORD)->where("enabled", true);

        $attributes->map(function ($item, $key) use ($ldap_attrs, $collection) {
            $name = $item['name'];

            if (isset($ldap_attrs[$name])) {
                $record = $ldap_attrs[$name];

                $isJson = Str::of($record)->isJson();

                if ($isJson && !is_numeric($record)) {
                    $this->renameAttributeCollection($collection, $item['renamed'], $record, $record);
                } else {
                    $this->renameAttributeCollection($collection, $item['renamed'], null, $record);
                }
            } else {
                $this->renameAttributeCollection($collection, $name);
            }
        });

        return $collection;
    }

    /**
     * Returns an array of attributes that we're supposed to retrieve from AD/LDAP when searching for user
     * It's a subset of all user attributes (filtered version)
     */
    public function getDirectoryAttributes()
    {
        $collection = $this->getCollection()->where("source_id", static::SOURCE_RECORD)->where("enabled", true);

        $attributes = $collection->map(function ($item, $key) {
            return $item['name'];
        });

        return array_values($attributes->toArray());
    }

    /**
     * @return array
     */
    public function getFilterAttributes($id)
    {
        $result = $this->getCollection()->where('source_id', $id)->toArray();

        return array_values($result);
    }

    /**
     * @return array
     */
    public function getFilteredAttributesRenamed()
    {
        $collection = $this->getCollection();

        $attributes = $collection->map(function ($item, $key) {
            return [
                'name' => $item['name'],
                'renamed' => $item['renamed']
            ];
        });

        return array_values($attributes->toArray());
    }

    /**
     * @return Collection
     */
    public function getCollection()
    {
        return $this->attributes;
    }

    /**
     * @param EntryCollection $collection
     * @param mixed $renamed
     * @param mixed $setCount
     * @param mixed|null $value
     * @return void
     */
    function renameAttributeCollection(
        EntryCollection $collection,
        mixed $renamed,
        mixed $setCount = null,
        mixed $value = null
    ): void {
        $collection->add(
            (new Entry())
                ->setName($renamed)
                ->setCount(is_null($setCount) ? 0 : sizeof($setCount))
                ->setValue($value)
        );
    }
}