package migration

import (
	"context"
	"net/http"
	"strings"
	"testing"
)

func TestSharedDriveItemDedup(t *testing.T) {
	store := NewSharedDriveItemStoreMemory()
	ctx := context.Background()
	if store.Has("drive-1", "file-1") {
		t.Fatal("expected miss before mark")
	}
	if err := store.MarkImported(ctx, "drive-1", "file-1", "Shared Drives/Team/doc.pdf", "job-1"); err != nil {
		t.Fatal(err)
	}
	if !store.Has("drive-1", "file-1") {
		t.Fatal("expected hit after mark")
	}
	if store.Has("drive-1", "file-2") {
		t.Fatal("different file should not match")
	}
	if store.Has("drive-2", "file-1") {
		t.Fatal("different drive should not match")
	}
}

func TestDriveImporterSharedDedup(t *testing.T) {
	d := &DriveImporter{sharedDedup: NewSharedDriveItemStoreMemory()}
	ctx := context.Background()
	if err := d.sharedDedup.MarkImported(ctx, "sd-1", "f-1", "path", "job-a"); err != nil {
		t.Fatal(err)
	}
	if !d.alreadyImportedShared("sd-1", "f-1", true) {
		t.Fatal("expected shared dedup hit")
	}
	if d.alreadyImportedShared("sd-1", "f-2", true) {
		t.Fatal("expected miss for other file")
	}
	if d.alreadyImportedShared("", "f-1", false) {
		t.Fatal("personal drive should not dedup at project level")
	}
}

func TestBootstrapSharedDrivesDiscovery(t *testing.T) {
	client := mockGoogleHTTPClient(t, func(w http.ResponseWriter, r *http.Request) {
		if strings.Contains(r.URL.Path, "/drive/v3/drives") {
			_, _ = w.Write([]byte(`{"drives":[{"id":"sd-team","name":"Team Drive"}]}`))
			return
		}
		http.NotFound(w, r)
	})

	d := NewDriveImporter(nil, nil).WithHTTPClient(client).WithProject("proj-1", SharedDriveModeAuto, NewSharedDriveItemStoreMemory())
	job := &Job{ProjectID: "proj-1", UserID: "user-1", CursorJSON: map[string]any{}}
	if err := d.bootstrapSharedDrives(context.Background(), job, "token"); err != nil {
		t.Fatalf("bootstrap: %v", err)
	}
}

func TestGoogleDriveListParams(t *testing.T) {
	myDrive := googleDriveListParams(driveFolderRef{ID: "root"})
	if !strings.Contains(myDrive, "supportsAllDrives=true") {
		t.Fatalf("my drive params: %q", myDrive)
	}
	if strings.Contains(myDrive, "corpora=drive") {
		t.Fatalf("my drive should not use corpora=drive: %q", myDrive)
	}

	shared := googleDriveListParams(driveFolderRef{ID: "sd-1", DriveID: "sd-1", Shared: true})
	if !strings.Contains(shared, "corpora=drive") || !strings.Contains(shared, "driveId=sd-1") {
		t.Fatalf("shared drive params: %q", shared)
	}
}

func TestGoogleDriveDownloadURL(t *testing.T) {
	personal := googleDriveDownloadURL("file-1", false)
	if strings.Contains(personal, "supportsAllDrives") {
		t.Fatalf("personal download: %q", personal)
	}
	shared := googleDriveDownloadURL("file-1", true)
	if !strings.Contains(shared, "supportsAllDrives=true") {
		t.Fatalf("shared download: %q", shared)
	}
}

func TestMergeSharedDriveFolders(t *testing.T) {
	d := NewDriveImporter(nil, nil)
	job := &Job{CursorJSON: map[string]any{}}
	if err := d.mergeSharedDriveFolders(context.Background(), job, "google"); err != nil {
		t.Fatal(err)
	}
	queue := readDriveFolderQueue(job.CursorJSON, "google")
	if len(queue) != 1 || queue[0].ID != "root" {
		t.Fatalf("without db only root queue: %#v", queue)
	}

	manualQueue := readDriveFolderQueue(map[string]any{}, "google")
	manualQueue = enqueueDriveFolder(manualQueue, driveFolderRef{
		ID: "sd-1", Path: "Shared Drives/Finance", DriveID: "sd-1", Shared: true,
	})
	if len(manualQueue) != 2 || !manualQueue[1].Shared {
		t.Fatalf("manual enqueue: %#v", manualQueue)
	}
}

func TestNormalizeSharedDriveMode(t *testing.T) {
	if got := NormalizeSharedDriveMode("manual"); got != SharedDriveModeManual {
		t.Fatalf("got %q", got)
	}
	if got := NormalizeSharedDriveMode(""); got != SharedDriveModeAuto {
		t.Fatalf("default got %q", got)
	}
}
