// Code generated by sqlc. DO NOT EDIT.
// versions:
//   sqlc v1.29.0
// source: relationships.sql

package sqlcgen

import (
	"context"
	"time"

	"github.com/google/uuid"
)

const endCurrentRelationship = `-- name: EndCurrentRelationship :execrows
UPDATE relationships SET valid_to = now()
WHERE source_id = $1 AND target_id = $2 AND type = $3 AND valid_to IS NULL
`

type EndCurrentRelationshipParams struct {
	SourceID uuid.UUID
	TargetID uuid.UUID
	Type     string
}

func (q *Queries) EndCurrentRelationship(ctx context.Context, arg EndCurrentRelationshipParams) (int64, error) {
	result, err := q.db.Exec(ctx, endCurrentRelationship, arg.SourceID, arg.TargetID, arg.Type)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}

const insertRelationshipIfAbsent = `-- name: InsertRelationshipIfAbsent :execrows
INSERT INTO relationships (source_id, target_id, type, attributes, valid_from)
SELECT $1, $2, $3,
       $4::jsonb, now()
WHERE NOT EXISTS (
    SELECT 1 FROM relationships
    WHERE source_id = $1
      AND target_id = $2
      AND type = $3
      AND valid_to IS NULL
)
`

type InsertRelationshipIfAbsentParams struct {
	SourceID   uuid.UUID
	TargetID   uuid.UUID
	Type       string
	Attributes []byte
}

// Idempotent relationship insert (the create_relationship surface): no-op if
// an active edge of the same source/target/type already exists. Replaces the
// raw INSERT...WHERE NOT EXISTS used in entity_tools.go.
func (q *Queries) InsertRelationshipIfAbsent(ctx context.Context, arg InsertRelationshipIfAbsentParams) (int64, error) {
	result, err := q.db.Exec(ctx, insertRelationshipIfAbsent,
		arg.SourceID,
		arg.TargetID,
		arg.Type,
		arg.Attributes,
	)
	if err != nil {
		return 0, err
	}
	return result.RowsAffected(), nil
}

const listEntityRelations = `-- name: ListEntityRelations :many
SELECT se.slug AS source_slug, te.slug AS target_slug, r.type, r.attributes,
       r.valid_from, r.valid_to
FROM relationships r
JOIN entities se ON se.id = r.source_id
JOIN entities te ON te.id = r.target_id
WHERE r.valid_to IS NULL
  AND (($1::text IN ('out','both') AND r.source_id = $2)
    OR ($1::text IN ('in','both')  AND r.target_id = $2))
  AND ($3::text IS NULL OR r.type = $3)
ORDER BY r.type, se.slug, te.slug
`

type ListEntityRelationsParams struct {
	Direction string
	ID        uuid.UUID
	RelType   *string
}

type ListEntityRelationsRow struct {
	SourceSlug string
	TargetSlug string
	Type       string
	Attributes []byte
	ValidFrom  time.Time
	ValidTo    *time.Time
}

func (q *Queries) ListEntityRelations(ctx context.Context, arg ListEntityRelationsParams) ([]ListEntityRelationsRow, error) {
	rows, err := q.db.Query(ctx, listEntityRelations, arg.Direction, arg.ID, arg.RelType)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListEntityRelationsRow
	for rows.Next() {
		var i ListEntityRelationsRow
		if err := rows.Scan(
			&i.SourceSlug,
			&i.TargetSlug,
			&i.Type,
			&i.Attributes,
			&i.ValidFrom,
			&i.ValidTo,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listGraphEdges = `-- name: ListGraphEdges :many
SELECT se.slug AS source_slug, te.slug AS target_slug, r.type, r.attributes,
       r.valid_from, r.valid_to
FROM relationships r
JOIN entities se ON se.id = r.source_id
JOIN entities te ON te.id = r.target_id
WHERE r.valid_to IS NULL
  AND r.source_id = ANY($1::uuid[])
  AND r.target_id = ANY($1::uuid[])
  AND ($2::text[] IS NULL OR r.type = ANY($2::text[]))
ORDER BY r.type, se.slug, te.slug
`

type ListGraphEdgesParams struct {
	Ids      []uuid.UUID
	RelTypes []string
}

type ListGraphEdgesRow struct {
	SourceSlug string
	TargetSlug string
	Type       string
	Attributes []byte
	ValidFrom  time.Time
	ValidTo    *time.Time
}

func (q *Queries) ListGraphEdges(ctx context.Context, arg ListGraphEdgesParams) ([]ListGraphEdgesRow, error) {
	rows, err := q.db.Query(ctx, listGraphEdges, arg.Ids, arg.RelTypes)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListGraphEdgesRow
	for rows.Next() {
		var i ListGraphEdgesRow
		if err := rows.Scan(
			&i.SourceSlug,
			&i.TargetSlug,
			&i.Type,
			&i.Attributes,
			&i.ValidFrom,
			&i.ValidTo,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}
