package errs

import (
	"context"
	"testing"

	"backend/pkg/library/errs/code"

	"github.com/zeromicro/go-zero/core/logx"
)

func TestFromError(t *testing.T) {
	t.Run("nil error", func(t *testing.T) {
		if err := FromError(nil); err != nil {
			t.Errorf("expected nil, got %v", err)
		}
	})

	t.Run("LibError type", func(t *testing.T) {
		libErr := NewError(1, 200, 10, "test error")
		if err := FromError(libErr); err != libErr {
			t.Errorf("expected %v, got %v", libErr, err)
		}
	})
}

func TestFromCode(t *testing.T) {
	tests := []struct {
		name     string
		code     uint32
		expected *LibError
	}{
		{"valid code", 1200314, NewError(12, 3, 14, "")},
		{"invalid code", 9999999, NewError(99, 999, 99, "")},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := FromCode(tt.code)
			if err.FullCode() != tt.expected.FullCode() {
				t.Errorf("expected %v, got %v", tt.expected.FullCode(), err.FullCode())
			}
		})
	}
}

func TestSystemTimeoutError(t *testing.T) {
	tests := []struct {
		name     string
		input    []string
		expected string
	}{
		{"single string", []string{"timeout"}, "timeout"},
		{"multiple strings", []string{"timeout", "occurred"}, "timeout occurred"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := SystemTimeoutError(tt.input...)
			if err.Error() != tt.expected {
				t.Errorf("expected %s, got %s", tt.expected, err.Error())
			}
		})
	}
}

func TestSystemInternalErrorL(t *testing.T) {
	tests := []struct {
		name  string
		input []string
	}{
		{"internal error", []string{"internal error"}},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			ctx := context.TODO()
			err := SystemInternalErrorL(logx.WithContext(ctx), nil, tt.input...)
			if err.Error() != tt.input[0] {
				t.Errorf("expected %s, got %s", tt.input[0], err.Error())
			}
		})
	}
}

func TestInvalidFormatL(t *testing.T) {
	mockLogger := logx.WithContext(context.Background())
	tests := []struct {
		name     string
		input    []string
		expected string
	}{
		{"invalid format", []string{"invalid format"}, "invalid format"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := InvalidFormatL(mockLogger, nil, tt.input...)
			if err.Error() != tt.expected {
				t.Errorf("expected %s, got %s", tt.expected, err.Error())
			}
		})
	}
}

func TestDBErrorL(t *testing.T) {
	mockLogger := logx.WithContext(context.Background())
	tests := []struct {
		name     string
		input    []string
		expected string
	}{
		{"DB error", []string{"DB error"}, "DB error"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := DBErrorL(mockLogger, nil, tt.input...)
			if err.Error() != tt.expected {
				t.Errorf("expected %s, got %s", tt.expected, err.Error())
			}
		})
	}
}

func TestResourceNotFoundL(t *testing.T) {
	mockLogger := logx.WithContext(context.Background())
	tests := []struct {
		name     string
		input    []string
		expected string
	}{
		{"resource not found", []string{"resource not found"}, "resource not found"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := ResourceNotFoundL(mockLogger, nil, tt.input...)
			if err.Error() != tt.expected {
				t.Errorf("expected %s, got %s", tt.expected, err.Error())
			}
		})
	}
}

func TestInsufficientPermissionL(t *testing.T) {
	mockLogger := logx.WithContext(context.Background())
	tests := []struct {
		name     string
		input    []string
		expected string
	}{
		{"insufficient permission", []string{"permission denied"}, "permission denied"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := InsufficientPermissionL(mockLogger, nil, tt.input...)
			if err.Error() != tt.expected {
				t.Errorf("expected %s, got %s", tt.expected, err.Error())
			}
		})
	}
}

func TestIsAuthUnauthorizedError(t *testing.T) {
	tests := []struct {
		name     string
		err      *LibError
		expected bool
	}{
		{"Unauthorized error", NewError(1, code.Unauthorized, 0, ""), true},
		{"AuthExpired error", NewError(1, code.AuthExpired, 0, ""), true},
		{"Other error", NewError(1, code.ArkInternal, 0, ""), false},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			res := IsAuthUnauthorizedError(tt.err)
			if res != tt.expected {
				t.Errorf("expected %t, got %t", tt.expected, res)
			}
		})
	}
}
