//
//  Copyright 2026 The InfiniFlow Authors. All Rights Reserved.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

package dataset

import (
	"errors"
	"testing"
	"time"

	"gorm.io/gorm"

	"ragflow/internal/dao"
	"ragflow/internal/entity"
)

func TestCleanupFailedDatasetIndexTaskDeletesTaskAndRestoresDocument(t *testing.T) {
	db := setupServiceTestDB(t)
	pushServiceDB(t, db)

	previousMsg := "previous progress"
	previousBeginAt := time.Date(2026, 6, 18, 10, 0, 0, 0, time.UTC)
	queuedMsg := "Task is queued..."
	queuedBeginAt := previousBeginAt.Add(time.Hour)
	taskID := "task-1"

	kb := &entity.Knowledgebase{
		ID:             "kb-1",
		TenantID:       "user-1",
		Name:           "test-kb",
		EmbdID:         "embedding@OpenAI",
		CreatedBy:      "user-1",
		Permission:     string(entity.TenantPermissionMe),
		ParserID:       "naive",
		ParserConfig:   entity.JSONMap{},
		GraphragTaskID: &taskID,
		Status:         sptr("1"),
	}
	if err := dao.DB.Create(kb).Error; err != nil {
		t.Fatalf("insert kb: %v", err)
	}

	doc := &entity.Document{
		ID:             "doc-1",
		KbID:           "kb-1",
		ParserID:       "naive",
		ParserConfig:   entity.JSONMap{},
		SourceType:     "local",
		Type:           "pdf",
		CreatedBy:      "user-1",
		Suffix:         ".pdf",
		ProgressMsg:    &queuedMsg,
		ProcessBeginAt: &queuedBeginAt,
	}
	if err := dao.DB.Create(doc).Error; err != nil {
		t.Fatalf("insert document: %v", err)
	}

	task := &entity.Task{ID: taskID, DocID: doc.ID, TaskType: "graphrag"}
	if err := dao.DB.Create(task).Error; err != nil {
		t.Fatalf("insert task: %v", err)
	}

	snapshot := &entity.Document{
		ID:             doc.ID,
		ProgressMsg:    &previousMsg,
		ProcessBeginAt: &previousBeginAt,
	}
	if err := cleanupFailedDatasetIndexTask(task.ID, snapshot, kb.ID, "graph"); err != nil {
		t.Fatalf("cleanup failed: %v", err)
	}

	var persistedTask entity.Task
	err := dao.DB.Where("id = ?", task.ID).First(&persistedTask).Error
	if !errors.Is(err, gorm.ErrRecordNotFound) {
		t.Fatalf("expected task to be deleted, got err=%v task=%#v", err, persistedTask)
	}

	ctx := t.Context()
	persistedDoc, err := dao.NewDocumentDAO().GetByID(ctx, db, doc.ID)
	if err != nil {
		t.Fatalf("fetch document: %v", err)
	}
	if persistedDoc.ProgressMsg == nil || *persistedDoc.ProgressMsg != previousMsg {
		t.Fatalf("expected progress_msg %q, got %#v", previousMsg, persistedDoc.ProgressMsg)
	}
	if persistedDoc.ProcessBeginAt == nil || !persistedDoc.ProcessBeginAt.Equal(previousBeginAt) {
		t.Fatalf("expected process_begin_at %v, got %#v", previousBeginAt, persistedDoc.ProcessBeginAt)
	}

	var persistedKB entity.Knowledgebase
	if err = dao.DB.Where("id = ?", kb.ID).First(&persistedKB).Error; err != nil {
		t.Fatalf("fetch kb: %v", err)
	}
	if persistedKB.GraphragTaskID != nil {
		t.Fatalf("expected graphrag_task_id to be cleared, got %#v", *persistedKB.GraphragTaskID)
	}
}
