/*
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 (
	"fmt"

	"github.com/pkg/errors"
	"github.com/spf13/cobra"

	k8sclient "sigs.k8s.io/controller-runtime/pkg/client"

	v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
	"github.com/apache/camel-k/pkg/client"
)

func newCmdReset(rootCmdOptions *RootCmdOptions) (*cobra.Command, *resetCmdOptions) {
	options := resetCmdOptions{
		RootCmdOptions: rootCmdOptions,
	}
	cmd := cobra.Command{
		Use:     "reset",
		Short:   "Reset the Camel K installation",
		Long:    `Reset the Camel K installation by deleting everything except current platform configuration.`,
		PreRunE: decode(&options),
		Run:     options.reset,
	}

	cmd.Flags().Bool("skip-kits", false, "Do not delete the integration kits")
	cmd.Flags().Bool("skip-integrations", false, "Do not delete the integrations")

	return &cmd, &options
}

type resetCmdOptions struct {
	*RootCmdOptions
	SkipKits         bool `mapstructure:"skip-kits"`
	SkipIntegrations bool `mapstructure:"skip-integrations"`
}

func (o *resetCmdOptions) reset(_ *cobra.Command, _ []string) {
	c, err := o.GetCmdClient()
	if err != nil {
		fmt.Print(err)
		return
	}

	var n int
	if !o.SkipIntegrations {
		if n, err = o.deleteAllIntegrations(c); err != nil {
			fmt.Print(err)
			return
		}
		fmt.Printf("%d integrations deleted from namespace %s\n", n, o.Namespace)
	}

	if !o.SkipKits {
		if n, err = o.deleteAllIntegrationKits(c); err != nil {
			fmt.Print(err)
			return
		}
		fmt.Printf("%d integration Kits deleted from namespace %s\n", n, o.Namespace)
	}

	if err = o.resetIntegrationPlatform(c); err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println("Camel K platform has been reset successfully!")
}

func (o *resetCmdOptions) deleteAllIntegrations(c client.Client) (int, error) {
	list := v1.NewIntegrationList()
	if err := c.List(o.Context, &list, k8sclient.InNamespace(o.Namespace)); err != nil {
		return 0, errors.Wrap(err, fmt.Sprintf("could not retrieve integrations from namespace %s", o.Namespace))
	}
	for _, i := range list.Items {
		it := i
		if err := c.Delete(o.Context, &it); err != nil {
			return 0, errors.Wrap(err, fmt.Sprintf("could not delete integration %s from namespace %s", it.Name, it.Namespace))
		}
	}
	return len(list.Items), nil
}

func (o *resetCmdOptions) deleteAllIntegrationKits(c client.Client) (int, error) {
	list := v1.NewIntegrationKitList()
	if err := c.List(o.Context, &list, k8sclient.InNamespace(o.Namespace)); err != nil {
		return 0, errors.Wrap(err, fmt.Sprintf("could not retrieve integration Kits from namespace %s", o.Namespace))
	}
	for _, i := range list.Items {
		kit := i
		if err := c.Delete(o.Context, &kit); err != nil {
			return 0, errors.Wrap(err, fmt.Sprintf("could not delete integration kit %s from namespace %s", kit.Name, kit.Namespace))
		}
	}
	return len(list.Items), nil
}

func (o *resetCmdOptions) resetIntegrationPlatform(c client.Client) error {
	list := v1.NewIntegrationPlatformList()
	if err := c.List(o.Context, &list, k8sclient.InNamespace(o.Namespace)); err != nil {
		return errors.Wrap(err, fmt.Sprintf("could not retrieve integration platform from namespace %s", o.Namespace))
	}
	if len(list.Items) > 1 {
		return errors.New(fmt.Sprintf("expected 1 integration platform in the namespace, found: %d", len(list.Items)))
	} else if len(list.Items) == 0 {
		return errors.New("no integration platforms found in the namespace: run \"kamel install\" to install the platform")
	}
	platform := list.Items[0]
	// Let's reset the status
	platform.Status = v1.IntegrationPlatformStatus{}
	return c.Status().Update(o.Context, &platform)
}
