package server

import (
	"context"
	"log/slog"
	"strings"
	"time"

	apiknowledgeqa "github.com/tidbcloud/AgentTeam/internal/api/knowledgeqa"
	"github.com/tidbcloud/AgentTeam/internal/config"
	knowledgeqaservice "github.com/tidbcloud/AgentTeam/internal/service/knowledgeqa/runtime"
	"github.com/tidbcloud/AgentTeam/internal/store/kb"
	"github.com/tidbcloud/AgentTeam/internal/store/knowledgeqa"
	"github.com/tidbcloud/AgentTeam/internal/store/resource/repos"
	"gorm.io/gorm"
)

func newKnowledgeQARuntimeHandler(
	cfg config.KnowledgeQAConfig,
	agsSrv agsServer,
	contentStore contentStoreRuntime,
	db *gorm.DB,
	knowledge *kb.Store,
	repositories *repos.Store,
	workspaceAccess knowledgeqaservice.WorkspaceAccessVerifier,
) (*apiknowledgeqa.Handler, *knowledgeqa.Store) {
	var runtime *knowledgeqaservice.Runtime
	var stateStore *knowledgeqa.Store
	var legacyRepository knowledgeqaservice.RepositoryPrimitive
	if snapshotServer, ok := agsSrv.(knowledgeqaservice.AGSRepositorySnapshotServer); ok {
		legacyRepository = knowledgeqaservice.AGSRepositoryPrimitive{Server: snapshotServer}
	}
	var nativeRepository knowledgeqaservice.RepositoryPrimitive
	if contentStore.kb != nil {
		nativeRepository = knowledgeqaservice.ContentStoreRepositoryPrimitive{
			Content: contentStore.kb, RestrictedEvidence: contentStore.core, Projection: knowledge,
		}
	}
	if (legacyRepository != nil || nativeRepository != nil) && strings.TrimSpace(cfg.MaaSBaseURL) != "" {
		stateStore = knowledgeqa.NewRuntime(db)
		tools := &knowledgeqaservice.Service{
			Handles:    stateStore,
			Repository: knowledgeqaservice.RepositoryRouter{Legacy: legacyRepository, Native: nativeRepository},
		}
		runtime = &knowledgeqaservice.Runtime{
			Resolver: &knowledgeqaservice.Resolver{
				Catalog: knowledgeqaservice.Catalog{
					Knowledge:        knowledge,
					Repositories:     repositories,
					WorkspaceAccess:  workspaceAccess,
					ContentAuthority: contentStore.store,
				},
				Handles: stateStore,
			},
			Tools:             tools,
			Inference:         knowledgeqaservice.MaaSClient{BaseURL: cfg.MaaSBaseURL},
			Checkpoints:       stateStore,
			WebReadClient:     knowledgeqaservice.NewWebReadClient(),
			WebSearchProvider: newKnowledgeQAWebSearchProvider(cfg),
			DebugModelOutput:  cfg.DebugModelOutput,
		}
	}
	return &apiknowledgeqa.Handler{Runtime: runtime}, stateStore
}

func newKnowledgeQAWebSearchProvider(cfg config.KnowledgeQAConfig) knowledgeqaservice.WebSearchProvider {
	switch strings.TrimSpace(cfg.WebSearchProvider) {
	case config.KnowledgeQAWebSearchProviderSearXNG:
		provider, err := knowledgeqaservice.NewSearXNGWebSearchProvider(cfg.SearXNGBaseURL, nil)
		if err != nil {
			return nil
		}
		return provider
	default:
		return nil
	}
}

func startKnowledgeQAStateCleanup(store *knowledgeqa.Store, workspaceScope WorkspaceScope, logger *slog.Logger) (context.CancelFunc, <-chan struct{}) {
	if store == nil {
		return nil, nil
	}
	const batchSize = 1000
	ctx, cancel := context.WithCancel(context.Background())
	done := startKBPeriodicWorkers(ctx, logger, kbPeriodicWorker{
		interval:       time.Minute,
		runImmediately: true,
		component:      "knowledge_qa_cleanup",
		errMsg:         "Knowledge Q&A expired state cleanup failed",
		run: func(ctx context.Context) error {
			now := time.Now().UTC()
			workspaceIDs, err := loadWorkspaceScope(ctx, workspaceScope)
			if err != nil {
				return err
			}
			if _, err := store.DeleteExpiredRootHandles(ctx, now, batchSize, workspaceIDs); err != nil {
				return err
			}
			_, err = store.DeleteExpiredAccountingCheckpoints(ctx, now, batchSize, workspaceIDs)
			return err
		},
	})
	return cancel, done
}
