package datamodeldiagram

import (
	"testing"

	"github.com/alecthomas/assert"
	"github.com/anz-bank/sysl/pkg/mermaid"
	"github.com/anz-bank/sysl/pkg/parse"
	"github.com/anz-bank/sysl/pkg/syslutil"
	"github.com/anz-bank/sysl/pkg/syslwrapper"
	"github.com/spf13/afero"
)

func TestGenerateMermaidDataModelDiagram(t *testing.T) {
	m, err := parse.NewParser().ParseFromFs("demo/petshop/petshop.sysl",
		syslutil.NewChrootFs(afero.NewOsFs(), mermaid.ProjectDir))
	assert.NoError(t, err)
	mapper := syslwrapper.MakeAppMapper(m)
	mapper.IndexTypes()
	mapper.ConvertTypes()
	r, err := GenerateFullDataDiagram(m)
	assert.NotNil(t, m)
	assert.NotNil(t, r)
	assert.NoError(t, err)
}

func TestGenerateMermaidDataModelDiagramWithMapper(t *testing.T) {
	m, err := parse.NewParser().ParseFromFs("demo/petshop/petshop.sysl",
		syslutil.NewChrootFs(afero.NewOsFs(), mermaid.ProjectDir))
	assert.NoError(t, err)
	mapper := syslwrapper.MakeAppMapper(m)
	mapper.IndexTypes()
	mapper.ConvertTypes()
	r, err := GenerateDataDiagramWithMapper(mapper, "PetShopModel", "Pet")
	assert.NotNil(t, m)
	assert.NotNil(t, r)
	assert.NoError(t, err)
}
func TestGenerateMermaidDataModelDiagramWithAppAndType(t *testing.T) {
	m, err := parse.NewParser().ParseFromFs("demo/petshop/petshop.sysl",
		syslutil.NewChrootFs(afero.NewOsFs(), mermaid.ProjectDir))
	assert.NoError(t, err)
	r, err := GenerateDataDiagramWithAppAndType(m, "PetShopModel", "Pet")
	assert.NotNil(t, m)
	assert.NotNil(t, r)
	assert.NoError(t, err)
}

func TestGenerateMermaidDataModelDiagramWithAppAndTypeNonExistentType(t *testing.T) {
	m, err := parse.NewParser().ParseFromFs("demo/petshop/petshop.sysl",
		syslutil.NewChrootFs(afero.NewOsFs(), mermaid.ProjectDir))
	assert.NoError(t, err)
	r, err := GenerateDataDiagramWithAppAndType(m, "PetShopModel", "ThisDoesNotExist")
	assert.NotNil(t, m)
	assert.NotNil(t, r)
	assert.NoError(t, err)
}

func TestGenerateMermaidDataModelDiagramWithAppAndTypeEmptyString(t *testing.T) {
	m, err := parse.NewParser().ParseFromFs("demo/petshop/petshop.sysl",
		syslutil.NewChrootFs(afero.NewOsFs(), mermaid.ProjectDir))
	assert.NoError(t, err)
	r, err := GenerateDataDiagramWithAppAndType(m, "PetShopModel", "")
	assert.NotNil(t, m)
	assert.NotNil(t, r)
	assert.NoError(t, err)
}

func TestGeneratePrimitive(t *testing.T) {
	r := GeneratePrimitive("String")
	expected := `%% AUTOGENERATED CODE -- DO NOT EDIT!

classDiagram
 class primitive{
  var String
 }`
	assert.Equal(t, expected, r)
}

func TestGenerateMermaidDataModelDiagramWithRecursiveReference(t *testing.T) {
	m, err := parse.NewParser().ParseFromFs("tests/recursive.sysl",
		syslutil.NewChrootFs(afero.NewOsFs(), mermaid.ProjectDir))
	assert.NoError(t, err)
	mapper := syslwrapper.MakeAppMapper(m)
	mapper.IndexTypes()
	mapper.ConvertTypes()
	r, err := GenerateDataDiagramWithAppAndType(m, "Simple", "simpleType")
	assert.NotNil(t, m)
	assert.NotNil(t, r)
	assert.NoError(t, err)
}

// TODO: This is a failing test, to be fixed
func TestGenerateMermaidDataModelDiagramWithNamespaces(t *testing.T) {
	appName := "Org :: Team :: TestApp"
	typeName := "test"
	syslInput := `
Org :: Team :: TestApp:
	!type test:
		field <: string
		field2 <: string

`
	m, err := parse.NewParser().ParseString(syslInput)
	assert.NoError(t, err)
	mapper := syslwrapper.MakeAppMapper(m)
	mapper.IndexTypes()
	mapper.ConvertTypes()
	r, err := GenerateDataDiagramWithAppAndType(m, appName, typeName)
	assert.NotNil(t, r)
	assert.NoError(t, err)
	t.Log(r)
}
