package filemanager

import (
	"testing"

	"gorm.io/gorm"
)

func TestFileTableName(t *testing.T) {
	var m File
	if got := m.TableName(); got != "file_files" {
		t.Fatalf("table name mismatch: got %s", got)
	}
}

func TestFileBeforeCreate(t *testing.T) {
	t.Run("assigns uuid when missing", func(t *testing.T) {
		m := &File{}
		if err := m.BeforeCreate(&gorm.DB{}); err != nil {
			t.Fatalf("before create error: %v", err)
		}
		if len(m.ID) != 16 {
			t.Fatalf("expected 16-byte id, got %d", len(m.ID))
		}
	})

	t.Run("keeps existing id", func(t *testing.T) {
		id := make([]byte, 16)
		for i := range id {
			id[i] = byte(i + 1)
		}
		m := &File{ID: append([]byte(nil), id...)}
		if err := m.BeforeCreate(&gorm.DB{}); err != nil {
			t.Fatalf("before create error: %v", err)
		}
		for i := range id {
			if m.ID[i] != id[i] {
				t.Fatalf("id changed at %d: got %d want %d", i, m.ID[i], id[i])
			}
		}
	})
}

func TestNormalizeFileStatus(t *testing.T) {
	cases := map[string]string{
		"uploaded":   FileStatusUploaded,
		"processing": FileStatusProcessing,
		"validated":  FileStatusValidated,
		"failed":     FileStatusFailed,
		"ready":      FileStatusReady,
		"trashed":    FileStatusTrashed,
		" pending ":  FileStatusUploaded,
		"UPLOADING":  FileStatusProcessing,
		"":           "",
	}

	for in, want := range cases {
		if got := NormalizeFileStatus(in); got != want {
			t.Fatalf("NormalizeFileStatus(%q) = %q, want %q", in, got, want)
		}
	}
}

func TestCanTransitionFileStatus(t *testing.T) {
	valid := [][2]string{
		{FileStatusUploaded, FileStatusProcessing},
		{FileStatusUploaded, FileStatusFailed},
		{FileStatusProcessing, FileStatusValidated},
		{FileStatusProcessing, FileStatusFailed},
		{FileStatusValidated, FileStatusReady},
		{FileStatusValidated, FileStatusFailed},
		{FileStatusReady, FileStatusTrashed},
	}
	for i := range valid {
		if !CanTransitionFileStatus(valid[i][0], valid[i][1]) {
			t.Fatalf("expected valid transition %s -> %s", valid[i][0], valid[i][1])
		}
	}

	invalid := [][2]string{
		{FileStatusUploaded, FileStatusReady},
		{FileStatusFailed, FileStatusReady},
		{FileStatusTrashed, FileStatusProcessing},
		{FileStatusReady, FileStatusValidated},
	}
	for i := range invalid {
		if CanTransitionFileStatus(invalid[i][0], invalid[i][1]) {
			t.Fatalf("expected invalid transition %s -> %s", invalid[i][0], invalid[i][1])
		}
	}
}

func TestNormalizeFileLifecycleStatus(t *testing.T) {
	cases := map[string]string{
		"":               FileLifecycleStatusTemp,
		" temp ":         FileLifecycleStatusTemp,
		"ACTIVE":         FileLifecycleStatusActive,
		"orphan_pending": FileLifecycleStatusOrphanPending,
		"deleted":        FileLifecycleStatusDeleted,
	}
	for in, want := range cases {
		if got := NormalizeFileLifecycleStatus(in); got != want {
			t.Fatalf("NormalizeFileLifecycleStatus(%q) = %q, want %q", in, got, want)
		}
	}
}

func TestIsKnownFileLifecycleStatus(t *testing.T) {
	known := []string{
		FileLifecycleStatusTemp,
		FileLifecycleStatusActive,
		FileLifecycleStatusOrphanPending,
		FileLifecycleStatusDeleted,
	}
	for i := range known {
		if !IsKnownFileLifecycleStatus(known[i]) {
			t.Fatalf("expected known lifecycle status %q", known[i])
		}
	}
	if IsKnownFileLifecycleStatus("unknown") {
		t.Fatalf("expected unknown lifecycle status to be false")
	}
}
