package hash

import (
	"fmt"

	"helmet/pkg/passwd"

	"github.com/spf13/cobra"
	"sigs.k8s.io/yaml"
)

type Tool struct {
	cmd              *cobra.Command
	createHashParams CreateHashParams
	checkHashParams  CheckHashParams
}

func NewTool() *Tool {
	tool := &Tool{}
	tool.cmd = &cobra.Command{
		Use:   "hash",
		Short: "Hash opeation",
	}
	createHashCmd := &cobra.Command{
		Use:   "create password",
		Args:  cobra.ExactArgs(1),
		Short: "Create authentification hash",
		RunE:  tool.CreateHash,
	}
	checkHashCmd := &cobra.Command{
		Use:   "check password hash",
		Args:  cobra.ExactArgs(2),
		Short: "Check authentification hash",
		RunE:  tool.CheckHash,
	}

	tool.cmd.AddCommand(createHashCmd)
	tool.cmd.AddCommand(checkHashCmd)
	return tool
}

func (tool *Tool) GetCmd() *cobra.Command {
	return tool.cmd
}

type CreateHashParams struct {
	Password string
}
type CreateHashResult struct {
	Hash string `json:"hash"`
}

func (tool *Tool) CreateHash(cmd *cobra.Command, args []string) error {
	tool.createHashParams.Password = args[0]
	res, err := tool.createHash(&tool.createHashParams)
	printResponse(res, err)
	return err
}

func (tool *Tool) createHash(params *CreateHashParams) (*CreateHashResult, error) {
	var err error
	res := &CreateHashResult{}
	if params.Password == "" {
		err = fmt.Errorf("Empty password")
		return res, err
	}
	res.Hash = passwd.MakeSHA256Hash([]byte(params.Password))
	if !passwd.PasswordMatch([]byte(params.Password), res.Hash) {
		err = fmt.Errorf("Error hash validation")
		return res, err
	}
	return res, err
}

type CheckHashParams struct {
	Password string
	Hash     string
}
type CheckHashResult struct {
	Match bool `json:"match"`
}

func (tool *Tool) CheckHash(cmd *cobra.Command, args []string) error {
	tool.checkHashParams.Password = args[0]
	tool.checkHashParams.Hash = args[1]
	res, err := tool.checkHash(&tool.checkHashParams)
	printResponse(res, err)
	return err
}

func (tool *Tool) checkHash(params *CheckHashParams) (*CheckHashResult, error) {
	var err error
	res := &CheckHashResult{}
	if params.Password == "" {
		err = fmt.Errorf("Empty password")
		return res, err
	}
	res.Match = passwd.PasswordMatch([]byte(params.Password), params.Hash)
	return res, err
}

func printResponse(res any, err error) {
	type Response struct {
		Error   bool   `json:"error"             json:"error"`
		Message string `json:"message,omitempty" json:"message,omitempty"`
		Result  any    `json:"result,omitempty"  json:"result,omitempty"`
	}
	resp := Response{}
	if err != nil {
		resp.Error = true
		resp.Message = err.Error()
	} else {
		resp.Result = res
	}
	respBytes, _ := yaml.Marshal(resp)
	fmt.Printf("---\n%s\n", string(respBytes))
}
