<?php

namespace Lucent\Channel;


use Lucent\Primitive\Collection;
use Lucent\Schema\Schema;
use Lucent\Schema\SchemaService;
use PhpOption\Option;

final class ChannelService
{
    public Channel $channel;

    private function __construct(
        public SchemaService $schemaService
    )
    {

    }

    public static function fromConfig(): ChannelService
    {
        $schemasArray = [];
        if (file_exists(schemas_path())) {
            $schemasJson = file_get_contents(schemas_path());
            $schemasArray = json_decode($schemasJson, true);
        }
        $schemaService = new SchemaService();
        $schemasCollection = (new Collection($schemasArray["schemas"] ?? []))->map([$schemaService, 'fromArray']);

        $channel = new Channel(
            name: config("lucent.name") ?? "",
            url: rtrim(config("lucent.url") ?? "", "/"),
            previewTarget: rtrim(config("lucent.previewTarget") ?? "", "/"),
            generateCommand: config("lucent.generateCommand") ?? "",
            schemas: $schemasCollection,
            imageFilters: config("lucent.imageFilters") ?? [],
            roles: $schemasArray["roles"] ?? []
        );

        $channelService = new ChannelService($schemaService);
        $channelService->channel = $channel;
        return $channelService;
    }

    /**
     * @param string $name
     * @return Option<Schema>
     */
    public function getSchema(string $name): Option
    {
        $schema = $this->channel->schemas->firstWhere("name", $name);
        if (empty($schema)) {
            return none();
        }
        return some($schema);
    }

    /**
     * @param array<string> $roles
     * @return array<string>
     */
    public function schemasReadableByRoles(array $roles): array
    {
        $schemasAllRead =  $this->channel->schemas->filter(fn(Schema $schema) => empty($schema->read))->values()->pluck("name");
        $schemasCanRead = $this->channel->schemas->filter(fn(Schema $schema) => count(array_intersect($schema->read ?? [], $roles)) > 0)->values()->pluck("name");
        $schemasCanWrite = $this->channel->schemas->filter(fn(Schema $schema) => count(array_intersect($schema->write ?? [], $roles)) > 0)->values()->pluck("name");
        return $schemasAllRead->merge($schemasCanRead)->merge($schemasCanWrite)->unique()->values()->toArray();

    }

    /**
     * @param array<string> $roles
     * @return array<string>
     */
    public function schemasWritableByRoles(array $roles): array
    {
        $schemasAllRead =  $this->channel->schemas->filter(fn(Schema $schema) => empty($schema->write ?? []))->values()->pluck("name");
        $schemasCanWrite = $this->channel->schemas->filter(fn(Schema $schema) => count(array_intersect($schema->write ??  [], $roles)) > 0)->values()->pluck("name");
        return $schemasAllRead->merge($schemasCanWrite)->unique()->values()->toArray();
    }

}
