// Copyright (c) 2022 Alibaba Group Holding Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package plugininit

import (
	"fmt"
	"os"
	"text/template"

	"github.com/AlecAivazis/survey/v2"
	"github.com/alibaba/higress/hgctl/pkg/plugin/types"
)

const (
	goMain = `// File generated by hgctl. Modify as required.
// See: https://higress.io/zh-cn/docs/user/wasm-go#2-%E7%BC%96%E5%86%99-maingo-%E6%96%87%E4%BB%B6

package main

import (
	"github.com/tidwall/gjson"
	"github.com/higress-group/proxy-wasm-go-sdk/proxywasm"
	"github.com/higress-group/proxy-wasm-go-sdk/proxywasm/types"
	"github.com/higress-group/wasm-go/pkg/wrapper"
	logs "github.com/higress-group/wasm-go/pkg/log"
)

func main() {
	wrapper.SetCtx(
		"{{ .Name }}",
		wrapper.ParseConfigBy(parseConfig),
		wrapper.ProcessRequestHeadersBy(onHttpRequestHeaders),
	)
}

// @Name {{ .Name }}
// @Category {{ .Category }}
// @Phase {{ .Phase }}
// @Priority {{ .Priority }}
// @Title {{ .I18nType }} {{ .Title }}
// @Description {{ .I18nType }} {{ .Description }}
// @IconUrl {{ .IconUrl }}
// @Version {{ .Version }}
//
// @Contact.name {{ .ContactName }}
// @Contact.url {{ .ContactUrl }}
// @Contact.email {{ .ContactEmail }}
//
// @Example
// firstField: hello
// secondField: world
// @End
//
type PluginConfig struct {
	// @Title 第一个字段，注解格式为 @Title [语言] [标题]，语言缺省值为 en-US
	// @Description 字符串的前半部分，注解格式为 @Description [语言] [描述]，语言缺省值为 en-US
	firstField string ` + "`required:\"true\"`" + `

	// @Title en-US Second Field, annotation format is @Title [language] [title], language defaults to en-US
	// @Description en-US The second half of the string, annotation format is @Description [language] [description], language defaults to en-US
	secondField string ` + "`required:\"true\"`" + `
}

func parseConfig(json gjson.Result, config *PluginConfig, log logs.Log) error {
	config.firstField = json.Get("firstField").String()
	config.secondField = json.Get("secondField").String()
	return nil
}

func onHttpRequestHeaders(ctx wrapper.HttpContext, config PluginConfig, log logs.Log) types.Action {
	err := proxywasm.AddHttpRequestHeader(config.firstField, config.secondField)
	if err != nil {
		log.Critical("failed to set request header")
	}
	return types.ActionContinue
}
`
	goMod = `// File generated by hgctl. Modify as required.

module {{ .Name }}

go 1.24

require (
	github.com/higress-group/wasm-go main
	github.com/higress-group/proxy-wasm-go-sdk main
	github.com/tidwall/gjson v1.14.3
)
`

	gitIgnore = `# File generated by hgctl. Modify as required.

*

!/.gitignore

!*.go
!go.sum
!go.mod

!LICENSE
!*.md
!*.yaml
!*.yml

!*/

/out
/test
`
)

func genGoMain(ans *answer, dir string) error {
	path := fmt.Sprintf("%s/main.go", dir)
	f, err := os.Create(path)
	if err != nil {
		return err
	}
	defer f.Close()

	if err = template.Must(template.New("GoMain").Parse(goMain)).Execute(f, ans); err != nil {
		return err
	}

	return nil
}

func genGoMod(ans *answer, dir string) error {
	path := fmt.Sprintf("%s/go.mod", dir)
	f, err := os.Create(path)
	if err != nil {
		return err
	}
	defer f.Close()

	if err = template.Must(template.New("GoMod").Parse(goMod)).Execute(f, ans); err != nil {
		return err
	}

	return nil
}

func genGitIgnore(dir string) error {
	path := fmt.Sprintf("%s/.gitignore", dir)
	f, err := os.Create(path)
	if err != nil {
		return err
	}
	defer f.Close()

	if _, err = f.WriteString(gitIgnore); err != nil {
		return err
	}

	return nil
}

// obtain parameters through command line interaction
type answer struct {
	Name        string
	Category    string
	Phase       string
	Priority    int64
	I18nType    string
	Title       string
	Description string
	IconUrl     string
	Version     string

	ContactName  string
	ContactUrl   string
	ContactEmail string
}

var questions = []*survey.Question{
	{
		Name: "Name",
		Prompt: &survey.Input{
			Message: "Plugin name:",
			Default: "hello-world",
		},
		Validate: survey.Required,
	},
	{
		Name: "Category",
		Prompt: &survey.Select{
			Message: "Choose a plugin category:",
			Options: []string{
				string(types.CategoryCustom),
				string(types.CategoryAuth),
				string(types.CategorySecurity),
				string(types.CategoryProtocol),
				string(types.CategoryFlowControl),
				string(types.CategoryFlowMonitor),
			},
			Default: string(types.CategoryCustom),
		},
		Validate: survey.Required,
	},
	{
		Name: "Phase",
		Prompt: &survey.Select{
			Message: "Choose a execution phase:",
			Options: []string{
				string(types.PhaseUnspecified),
				string(types.PhaseAuthn),
				string(types.PhaseAuthz),
				string(types.PhaseStats),
			},
			Default: string(types.PhaseUnspecified),
		},
		Validate: survey.Required,
	},
	{
		Name: "Priority",
		Prompt: &survey.Input{
			Message: "Execution priority:",
			Default: "0",
		},
		Validate: survey.Required,
	},
	{
		Name: "I18nType",
		Prompt: &survey.Select{
			Message: "Choose a language:",
			Options: []string{
				string(types.I18nEN_US),
				string(types.I18nZH_CN),
			},
			Default: string(types.I18nDefault),
		},
		Validate: survey.Required,
	},
	{
		Name: "Title",
		Prompt: &survey.Input{
			Message: "Display name in the plugin market:",
			Default: "Hello World",
		},
		Validate: survey.Required,
	},
	{
		Name: "Description",
		Prompt: &survey.Input{
			Message: "Description of the plugin functionality:",
			Default: "This is a demo plugin",
		},
	},
	{
		Name: "IconUrl",
		Prompt: &survey.Input{
			Message: "Display icon in the plugin market:",
			Default: "",
		},
	},
	{
		Name: "Version",
		Prompt: &survey.Input{
			Message: "Plugin version:",
			Default: "0.1.0",
		},
		Validate: survey.Required,
	},
	{
		Name: "ContactName",
		Prompt: &survey.Input{
			Message: "Name of developer:",
			Default: "",
		},
	},
	{
		Name: "ContactUrl",
		Prompt: &survey.Input{
			Message: "Homepage of developer:",
			Default: "",
		},
	},
	{
		Name: "ContactEmail",
		Prompt: &survey.Input{
			Message: "Email of developer:",
			Default: "",
		},
	},
}
