/*
   Copyright The containerd Authors.

   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 images

import (
	"context"
	"fmt"
	"path/filepath"
	"runtime"

	containerd "github.com/containerd/containerd/v2/client"
	"github.com/containerd/containerd/v2/core/metadata"
	"github.com/containerd/containerd/v2/core/snapshots"
	"github.com/containerd/containerd/v2/core/transfer"
	criconfig "github.com/containerd/containerd/v2/internal/cri/config"
	"github.com/containerd/containerd/v2/internal/cri/constants"
	"github.com/containerd/containerd/v2/internal/cri/server/images"
	"github.com/containerd/containerd/v2/plugins"
	"github.com/containerd/containerd/v2/plugins/services/warning"
	"github.com/containerd/containerd/v2/version"
	"github.com/containerd/log"
	"github.com/containerd/platforms"
	"github.com/containerd/plugin"
	"github.com/containerd/plugin/registry"
)

func init() {
	config := criconfig.DefaultImageConfig()

	registry.Register(&plugin.Registration{
		Type:   plugins.CRIServicePlugin,
		ID:     "images",
		Config: &config,
		Requires: []plugin.Type{
			plugins.LeasePlugin,
			plugins.MetadataPlugin,
			plugins.SandboxStorePlugin,
			plugins.ServicePlugin,  // For client
			plugins.SnapshotPlugin, // For root directory properties
			plugins.TransferPlugin, // For pulling image using transfer service
			plugins.WarningPlugin,
		},
		InitFn: func(ic *plugin.InitContext) (interface{}, error) {
			m, err := ic.GetSingle(plugins.MetadataPlugin)
			if err != nil {
				return nil, err
			}
			mdb := m.(*metadata.DB)

			if warnings, err := criconfig.ValidateImageConfig(ic.Context, &config); err != nil {
				return nil, fmt.Errorf("invalid cri image config: %w", err)
			} else if len(warnings) > 0 {
				ws, err := ic.GetSingle(plugins.WarningPlugin)
				if err != nil {
					return nil, err
				}
				warn := ws.(warning.Service)
				for _, w := range warnings {
					warn.Emit(ic.Context, w)
				}
			}

			if !config.UseLocalImagePull {
				criconfig.CheckLocalImagePullConfigs(ic.Context, &config)
			}

			ts, err := ic.GetSingle(plugins.TransferPlugin)
			if err != nil {
				return nil, err
			}

			options := &images.CRIImageServiceOptions{
				Content:          mdb.ContentStore(),
				RuntimePlatforms: map[string]images.ImagePlatform{},
				Snapshotters:     map[string]snapshots.Snapshotter{},
				ImageFSPaths:     map[string]string{},
				Transferrer:      ts.(transfer.Transferrer),
			}

			ctrdCli, err := containerd.New(
				"",
				containerd.WithDefaultNamespace(constants.K8sContainerdNamespace),
				containerd.WithDefaultPlatform(platforms.Default()),
				containerd.WithInMemoryServices(ic),
			)
			if err != nil {
				return nil, fmt.Errorf("unable to init client for cri image service: %w", err)
			}
			options.Images = ctrdCli.ImageService()
			options.Client = ctrdCli

			allSnapshotters := mdb.Snapshotters()
			defaultSnapshotter := config.Snapshotter
			if s, ok := allSnapshotters[defaultSnapshotter]; ok {
				options.Snapshotters[defaultSnapshotter] = s
			} else {
				return nil, fmt.Errorf("failed to find snapshotter %q", defaultSnapshotter)
			}

			snapshotRoot := func(snapshotter string) (snapshotRoot string) {
				if plugin := ic.Plugins().Get(plugins.SnapshotPlugin, snapshotter); plugin != nil {
					snapshotRoot = plugin.Meta.Exports["root"]
				}
				if snapshotRoot == "" {
					// Try a root in the same parent as this plugin
					snapshotRoot = filepath.Join(filepath.Dir(ic.Properties[plugins.PropertyRootDir]), plugins.SnapshotPlugin.String()+"."+snapshotter)
				}
				return snapshotRoot
			}

			options.ImageFSPaths[defaultSnapshotter] = snapshotRoot(defaultSnapshotter)
			log.L.Infof("Get image filesystem path %q for snapshotter %q", options.ImageFSPaths[defaultSnapshotter], defaultSnapshotter)

			for runtimeName, rp := range config.RuntimePlatforms {
				snapshotter := rp.Snapshotter
				if snapshotter == "" {
					snapshotter = defaultSnapshotter
				}

				if _, ok := options.ImageFSPaths[snapshotter]; !ok {
					options.ImageFSPaths[snapshotter] = snapshotRoot(snapshotter)
					log.L.Infof("Get image filesystem path %q for snapshotter %q", options.ImageFSPaths[snapshotter], snapshotter)
				}

				platform := platforms.DefaultSpec()
				if rp.Platform != "" {
					p, err := platforms.Parse(rp.Platform)
					if err != nil {
						return nil, fmt.Errorf("unable to parse platform %q: %w", rp.Platform, err)
					}
					platform = p
				}

				options.RuntimePlatforms[runtimeName] = images.ImagePlatform{
					Snapshotter: snapshotter,
					Platform:    platform,
				}
			}

			service, err := images.NewService(config, options)
			if err != nil {
				return nil, fmt.Errorf("failed to create image service: %w", err)
			}

			return service, nil
		},
		ConfigMigration: configMigration,
	})
}

func configMigration(ctx context.Context, configVersion int, pluginConfigs map[string]interface{}) error {
	if configVersion >= version.ConfigVersion {
		return nil
	}
	original, ok := pluginConfigs[string(plugins.GRPCPlugin)+".cri"]
	if !ok {
		return nil
	}
	src := original.(map[string]interface{})
	updated, ok := pluginConfigs[string(plugins.CRIServicePlugin)+".images"]
	var dst map[string]interface{}
	if ok {
		dst = updated.(map[string]interface{})
	} else {
		dst = map[string]interface{}{}
	}

	migrateConfig(dst, src)
	pluginConfigs[string(plugins.CRIServicePlugin)+".images"] = dst
	return nil
}
func migrateConfig(dst, src map[string]interface{}) {
	var pinnedImages map[string]interface{}
	if v, ok := dst["pinned_images"]; ok {
		pinnedImages = v.(map[string]interface{})
	} else {
		pinnedImages = map[string]interface{}{}
	}

	if simage, ok := src["sandbox_image"]; ok {
		pinnedImages["sandbox"] = simage
	}
	if len(pinnedImages) > 0 {
		dst["pinned_images"] = pinnedImages
	}

	for _, key := range []string{
		"registry",
		"image_decryption",
		"max_concurrent_downloads",
		"image_pull_progress_timeout",
		"image_pull_with_sync_fs",
		"stats_collect_period",
	} {
		if val, ok := src[key]; ok {
			dst[key] = val
		}
	}
	if runtime.GOOS == "linux" {
		if value, ok := dst["registry"]; ok {
			regMap := value.(map[string]any)
			if configPath, ok := regMap["config_path"]; ok {
				if configPath == "" {
					// Fill in default from config_unix.go (DefaultImageConfig)
					regMap["config_path"] = "/etc/containerd/certs.d:/etc/docker/certs.d"
				}
			}
			dst["registry"] = regMap
		}
	}

	containerdConf, ok := src["containerd"]
	if !ok {
		return
	}
	containerdConfMap := containerdConf.(map[string]interface{})
	runtimesConf, ok := containerdConfMap["runtimes"]
	if !ok {
		return
	}

	var runtimePlatforms map[string]interface{}
	if v, ok := dst["runtime_platform"]; ok {
		runtimePlatforms = v.(map[string]interface{})
	} else {
		runtimePlatforms = map[string]interface{}{}
	}
	for runtime, v := range runtimesConf.(map[string]interface{}) {
		runtimeConf := v.(map[string]interface{})
		if snapshotter, ok := runtimeConf["snapshot"]; ok && snapshotter != "" {
			runtimePlatforms[runtime] = map[string]interface{}{
				"platform":    platforms.DefaultStrict(),
				"snapshotter": snapshotter,
			}
		}
	}
	if len(runtimePlatforms) > 0 {
		dst["runtime_platform"] = runtimePlatforms
	}

	for _, key := range []string{
		"snapshotter",
		"disable_snapshot_annotations",
		"discard_unpacked_layers",
	} {
		if val, ok := containerdConfMap[key]; ok {
			dst[key] = val
		}
	}
}
