package repository

import (
	"context"
	"time"

	"code.cubecraftcreations.com/CubeCraft-Creations/Control-Center/go-backend/internal/models"
	"github.com/jackc/pgx/v5"
	"github.com/jackc/pgx/v5/pgxpool"
)

// SessionRepository provides PostgreSQL-backed CRUD for sessions.
type SessionRepository struct {
	pool *pgxpool.Pool
}

// NewSessionRepository returns a repository wired to the given connection pool.
func NewSessionRepository(pool *pgxpool.Pool) *SessionRepository {
	return &SessionRepository{pool: pool}
}

// Create inserts a new session into the sessions table.
// Because the existing sessions table only has id, agent_id, started_at,
// ended_at, and status, we map what we can and store additional metadata
// as a fallback. AgentID is required by FK — if the session AgentID can't
// be cast to a valid UUID we store a sentinel.
func (r *SessionRepository) Create(ctx context.Context, s models.Session) (models.Session, error) {
	if s.StartedAt.IsZero() {
		s.StartedAt = time.Now().UTC()
	}
	if s.LastActivityAt.IsZero() {
		s.LastActivityAt = s.StartedAt
	}

	err := r.pool.QueryRow(ctx, `
		INSERT INTO sessions (agent_id, started_at, status)
		VALUES ($1, $2, $3)
		RETURNING id, agent_id, started_at, ended_at, status
	`, s.AgentID, s.StartedAt, s.Status).Scan(
		&s.ID, &s.AgentID, &s.StartedAt, nil, &s.Status)

	return s, err
}

// ListActive returns all sessions with status 'running' or 'streaming',
// ordered by started_at descending.
func (r *SessionRepository) ListActive(ctx context.Context) ([]models.Session, error) {
	rows, err := r.pool.Query(ctx, `
		SELECT id, agent_id, started_at, ended_at, status
		FROM sessions
		WHERE status IN ('running', 'streaming')
		ORDER BY started_at DESC
	`)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	return pgx.CollectRows(rows, func(row pgx.CollectableRow) (models.Session, error) {
		var s models.Session
		var endedAt *time.Time
		if err := row.Scan(&s.ID, &s.AgentID, &s.StartedAt, &endedAt, &s.Status); err != nil {
			return s, err
		}
		s.LastActivityAt = s.StartedAt
		if endedAt != nil {
			s.LastActivityAt = *endedAt
		}
		return s, nil
	})
}

// Count returns the total number of sessions.
func (r *SessionRepository) Count(ctx context.Context) (int, error) {
	var n int
	err := r.pool.QueryRow(ctx, `SELECT COUNT(*) FROM sessions`).Scan(&n)
	return n, err
}
