package tests_test

import (
	"path/filepath"
	"strings"
	"testing"

	"git.urbach.dev/cli/q/src/build"
	"git.urbach.dev/cli/q/src/errors"
	"git.urbach.dev/go/assert"
)

var errs = []struct {
	File          string
	ExpectedError error
}{
	{"EmptySwitch.q", errors.EmptySwitch},
	{"ExpectedDLLName.q", errors.ExpectedDLLName},
	{"ExpectedFunctionDefinition.q", errors.ExpectedFunctionDefinition},
	{"ExpectedFunctionParameters.q", errors.ExpectedFunctionParameters},
	{"ExpectedIfBeforeElse.q", errors.ExpectedIfBeforeElse},
	{"ExpectedIfBeforeElse2.q", errors.ExpectedIfBeforeElse},
	{"ExpectedStructName.q", errors.ExpectedStructName},
	{"ExpectedPackageName.q", errors.ExpectedPackageName},
	{"InvalidCondition.q", errors.InvalidCondition},
	{"InvalidInstructionCall.q", &errors.InvalidInstruction{Instruction: "sys.write"}},
	{"InvalidInstructionExpression.q", &errors.InvalidInstruction{Instruction: "2+3"}},
	{"InvalidInstructionIdentifier.q", &errors.InvalidInstruction{Instruction: "abc"}},
	{"InvalidInstructionNumber.q", &errors.InvalidInstruction{Instruction: "123"}},
	{"InvalidInstructionString.q", &errors.InvalidInstruction{Instruction: "\"Hello\""}},
	{"InvalidInstructionTopLevel.q", &errors.InvalidInstruction{Instruction: "123"}},
	{"InvalidInstructionTopLevel2.q", &errors.InvalidInstruction{Instruction: "\"Hello\""}},
	{"InvalidInstructionTopLevel3.q", &errors.InvalidInstruction{Instruction: "+"}},
	{"InvalidExpression.q", errors.InvalidExpression},
	{"InvalidCharacter.q", &errors.InvalidCharacter{Character: "@"}},
	{"InvalidCharacter2.q", &errors.InvalidCharacter{Character: "@"}},
	{"InvalidCharacter3.q", &errors.InvalidCharacter{Character: "@"}},
	{"InvalidCharacter4.q", &errors.InvalidCharacter{Character: "+++"}},
	{"MissingBlockEnd.q", errors.MissingBlockEnd},
	{"MissingBlockEnd2.q", errors.MissingBlockEnd},
	{"MissingBlockStart.q", errors.MissingBlockStart},
	{"MissingBlockStart2.q", errors.MissingBlockStart},
	{"MissingExpression.q", errors.MissingExpression},
	{"MissingGroupEnd.q", errors.MissingGroupEnd},
	{"MissingGroupStart.q", errors.MissingGroupStart},
	{"MissingMainFunction.q", errors.MissingMainFunction},
	{"MissingOperand.q", errors.MissingOperand},
	{"MissingOperand2.q", errors.MissingOperand},
	{"MissingParameter.q", errors.MissingParameter},
	{"MissingParameter2.q", errors.MissingParameter},
	{"MissingParameter3.q", errors.MissingParameter},
	{"MissingType.q", errors.MissingType},
	{"ReturnCountMismatch.q", &errors.ReturnCountMismatch{Count: 1, ExpectedCount: 0}},
	{"TypeMismatch.q", &errors.TypeMismatch{Expected: "*any", Encountered: "int", ParameterName: "p"}},
	{"TypeMismatch2.q", &errors.TypeMismatch{Expected: "[]any", Encountered: "int", ParameterName: "array"}},
	{"UnknownIdentifier.q", &errors.UnknownIdentifier{Name: "x"}},
	{"UnknownIdentifier2.q", &errors.UnknownIdentifier{Name: "x"}},
	{"UnknownIdentifier3.q", &errors.UnknownIdentifier{Name: "x"}},
	{"UnknownIdentifier4.q", &errors.UnknownIdentifier{Name: "unknown"}},
	{"UnknownIdentifier5.q", &errors.UnknownIdentifier{Name: "unknown"}},
	{"UnknownPackage.q", &errors.UnknownPackage{Name: "sys"}},
	{"UnknownType.q", &errors.UnknownType{Name: "unknown"}},
	{"UnknownType2.q", &errors.UnknownType{Name: "unknown"}},
	{"UnknownStructField.q", &errors.UnknownStructField{StructName: "A", FieldName: "x"}},
	{"UntypedExpression.q", errors.UntypedExpression},
	{"UnusedImport.q", &errors.UnusedImport{Package: "sys"}},
	{"UnusedVariable.q", &errors.UnusedVariable{Name: "x"}},
	{"UnusedVariable2.q", &errors.UnusedVariable{Name: "x"}},
	{"VariableAlreadyExists.q", &errors.VariableAlreadyExists{Name: "x"}},
}

func TestErrors(t *testing.T) {
	for _, test := range errs {
		name := strings.TrimSuffix(test.File, ".q")

		t.Run(name, func(t *testing.T) {
			b := build.New(filepath.Join("errors", test.File))
			_, err := b.Run()
			assert.NotNil(t, err)
			assert.Contains(t, err.Error(), test.ExpectedError.Error())
		})
	}
}