<?php

namespace Lucent\Query\DatabaseGraph;

use Illuminate\Support\Facades\DB;
use Lucent\Query\QueryOptions;

class PgsqlDatabaseGraph implements DatabaseGraph
{

    /**
     * @param array<string> $ids
     */
    public function getChildren(array $ids, QueryOptions $options): array
    {
        $subquery = DB::table('edges AS g')
            ->select(DB::raw('g.source,g.target,g.rank,"g"."sourceSchema","g"."targetSchema",g.field, 1 as depth '))
            ->whereIn('source', $ids);

        if (!empty($options->childrenFields)) {
            $subquery->whereIn('field', $options->childrenFields);
        }

        $subquery->limit($options->childrenLimit)
            ->unionAll(
                DB::table(DB::raw("edges AS g, search_graph AS sg "))
                    ->selectRaw('g.source,g.target,g.rank,"g"."sourceSchema","g"."targetSchema",g.field,sg.depth + 1 as depth')
                    ->whereRaw("g.source = sg.target")
                    ->where("depth", "<", $options->childrenDepth)
                    ->orderBy("rank")
            );

        return DB::table('search_graph')
            //            ->select(DB::raw("*, 1 as depth "))
            ->withRecursiveExpression('search_graph', $subquery)
            ->get()->toArray();
    }

    /**
     * @param array<string> $ids
     */
    public function getParents(array $ids, QueryOptions $options): array
    {
        $subquery = DB::table('edges AS g')
            ->select(DB::raw('g.source,g.target,g.rank,"g"."sourceSchema","g"."targetSchema",g.field, 1 as depth '))
            ->limit($options->parentsLimit)
            ->whereIn('g.target', $ids)
            ->unionAll(
                DB::table(DB::raw("edges AS g, search_graph AS sg "))
                    ->selectRaw('g.source,g.target,g.rank,"g"."sourceSchema","g"."targetSchema",g.field,sg.depth + 1 as depth')
                    ->whereRaw("g.target = sg.source")
                    ->where("depth", "<", $options->parentsDepth)
                    ->orderBy("rank")
            );

        return DB::table('search_graph')
            //            ->select(DB::raw('sg.source,sg.target,sg.rank,sg."sourceSchema",sg."targetSchema",sg.field,sg.depth'))
            ->withRecursiveExpression('search_graph', $subquery)
            ->get()->toArray();
    }
}