package ucca

import (
	"context"
	"time"

	"github.com/google/uuid"
	"github.com/jackc/pgx/v5"
	"github.com/jackc/pgx/v5/pgxpool"
)

// CorpusVersion tracks a specific version of the RAG compliance corpus.
type CorpusVersion struct {
	ID              uuid.UUID `json:"id"`
	Version         string    `json:"version"`           // "2026-03-02.1"
	CollectionName  string    `json:"collection_name"`   // "bp_compliance_ce"
	DocumentsCount  int       `json:"documents_count"`
	ChunksCount     int       `json:"chunks_count"`
	Regulations     []string  `json:"regulations"`       // ["eu_2016_679", ...]
	Digest          string    `json:"digest,omitempty"`   // SHA256 over chunks
	IngestionSource string    `json:"ingestion_source,omitempty"`
	Notes           string    `json:"notes,omitempty"`
	CreatedAt       time.Time `json:"created_at"`
	CreatedBy       string    `json:"created_by,omitempty"`
}

// CorpusVersionStore handles corpus version persistence.
type CorpusVersionStore struct {
	pool *pgxpool.Pool
}

// NewCorpusVersionStore creates a new corpus version store.
func NewCorpusVersionStore(pool *pgxpool.Pool) *CorpusVersionStore {
	return &CorpusVersionStore{pool: pool}
}

// CreateCorpusVersion inserts a new corpus version record.
func (s *CorpusVersionStore) CreateCorpusVersion(ctx context.Context, v *CorpusVersion) error {
	if v.ID == uuid.Nil {
		v.ID = uuid.New()
	}
	if v.CreatedAt.IsZero() {
		v.CreatedAt = time.Now().UTC()
	}

	_, err := s.pool.Exec(ctx, `
		INSERT INTO compliance_corpus_versions (
			id, version, collection_name, documents_count, chunks_count,
			regulations, digest, ingestion_source, notes, created_at, created_by
		) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
	`,
		v.ID, v.Version, v.CollectionName, v.DocumentsCount, v.ChunksCount,
		v.Regulations, v.Digest, v.IngestionSource, v.Notes, v.CreatedAt, v.CreatedBy,
	)
	return err
}

// GetLatestCorpusVersion returns the most recent version for a collection.
func (s *CorpusVersionStore) GetLatestCorpusVersion(ctx context.Context, collection string) (*CorpusVersion, error) {
	var v CorpusVersion
	err := s.pool.QueryRow(ctx, `
		SELECT id, version, collection_name, documents_count, chunks_count,
			   regulations, digest, ingestion_source, notes, created_at, created_by
		FROM compliance_corpus_versions
		WHERE collection_name = $1
		ORDER BY created_at DESC
		LIMIT 1
	`, collection).Scan(
		&v.ID, &v.Version, &v.CollectionName, &v.DocumentsCount, &v.ChunksCount,
		&v.Regulations, &v.Digest, &v.IngestionSource, &v.Notes, &v.CreatedAt, &v.CreatedBy,
	)
	if err == pgx.ErrNoRows {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}
	return &v, nil
}

// GetCorpusVersionByID retrieves a specific corpus version by ID.
func (s *CorpusVersionStore) GetCorpusVersionByID(ctx context.Context, id uuid.UUID) (*CorpusVersion, error) {
	var v CorpusVersion
	err := s.pool.QueryRow(ctx, `
		SELECT id, version, collection_name, documents_count, chunks_count,
			   regulations, digest, ingestion_source, notes, created_at, created_by
		FROM compliance_corpus_versions
		WHERE id = $1
	`, id).Scan(
		&v.ID, &v.Version, &v.CollectionName, &v.DocumentsCount, &v.ChunksCount,
		&v.Regulations, &v.Digest, &v.IngestionSource, &v.Notes, &v.CreatedAt, &v.CreatedBy,
	)
	if err == pgx.ErrNoRows {
		return nil, nil
	}
	if err != nil {
		return nil, err
	}
	return &v, nil
}

// ListCorpusVersions returns all versions for a collection, newest first.
func (s *CorpusVersionStore) ListCorpusVersions(ctx context.Context, collection string) ([]CorpusVersion, error) {
	rows, err := s.pool.Query(ctx, `
		SELECT id, version, collection_name, documents_count, chunks_count,
			   regulations, digest, ingestion_source, notes, created_at, created_by
		FROM compliance_corpus_versions
		WHERE collection_name = $1
		ORDER BY created_at DESC
	`, collection)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var versions []CorpusVersion
	for rows.Next() {
		var v CorpusVersion
		err := rows.Scan(
			&v.ID, &v.Version, &v.CollectionName, &v.DocumentsCount, &v.ChunksCount,
			&v.Regulations, &v.Digest, &v.IngestionSource, &v.Notes, &v.CreatedAt, &v.CreatedBy,
		)
		if err != nil {
			return nil, err
		}
		versions = append(versions, v)
	}
	return versions, nil
}

// GetAllLatestVersions returns the latest version for every collection.
func (s *CorpusVersionStore) GetAllLatestVersions(ctx context.Context) ([]CorpusVersion, error) {
	rows, err := s.pool.Query(ctx, `
		SELECT DISTINCT ON (collection_name)
			id, version, collection_name, documents_count, chunks_count,
			regulations, digest, ingestion_source, notes, created_at, created_by
		FROM compliance_corpus_versions
		ORDER BY collection_name, created_at DESC
	`)
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	var versions []CorpusVersion
	for rows.Next() {
		var v CorpusVersion
		err := rows.Scan(
			&v.ID, &v.Version, &v.CollectionName, &v.DocumentsCount, &v.ChunksCount,
			&v.Regulations, &v.Digest, &v.IngestionSource, &v.Notes, &v.CreatedAt, &v.CreatedBy,
		)
		if err != nil {
			return nil, err
		}
		versions = append(versions, v)
	}
	return versions, nil
}
