// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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 cmd

import (
	"errors"
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

import (
	"github.com/spf13/cobra"

	"go.uber.org/zap/zapcore"
)

import (
	"github.com/apache/dubbo-kubernetes/app/dubboctl/internal/kube"
	"github.com/apache/dubbo-kubernetes/pkg/core/logger"
)

type ManifestDiffArgs struct {
	CompareDir bool
}

func ConfigManifestDiffCmd(baseCmd *cobra.Command) {
	mdArgs := &ManifestDiffArgs{}
	mdCmd := &cobra.Command{
		Use:   "diff",
		Short: "show the difference between two files or dirs",
		Example: `  # show the difference between two files
  dubboctl manifest diff fileA fileB
  # show the difference between two dirs
  dubboctl manifest diff dirA dirB --compareDir=true
`,
		Args: func(cmd *cobra.Command, args []string) error {
			if len(args) != 2 {
				return fmt.Errorf("manifest diff needs two files or dirs")
			}
			return nil
		},
		RunE: func(cmd *cobra.Command, args []string) error {
			logger.InitCmdSugar(zapcore.AddSync(cmd.OutOrStdout()))
			if err := compare(args, mdArgs); err != nil {
				return err
			}
			return nil
		},
	}
	mdCmd.PersistentFlags().BoolVarP(&mdArgs.CompareDir, "compareDir", "", false,
		"Indicate whether compare two dirs or two files")

	baseCmd.AddCommand(mdCmd)
}

func compare(args []string, mdArgs *ManifestDiffArgs) error {
	var res string
	var err error
	if mdArgs.CompareDir {
		res, err = compareDirs(args[0], args[1])
	} else {
		res, err = compareFiles(args[0], args[1])
	}
	if err != nil {
		return err
	}
	logger.CmdSugar().Print(res)
	return nil
}

func compareDirs(dirA, dirB string) (string, error) {
	filesA, err := os.ReadDir(dirA)
	if err != nil {
		return "", err
	}
	filesB, err := os.ReadDir(dirB)
	if err != nil {
		return "", err
	}
	createFileMap := func(dir string, files []os.DirEntry) (map[string]struct{}, error) {
		res := make(map[string]struct{})
		for _, file := range files {
			if file.IsDir() {
				return nil, errors.New("do not support recursive traversal")
			}
			res[file.Name()] = struct{}{}
		}
		return res, nil
	}
	mapA, err := createFileMap(dirA, filesA)
	if err != nil {
		return "", err
	}
	mapB, err := createFileMap(dirB, filesB)
	if err != nil {
		return "", err
	}
	var diffBuilder strings.Builder
	var addBuilder strings.Builder
	var errBuilder strings.Builder
	for file := range mapA {
		if _, ok := mapB[file]; ok {
			fileA := filepath.Join(dirA, file)
			fileB := filepath.Join(dirB, file)
			res, err := compareFiles(fileA, fileB)
			if err != nil {
				errBuilder.WriteString(err.Error() + "\n")
				continue
			}
			if res != "" {
				diffBuilder.WriteString(fmt.Sprintf("%s---%s\n", fileA, fileB))
				diffBuilder.WriteString(res + "\n")
			}
		} else {
			addBuilder.WriteString(fmt.Sprintf("%s doesn't exist in %s\n", file, dirB))
		}
	}
	for file := range mapB {
		if _, ok := mapA[file]; !ok {
			addBuilder.WriteString(fmt.Sprintf("%s doesn't exist in %s\n", file, dirA))
		}
	}
	errRes := errBuilder.String()
	if errRes != "" {
		errRes = "------parse error------\n" + errRes + "\n"
	}
	addRes := addBuilder.String()
	if addRes != "" {
		addRes = "------addition------\n" + addRes + "\n"
	}
	diffRes := diffBuilder.String()
	if diffRes != "" {
		diffRes = "------diff------\n" + diffRes + "\n"
	}

	var final string
	if errRes == "" && addRes == "" && diffRes == "" {
		final = "two dirs are identical\n"
	} else {
		final = errRes + addRes + diffRes
	}

	return final, nil
}

func compareFiles(fileA, fileB string) (string, error) {
	bytesA, err := os.ReadFile(fileA)
	if err != nil {
		return "", fmt.Errorf("read %s failed, err: %s", fileA, err)
	}
	bytesB, err := os.ReadFile(fileB)
	if err != nil {
		return "", fmt.Errorf("read %s failed, err: %s", fileB, err)
	}
	objsA, err := kube.ParseObjectsFromManifest(string(bytesA), false)
	if err != nil {
		return "", fmt.Errorf("parse %s failed, err: %s", fileA, err)
	}
	objsB, err := kube.ParseObjectsFromManifest(string(bytesB), false)
	if err != nil {
		return "", fmt.Errorf("parse %s failed, err: %s", fileA, err)
	}
	diffRes, addRes, errRes := kube.CompareObjects(objsA, objsB)

	return diffRes + addRes + errRes, nil
}
