package purge

import (
	"context"
	"fmt"

	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"

	"bit.admedia.com/scm/ad/adpilot-indexing-repo-sync.com/internal/config"
)

// Result summarizes documents removed per database.collection.
type Result map[string]int64

type databaseTarget struct {
	database    string
	collections []string
}

// PipelinePurger deletes per-repo pipeline data across MongoDB databases.
type PipelinePurger struct {
	client  *mongo.Client
	targets []databaseTarget
}

// NewPipelinePurger connects to Mongo and configures cross-database purge targets.
func NewPipelinePurger(cfg config.PipelineConfig) (*PipelinePurger, error) {
	uri := cfg.MongoURI
	if uri == "" {
		return nil, fmt.Errorf("pipeline mongo uri is required")
	}

	ctx, cancel := context.WithTimeout(context.Background(), defaultConnectTimeout)
	defer cancel()

	client, err := mongo.Connect(ctx, options.Client().ApplyURI(uri))
	if err != nil {
		return nil, fmt.Errorf("connect pipeline mongodb: %w", err)
	}

	targets := []databaseTarget{
		{
			database: cfg.RepoSyncDatabase,
			collections: []string{
				"repositories", "snapshots", "sync_jobs", "indexing_runs",
				"snapshot_files", "indexing_diagnostics",
			},
		},
		{
			database: cfg.CodeParserDatabase,
			collections: []string{
				"code_chunks", "snapshot_graphs", "graph_deltas", "graph_delta_parts",
				"commit_processing_state", "code_graph_artifacts", "code_graph_artifact_parts",
				"snapshot_graph_parts",
			},
		},
		{database: cfg.CommitIntelDatabase, collections: []string{"commit_analyses"}},
		{database: cfg.EmbeddingDatabase, collections: []string{"embedding_records", "embedding_runs"}},
		{database: cfg.DocsDatabase, collections: []string{"doc_chunks"}},
	}

	for _, target := range targets {
		if target.database == "" {
			return nil, fmt.Errorf("pipeline purge database name is required")
		}
	}

	return &PipelinePurger{client: client, targets: targets}, nil
}

// Close disconnects the Mongo client.
func (p *PipelinePurger) Close(ctx context.Context) error {
	if p == nil || p.client == nil {
		return nil
	}
	return p.client.Disconnect(ctx)
}

// PurgeRepo deletes all pipeline documents for repoID across configured databases.
func (p *PipelinePurger) PurgeRepo(ctx context.Context, repoID string) (Result, error) {
	if p == nil || p.client == nil {
		return nil, fmt.Errorf("pipeline purger is not configured")
	}
	if repoID == "" {
		return nil, fmt.Errorf("repo_id is required")
	}

	filter := bson.M{"repo_id": repoID}
	summary := make(Result)

	for _, target := range p.targets {
		db := p.client.Database(target.database)
		for _, collection := range target.collections {
			key := target.database + "." + collection
			res, err := db.Collection(collection).DeleteMany(ctx, filter)
			if err != nil {
				return summary, fmt.Errorf("delete %s: %w", key, err)
			}
			summary[key] = res.DeletedCount
		}
	}

	return summary, nil
}
