package got

import (
	"text/template"

	. "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/common"
	G "github.com/dave/jennifer/jen"
)

const ()

var (
	undeleteStmtsTmpl, hasDepUndeleteStmtsTmpl *template.Template
	undeleteStmtsErr                           error
)

func init() {

	undeleteStmtsTmpl, undeleteStmtsErr = ParseTemplate(`
	var (
		patchs = &models.{{.entity}}Patchs{Set: &models.{{.entity}}Input{}}
		entity = patchs.Set
	)

	values := ctx.Values()
	values.Set("patchs", patchs)
	values.Set("entity", entity)

	user := values.Get("$user.ref").(*models.UserReference)
	
	entity.SetDeleted(false)
	entity.LastUpdate = api.NowUnix()
	entity.UpdatedBy = user

	{{if .preconditions}}
		if _, err = executeAction(
			ctx,
			{{.preconditions}},
		); err != nil {
			return
		}
	{{end}}

	options := values.Get("$filter").(*api.Filter)
	options.DB = "{{.dbName}}"
	options.Collection = "{{.collectionName}}"
	options.Patchs, options.Options = patchs.Patch()

	if _, err = models.Api.PatchOne(options); err != nil {
		return
	}

	{{if .beforeResponse}}
	if resp, err = executeAction(
		ctx,
		{{.beforeResponse}},
	); err != nil || resp != nil {
		return
	}
	{{end}}

	resp = ""

	return`)

	if undeleteStmtsErr != nil {
		panic(undeleteStmtsErr)
	}
}

var (
	GenUndeleteStmts = &Middleware{
		Id:   "undelete",
		Type: "method",
		Fn: func(ctx *MiddlewareContext) error {
			var (
				project          = ctx.Project
				method           = ctx.Method
				dbName           = project.GetEntityDB(method.Entity)
				collectionName   = project.GetCollection(method.Entity)
				relations        = SR.Get(method.Entity)
				relationCount    = len(relations)
				dependenceMethod = BASE_HAS_DEPENDE + method.Entity
				// createDepFunc    = SR.Has(method.Entity)
				beforeSend    = method.Hook("beforeSend")
				beforePersist = method.Hook("beforePersist")
				context       = map[string]interface{}{
					"dbName":         dbName,
					"collectionName": collectionName,
					"entity":         method.Entity,
					// "createDepFunc":    createDepFunc,
					"relationCount":    relationCount,
					"relations":        relations,
					"dependenceMethod": dependenceMethod,
					"beforePersist":    beforePersist,
					"beforeSend":       beforeSend,
					"preconditions":    parseMethodActions(method.Preconditions),
					"beforeResponse":   parseMethodActions(method.BeforeResponse),
				}
			)
			// Nome do metodo que verifica se a entidade tem dependencias

			out, _ := TemplateToString(undeleteStmtsTmpl, context)
			ctx.Statement.Block(G.Id(out)).Line()

			// if createDepFunc {
			// 	out, _ = TemplateToString(hasDepUndeleteStmtsTmpl, context)
			// 	afterMethod.Id(out)
			// }

			return nil
		},
	}
)

// import (
// 	"fmt"
// 	"strings"

// 	. "git.eugeniocarvalho.dev/eugeniucarvalho/apicodegen/common"
// 	G "github.com/dave/jennifer/jen"
// 	// "github.com/davecgh/go-spew/spew"
// )

// var (
// 	GenUndeleteStmts = &Middleware{
// 		Id:   "undelete",
// 		Type: "method",
// 		Fn: func(ctx *MiddlewareContext) error {

// 			var (
// 				// UpdateRelationRotine *G.Statement
// 				method = ctx.Method
// 				// updRelation          = UPDATE_RELATION + method.Entity
// 				// createUpdateRelation = false
// 				entity         = method.Request
// 				responseEntity = GenericPart.ReplaceAllString(method.Response, "")
// 			)
// 			if entity == "" {
// 				panic("Modelo de request não definido em UpdateStmt!")
// 			}
// 			if responseEntity == "" {
// 				panic("Modelo de response não definido!")
// 			}

// 			ctx.Statement.Block(
// 				// Declaracao das variaveis
// 				G.Var().Defs(
// 					// G.Id("err").Op("*").Qual(API_ERROR, "Error"),
// 					// G.Id("patchs").Op("=").Op("&").Id(entity).Values(),
// 					G.Id("patchs").Op("=").Op("&").Id(fmt.Sprintf("%sPatchs", method.Entity)).Values(
// 						G.Id("Set").Op(": &").Id(entity).Values(),
// 					),
// 					// G.Id("patchs").Op("=").Id(entity).Values(),
// 					G.Id("entity = patchs.Set"),
// 					G.Do(func(s *G.Statement) {
// 						if method.BeforePersistAction {
// 							s.Id("fn").Func().Call().Op("*").Qual(API_ERROR, "Error")
// 						}
// 					}),
// 				).Line(),
// 				// G.Id("fmt.Println(`era o undelete`)").Line(),
// 				// Fazendo o parse do body
// 				// G.If(
// 				// 	G.Id("err").Op("=").Qual(API_URL, "ReadJson").Call(G.Id("ctx"), G.Id("patchs")),
// 				// 	G.Id("err").Op("!=").Id("nil"),
// 				// ).Block(
// 				// 	// G.Id("api").Dot("Falha").Call(
// 				// 	// 	G.Id("ctx"),
// 				// 	// 	G.Id("api").Dot("ErrGeneral"),
// 				// 	// 	G.Id("err").Dot("Error").Call(),
// 				// 	// 	G.Nil(),
// 				// 	// ),
// 				// 	// G.Return(G.Id("err")),
// 				// 	G.Return(),
// 				// ),
// 				// G.Do(func(s *G.Statement) {
// 				// 	entity := ctx.Project.EntityDesc(method.Entity)
// 				// 	if entity != nil && entity.HasMode {
// 				// 		s.Add(G.Id(`entity.SetMode("create")`))
// 				// 	}
// 				// }),
// 				// G.If(
// 				// 	G.Id("err").Op("=").Qual(API_URL, "Validate").Call(G.Id("entity")),
// 				// 	G.Id("err").Op("!=").Id("nil"),
// 				// ).Block(
// 				// 	// G.Return(G.Id("err")),
// 				// 	G.Return(),
// 				// ).Line(),
// 				// Captura a base de values
// 				G.Id("values").Op(":=").Id("ctx").Dot("Values").Call(),
// 				G.Id("values").Dot("Set").Call(G.Lit("patchs"), G.Id("patchs")),
// 				G.Id("entity.SetDeleted(false)"),

// 				// Gera as atribuicoes de variaveis que seram atualizadas (usuario e ultimo update quando existir)
// 				G.Do(func(part *G.Statement) {
// 					entity := ctx.Project.GetSchema(method.Entity)
// 					user := false
// 					for _, prop := range entity.Properties {
// 						if def, ok := prop.Autogenerate["update"]; ok {
// 							switch def.Type {
// 							case "user":
// 								if !user {
// 									part.Add(G.Id(`user := values.Get("$user.ref").(*UserReference)`).Line())
// 									user = true
// 								}

// 								part.Add(G.Id("entity").Dot(strings.Title(prop.ID)).Op("=").Id("user").Line())
// 							case "now":
// 								part.Add(G.Id("entity").Dot(strings.Title(prop.ID)).Op("=").Qual("time", "Now").Call().Id(".Unix()").Line())
// 							}
// 						}
// 					}
// 				}).Line(),

// 				// Carrega o filtro do contexto para adicionar a entidade
// 				G.Id("filter").Op(":=").Id("values").Dot("Get").Call(
// 					G.Lit("$filter"),
// 				).Assert(G.Op("*").Qual(API_URL, "Filter")).Line(),

// 				// Adiciona a entidade
// 				G.Id("filter").Dot("DB").Op("=").Lit(ctx.Project.GetEntityDB(method.Entity)),
// 				G.Id("filter").Dot("Collection").Op("=").Lit(ctx.Project.GetCollection(method.Entity)),

// 				G.Do(func(s *G.Statement) {
// 					if method.BeforePersistAction {
// 						fnName := fmt.Sprintf("Before%s%s", strings.Title(method.ID), method.Entity)
// 						part := s.Comment("Chama uma função onde são descritas as ações executadas antes da entidade ser persistida.").Line()
// 						part.If(
// 							G.List(G.Id("fn"), G.Id("err")).Op("=").Id(fnName).Call(G.Id("ctx"), G.Id("patchs")),
// 							G.Id("err").Op("!=").Id("nil"),
// 						).Block(G.Return())
// 					}
// 				}),

// 				G.Id("filter").Dot("Patchs").Op("=").Id("patchs.Patch()").Line(),

// 				// Inseri a entidade na coleção e verifica se a operação ocorreu com exito
// 				G.If(
// 					G.List(G.Id("_"), G.Id("err")).Op("=").Id("Models").Dot("PatchOne").Call(
// 						// G.Lit(ctx.Project.GetCollection(method.Entity)),
// 						G.Id("filter"),
// 					),
// 					G.Id("err").Op("!=").Id("nil"),
// 				).Block(
// 					// G.Id("api").Dot("Falha").Call(
// 					// 	G.Id("ctx"),
// 					// 	G.Id("api").Dot("ErrGeneral"),
// 					// 	G.Id("err").Dot("Error").Call(),
// 					// 	G.Nil(),
// 					// ),
// 					// bson.IsObjectIdHex(m.Id.Hex())
// 					// G.Return(G.Id("err")),
// 					G.Return(),
// 				),
// 				G.Do(func(s *G.Statement) {
// 					if method.BeforePersistAction {
// 						part := s.Comment("Chama uma função onde são descritas as ações executadas após a entidade ser persistida.").Line()
// 						part.If(
// 							G.Id("err").Op("=").Id("fn").Call(),
// 							G.Id("err").Op("!=").Id("nil"),
// 						).Block(G.Return())
// 					}
// 				}),
// 				G.Id("resp").Op("=").Lit(""),
// 				// Cria a rotina de atualização de relacionamentos
// 				// G.Do(func(s *G.Statement) {

// 				// 	if SR.Has(method.Entity) {
// 				// 		createUpdateRelation = true
// 				// 		s.Comment("Cria uma thread que executa a atualizaca das referências.").Line().Go().Func().Params().Block(
// 				// 			G.Id(updRelation).Call(G.Id("filter")),
// 				// 		).Call()

// 				// 	}
// 				// }),

// 				// Envia a resposta pro usuario em caso de sucesso
// 				// G.Line().Id("resp").Op("=").Id(responseEntity).Values(G.Dict{
// 				// 	G.Id("Entity"): G.Id("entity"),
// 				// }),
// 				// G.Line().Id("resp").Op("=").Id("entity"),

// 				// G.Return(G.Nil()),
// 				G.Return(),
// 			).Line()
// 			return nil
// 		},
// 	}
// )
