/*
 * Copyright 2026 Oleg Borodin <onborodin@gmail.com>
 */
package filecmd

import (
	"context"
	"errors"
	"fmt"
	"io/fs"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/spf13/cobra"

	"mstore/pkg/filecli"
)

// ImportFiles
type ImportFilesParams struct {
	Source   string
	Dest     string
	Progress bool
	Chart    bool
}
type ImportFilesResult struct {
	Files []string `json:"files,omitempty"`
}

func (util *FileUtil) ImportFiles(cmd *cobra.Command, args []string) {
	util.importFilesParams.Source = args[0]
	util.importFilesParams.Dest = args[1]

	res, err := util.importFiles(&util.commonFileParams, &util.importFilesParams)
	printResponse(res, err)
}

func (util *FileUtil) importFiles(common *CommonFileParams, params *ImportFilesParams) (*ImportFilesResult, error) {
	var err error
	res := &ImportFilesResult{
		Files: make([]string, 0),
	}

	putErrors := make([]error, 0)
	walcFunc := func(walkpath string, infoItem fs.FileInfo, err error) error {
		if err != nil {
			return err
		}
		mode := infoItem.Mode()
		skip := mode == fs.ModeDevice
		skip = skip || mode == fs.ModeNamedPipe
		skip = skip || mode == fs.ModeCharDevice
		if skip {
			return nil
		}

		if !infoItem.IsDir() {
			relpath, _ := strings.CutPrefix(walkpath, params.Source)
			ref, err := filecli.ParsePath(params.Dest)
			if err != nil {
				putErrors = append(putErrors, err)
				return nil
			}
			ref.JoinResource(relpath)
			file, err := os.OpenFile(walkpath, os.O_RDONLY, 0)
			if err != nil {
				putErrors = append(putErrors, err)
				return nil
			}
			defer file.Close()
			stat, err := file.Stat()
			if err != nil {
				putErrors = append(putErrors, err)
				return nil
			}
			timeout := time.Duration(common.Timeout) * time.Second
			ctx, _ := context.WithTimeout(context.Background(), timeout)

			ref.SetUserinfo(common.Username, common.Password)
			mw := filecli.NewBasicAuthMiddleware(ref.Userinfo())

			cli := filecli.NewClient(nil, mw)
			mime := defMediaType
			if params.Chart {
				mime = hcMediaType
			}
			err = cli.PutFile(ctx, ref.Raw(), mime, file, stat.Size())
			if err != nil {
				putErrors = append(putErrors, err)
				fmt.Printf("- %s: error: %v \n", ref.Raw(), err)
			} else {
				res.Files = append(res.Files, relpath)
				fmt.Printf("- %s: ok\n", ref.Raw())
			}
		}
		return nil
	}
	err = filepath.Walk(params.Source, walcFunc)
	if err != nil {
		return res, err
	}

	for _, item := range putErrors {
		err = errors.Join(err, item)
	}
	err = filepath.Walk(params.Source, walcFunc)
	if err != nil {
		return res, err
	}
	return res, err
}
