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

	"github.com/spf13/viper"

	"github.com/apache/camel-k/pkg/util/olm"
	"github.com/pkg/errors"
	"k8s.io/client-go/kubernetes"

	"github.com/apache/camel-k/pkg/client"
	"github.com/apache/camel-k/pkg/util/kubernetes/customclient"
	"github.com/spf13/cobra"
	k8serrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func newCmdUninstall(rootCmdOptions *RootCmdOptions) (*cobra.Command, *uninstallCmdOptions) {
	options := uninstallCmdOptions{
		RootCmdOptions: rootCmdOptions,
	}

	cmd := cobra.Command{
		Use:     "uninstall",
		Short:   "Uninstall Camel K from a Kubernetes cluster",
		Long:    `Uninstalls Camel K from a Kubernetes or OpenShift cluster.`,
		PreRunE: options.decode,
		RunE:    options.uninstall,
	}

	cmd.Flags().Bool("skip-operator", false, "Do not uninstall the Camel K Operator in the current namespace")
	cmd.Flags().Bool("skip-crd", true, "Do not uninstall the Camel K Custom Resource Definitions (CRD)")
	cmd.Flags().Bool("skip-role-bindings", false, "Do not uninstall the Camel K Role Bindings in the current namespace")
	cmd.Flags().Bool("skip-roles", false, "Do not uninstall the Camel K Roles in the current namespace")
	cmd.Flags().Bool("skip-cluster-role-bindings", true, "Do not uninstall the Camel K Cluster Role Bindings")
	cmd.Flags().Bool("skip-cluster-roles", true, "Do not uninstall the Camel K Cluster Roles")
	cmd.Flags().Bool("skip-integration-platform", false, "Do not uninstall the Camel K Integration Platform in the current namespace")
	cmd.Flags().Bool("skip-service-accounts", false, "Do not uninstall the Camel K Service Accounts in the current namespace")
	cmd.Flags().Bool("skip-config-maps", false, "Do not uninstall the Camel K Config Maps in the current namespace")
	cmd.Flags().Bool("global", false, "Indicates that a global installation is going to be uninstalled (affects OLM)")
	cmd.Flags().Bool("olm", true, "Try to uninstall via OLM (Operator Lifecycle Manager) if available")
	cmd.Flags().String("olm-operator-name", olm.DefaultOperatorName, "Name of the Camel K operator in the OLM source or marketplace")
	cmd.Flags().String("olm-package", olm.DefaultPackage, "Name of the Camel K package in the OLM source or marketplace")
	cmd.Flags().String("olm-global-namespace", olm.DefaultGlobalNamespace, "A namespace containing an OperatorGroup that defines "+
		"global scope for the operator (used in combination with the --global flag)")
	cmd.Flags().Bool("all", false, "Do uninstall all Camel K resources")

	return &cmd, &options
}

type uninstallCmdOptions struct {
	*RootCmdOptions
	SkipOperator            bool `mapstructure:"skip-operator"`
	SkipCrd                 bool `mapstructure:"skip-crd"`
	SkipRoleBindings        bool `mapstructure:"skip-role-bindings"`
	SkipRoles               bool `mapstructure:"skip-roles"`
	SkipClusterRoleBindings bool `mapstructure:"skip-cluster-role-bindings"`
	SkipClusterRoles        bool `mapstructure:"skip-cluster-roles"`
	SkipIntegrationPlatform bool `mapstructure:"skip-integration-platform"`
	SkipServiceAccounts     bool `mapstructure:"skip-service-accounts"`
	SkipConfigMaps          bool `mapstructure:"skip-config-maps"`
	Global                  bool `mapstructure:"global"`
	OlmEnabled              bool `mapstructure:"olm"`
	UninstallAll            bool `mapstructure:"all"`

	OlmOptions olm.Options
}

var defaultListOptions = metav1.ListOptions{
	LabelSelector: "app=camel-k",
}

func (o *uninstallCmdOptions) decode(cmd *cobra.Command, _ []string) error {
	path := pathToRoot(cmd)
	if err := decodeKey(o, path); err != nil {
		return err
	}

	o.OlmOptions.OperatorName = viper.GetString(path + ".olm-operator-name")
	o.OlmOptions.Package = viper.GetString(path + ".olm-package")
	o.OlmOptions.GlobalNamespace = viper.GetString(path + ".olm-global-namespace")

	return nil
}

// nolint: gocyclo
func (o *uninstallCmdOptions) uninstall(cmd *cobra.Command, _ []string) error {
	c, err := o.GetCmdClient()
	if err != nil {
		return err
	}

	uninstallViaOLM := false
	if o.OlmEnabled {
		var err error
		if uninstallViaOLM, err = olm.IsAPIAvailable(o.Context, c, o.Namespace); err != nil {
			return errors.Wrap(err, "error while checking OLM availability. Run with '--olm=false' to skip this check")
		}

		if uninstallViaOLM {
			fmt.Fprintln(cmd.OutOrStdout(), "OLM is available in the cluster")
			if err = olm.Uninstall(o.Context, c, o.Namespace, o.Global, o.OlmOptions); err != nil {
				return err
			}
			where := fmt.Sprintf("from namespace %s", o.Namespace)
			if o.Global {
				where = "globally"
			}
			fmt.Fprintf(cmd.OutOrStdout(), "Camel K OLM service removed %s\n", where)
		}
	}

	if !o.SkipIntegrationPlatform {
		if err = o.uninstallIntegrationPlatform(o.Context); err != nil {
			return err
		}
		fmt.Fprintf(cmd.OutOrStdout(), "Camel K Integration Platform removed from namespace %s\n", o.Namespace)
	}

	if err = o.uninstallNamespaceResources(o.Context, c); err != nil {
		return err
	}

	if !uninstallViaOLM {
		if !o.SkipOperator {
			if err = o.uninstallOperator(o.Context, c); err != nil {
				return err
			}
			fmt.Fprintf(cmd.OutOrStdout(), "Camel K Operator removed from namespace %s\n", o.Namespace)
		}

		if err = o.uninstallNamespaceRoles(o.Context, c); err != nil {
			return err
		}

		if err = o.uninstallClusterWideResources(o.Context, c); err != nil {
			return err
		}

	}

	return nil
}

func (o *uninstallCmdOptions) uninstallOperator(ctx context.Context, c client.Client) error {
	api := c.AppsV1()

	deployments, err := api.Deployments(o.Namespace).List(ctx, defaultListOptions)
	if err != nil {
		return err
	}

	for _, deployment := range deployments.Items {
		err := api.Deployments(o.Namespace).Delete(ctx, deployment.Name, metav1.DeleteOptions{})
		if err != nil {
			return err
		}
	}

	return nil
}

func (o *uninstallCmdOptions) uninstallClusterWideResources(ctx context.Context, c client.Client) error {
	if !o.SkipCrd || o.UninstallAll {
		if err := o.uninstallCrd(ctx, c); err != nil {
			if k8serrors.IsForbidden(err) {
				return createActionNotAuthorizedError()
			}
			return err
		}
		fmt.Printf("Camel K Custom Resource Definitions removed from cluster\n")
	}

	if !o.SkipClusterRoleBindings || o.UninstallAll {
		if err := o.uninstallClusterRoleBindings(ctx, c); err != nil {
			if k8serrors.IsForbidden(err) {
				return createActionNotAuthorizedError()
			}
			return err
		}
		fmt.Printf("Camel K Cluster Role Bindings removed from cluster\n")
	}

	if !o.SkipClusterRoles || o.UninstallAll {
		if err := o.uninstallClusterRoles(ctx, c); err != nil {
			if k8serrors.IsForbidden(err) {
				return createActionNotAuthorizedError()
			}
			return err
		}
		fmt.Printf("Camel K Cluster Roles removed from cluster\n")
	}

	return nil
}

func (o *uninstallCmdOptions) uninstallNamespaceRoles(ctx context.Context, c client.Client) error {
	if !o.SkipRoleBindings {
		if err := o.uninstallRoleBindings(ctx, c); err != nil {
			return err
		}
		fmt.Printf("Camel K Role Bindings removed from namespace %s\n", o.Namespace)
	}

	if !o.SkipRoles {
		if err := o.uninstallRoles(ctx, c); err != nil {
			return err
		}
		fmt.Printf("Camel K Roles removed from namespace %s\n", o.Namespace)
	}

	if !o.SkipServiceAccounts {
		if err := o.uninstallServiceAccounts(ctx, c); err != nil {
			return err
		}
		fmt.Printf("Camel K Service Accounts removed from namespace %s\n", o.Namespace)
	}

	return nil
}

func (o *uninstallCmdOptions) uninstallNamespaceResources(ctx context.Context, c client.Client) error {
	if !o.SkipConfigMaps {
		if err := o.uninstallConfigMaps(ctx, c); err != nil {
			return err
		}
		fmt.Printf("Camel K Config Maps removed from namespace %s\n", o.Namespace)
	}

	return nil
}

func (o *uninstallCmdOptions) uninstallCrd(ctx context.Context, c kubernetes.Interface) error {
	restClient, err := customclient.GetClientFor(c, "apiextensions.k8s.io", "v1beta1")
	if err != nil {
		return err
	}

	result := restClient.
		Delete().
		Param("labelSelector", "app=camel-k").
		Resource("customresourcedefinitions").
		Do(ctx)

	if result.Error() != nil {
		return result.Error()
	}

	return nil
}

func (o *uninstallCmdOptions) uninstallRoles(ctx context.Context, c client.Client) error {
	api := c.RbacV1()

	roleBindings, err := api.Roles(o.Namespace).List(ctx, defaultListOptions)
	if err != nil {
		return err
	}

	for _, roleBinding := range roleBindings.Items {
		err := api.Roles(o.Namespace).Delete(ctx, roleBinding.Name, metav1.DeleteOptions{})
		if err != nil {
			return err
		}
	}

	return nil
}

func (o *uninstallCmdOptions) uninstallRoleBindings(ctx context.Context, c client.Client) error {
	api := c.RbacV1()

	roleBindings, err := api.RoleBindings(o.Namespace).List(ctx, defaultListOptions)
	if err != nil {
		return err
	}

	for _, roleBinding := range roleBindings.Items {
		err := api.RoleBindings(o.Namespace).Delete(ctx, roleBinding.Name, metav1.DeleteOptions{})
		if err != nil {
			return err
		}
	}

	return nil
}

func (o *uninstallCmdOptions) uninstallClusterRoles(ctx context.Context, c client.Client) error {
	api := c.RbacV1()

	clusterRoles, err := api.ClusterRoles().List(ctx, defaultListOptions)
	if err != nil {
		return err
	}

	for _, clusterRole := range clusterRoles.Items {
		err := api.ClusterRoles().Delete(ctx, clusterRole.Name, metav1.DeleteOptions{})
		if err != nil {
			return err
		}
	}

	return nil
}

func (o *uninstallCmdOptions) uninstallClusterRoleBindings(ctx context.Context, c client.Client) error {
	api := c.RbacV1()

	clusterRoleBindings, err := api.ClusterRoleBindings().List(ctx, defaultListOptions)
	if err != nil {
		return err
	}

	for _, clusterRoleBinding := range clusterRoleBindings.Items {
		err := api.ClusterRoleBindings().Delete(ctx, clusterRoleBinding.Name, metav1.DeleteOptions{})
		if err != nil {
			return err
		}
	}

	return nil
}

func (o *uninstallCmdOptions) uninstallServiceAccounts(ctx context.Context, c client.Client) error {
	api := c.CoreV1()

	serviceAccountList, err := api.ServiceAccounts(o.Namespace).List(ctx, defaultListOptions)
	if err != nil {
		return err
	}

	for _, serviceAccount := range serviceAccountList.Items {
		err := api.ServiceAccounts(o.Namespace).Delete(ctx, serviceAccount.Name, metav1.DeleteOptions{})
		if err != nil {
			return err
		}
	}

	return nil
}

func (o *uninstallCmdOptions) uninstallIntegrationPlatform(ctx context.Context) error {
	api, err := customclient.GetDefaultDynamicClientFor("integrationplatforms", o.Namespace)
	if err != nil {
		return err
	}

	integrationPlatforms, err := api.List(ctx, defaultListOptions)
	if err != nil {
		return err
	}

	for _, integrationPlatform := range integrationPlatforms.Items {
		err := api.Delete(ctx, integrationPlatform.GetName(), metav1.DeleteOptions{})
		if err != nil {
			return err
		}
	}

	return nil
}

func (o *uninstallCmdOptions) uninstallConfigMaps(ctx context.Context, c client.Client) error {
	api := c.CoreV1()

	configMapsList, err := api.ConfigMaps(o.Namespace).List(ctx, defaultListOptions)
	if err != nil {
		return err
	}

	for _, configMap := range configMapsList.Items {
		err := api.ConfigMaps(o.Namespace).Delete(ctx, configMap.Name, metav1.DeleteOptions{})
		if err != nil {
			return err
		}
	}

	return nil
}

func createActionNotAuthorizedError() error {
	fmt.Println("Current user is not authorized to remove cluster-wide objects like custom resource definitions or cluster roles")
	msg := `login as cluster-admin and execute "kamel uninstall" or use flags "--skip-crd --skip-cluster-roles --skip-cluster-role-bindings"`
	return errors.New(msg)
}
