package storage

import (
	"context"
	"encoding/json"

	"github.com/jackc/pgx/v5/pgxpool"
	"github.com/nomadcode/nomadcode-core/internal/db"
)

type Task = db.Task

type CreateTaskInput struct {
	Title            string
	Source           string
	Payload          json.RawMessage
	Metadata         json.RawMessage
	ExternalProvider *string
	ExternalID       *string
	ExternalURL      *string
	ExternalMetadata json.RawMessage
}

type Store struct {
	queries *db.Queries
}

func NewStore(pool *pgxpool.Pool) *Store {
	return &Store{queries: db.New(pool)}
}

// NewStoreWithQueries creates a Store with a pre-built *db.Queries (for testing).
func NewStoreWithQueries(queries *db.Queries) *Store {
	return &Store{queries: queries}
}

func (s *Store) CreateTask(ctx context.Context, input CreateTaskInput) (db.Task, error) {
	metadata := input.Metadata
	if len(metadata) == 0 || string(metadata) == "null" {
		metadata = json.RawMessage(`{}`)
	}

	externalMetadata := input.ExternalMetadata
	if len(externalMetadata) == 0 || string(externalMetadata) == "null" {
		externalMetadata = json.RawMessage(`{}`)
	}

	return s.queries.CreateTask(ctx, db.CreateTaskParams{
		Title:            input.Title,
		Source:           input.Source,
		Payload:          input.Payload,
		Metadata:         metadata,
		ExternalProvider: input.ExternalProvider,
		ExternalID:       input.ExternalID,
		ExternalUrl:      input.ExternalURL,
		ExternalMetadata: externalMetadata,
	})
}

func (s *Store) GetTaskByExternalRef(ctx context.Context, provider, id string) (db.Task, error) {
	return s.queries.GetTaskByExternalRef(ctx, db.GetTaskByExternalRefParams{
		ExternalProvider: &provider,
		ExternalID:       &id,
	})
}

func (s *Store) GetTask(ctx context.Context, id string) (db.Task, error) {
	return s.queries.GetTask(ctx, id)
}

func (s *Store) ListTasks(ctx context.Context, limit int32) ([]db.Task, error) {
	return s.queries.ListTasks(ctx, limit)
}

func (s *Store) UpdateMetadata(ctx context.Context, id string, metadata json.RawMessage) (db.Task, error) {
	if len(metadata) == 0 || string(metadata) == "null" {
		metadata = json.RawMessage(`{}`)
	}
	return s.queries.UpdateTaskMetadata(ctx, db.UpdateTaskMetadataParams{
		ID:       id,
		Metadata: metadata,
	})
}

func (s *Store) UpdateStatus(ctx context.Context, id, status string) (db.Task, error) {
	return s.queries.UpdateTaskStatus(ctx, db.UpdateTaskStatusParams{
		ID:     id,
		Status: status,
	})
}

func (s *Store) CompleteTask(ctx context.Context, id string, result json.RawMessage) (db.Task, error) {
	return s.queries.CompleteTask(ctx, db.CompleteTaskParams{
		ID:     id,
		Result: result,
	})
}

func (s *Store) FailTask(ctx context.Context, id, message string) (db.Task, error) {
	return s.queries.FailTask(ctx, db.FailTaskParams{
		ID:    id,
		Error: &message,
	})
}
