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"
)

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

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

// Create inserts a new project. The current projects table only stores
// a single agent_id, so we use the first entry from AgentIDs if present.
func (r *ProjectRepository) Create(ctx context.Context, p models.Project) (models.Project, error) {
	now := time.Now().UTC()
	if p.CreatedAt.IsZero() {
		p.CreatedAt = now
	}
	if p.UpdatedAt.IsZero() {
		p.UpdatedAt = now
	}

	var agentID *string
	if len(p.AgentIDs) > 0 {
		agentID = &p.AgentIDs[0]
	}

	err := r.pool.QueryRow(ctx, `
		INSERT INTO projects (name, description, status, agent_id, created_at, updated_at)
		VALUES ($1, $2, $3, $4, $5, $6)
		RETURNING id, name, description, status, agent_id, created_at, updated_at
	`, p.Name, p.Description, string(p.Status), agentID, p.CreatedAt, p.UpdatedAt).Scan(
		&p.ID, &p.Name, &p.Description, &p.Status, &agentID,
		&p.CreatedAt, &p.UpdatedAt,
	)
	if err != nil {
		return p, err
	}

	if agentID != nil {
		p.AgentIDs = []string{*agentID}
	} else {
		p.AgentIDs = []string{}
	}

	return p, nil
}

// List returns all projects ordered by name.
func (r *ProjectRepository) List(ctx context.Context) ([]models.Project, error) {
	rows, err := r.pool.Query(ctx, `
		SELECT id, name, description, status, agent_id, created_at, updated_at
		FROM projects
		ORDER BY name
	`)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	return pgx.CollectRows(rows, func(row pgx.CollectableRow) (models.Project, error) {
		var p models.Project
		var agentID *string

		if err := row.Scan(&p.ID, &p.Name, &p.Description, &p.Status,
			&agentID, &p.CreatedAt, &p.UpdatedAt); err != nil {
			return p, err
		}

		if agentID != nil {
			p.AgentIDs = []string{*agentID}
		} else {
			p.AgentIDs = []string{}
		}
		return p, nil
	})
}

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