package maker

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"regexp"

	"gitea.loveuer.com/yizhisec/pkg3/logger"
	"yizhisec.com/hsv2/forge/internal/opt"
	"yizhisec.com/hsv2/forge/pkg/downloader"
)

type RedisOpt func(*redisOpt)

type redisOpt struct {
	ReplicaCount int
	Password     string
	Storage      string
}

func WithRedisReplicaCount(replica int) RedisOpt {
	return func(o *redisOpt) {
		if replica > 0 {
			o.ReplicaCount = replica
		}
	}
}

func WithRedisPassword(password string) RedisOpt {
	return func(o *redisOpt) {
		if password != "" {
			o.Password = password
		}
	}
}

func WithRedisStorage(storage string) RedisOpt {
	return func(o *redisOpt) {
		if matched, _ := regexp.MatchString(`^\d+(\.\d+)?[EPTGMK]i?$`, storage); matched {
			o.Storage = storage
		}
	}
}

func (m *maker) Redis(ctx context.Context, opts ...RedisOpt) error {
	const (
		valuesTemplate = `# Redis configuration
architecture: replication

image:
  registry: docker.io
  repository: bitnami/redis
  tag: 8.2.2
  pullPolicy: IfNotPresent

auth:
  enabled: true
  password: "%s"

master:
  persistence:
    enabled: true
    storageClass: "longhorn"
    size: %s

replica:
  replicaCount: %d
  persistence:
    enabled: true
    storageClass: "longhorn"
    size: %s

metrics:
  enabled: false
  serviceMonitor:
    enabled: false
`
		defaultPassword = "HybridScope0xRed1s."
		chartURL        = "https://artifactory.yizhisec.com:443/artifactory/filestore/hsv3/charts/redis-23.2.2.tgz"
		chartFilename   = "redis-23.2.2.tgz"
	)

	o := &redisOpt{
		ReplicaCount: 2,
		Password:     "HybridScope0xRed1s.",
		Storage:      "5Gi",
	}
	for _, fn := range opts {
		fn(o)
	}

	redisDir := filepath.Join(opt.Cfg.Make.Dir, "dependency", "redis")
	chartFile := filepath.Join(redisDir, chartFilename)
	valuesFile := filepath.Join(redisDir, "values.yaml")

	logger.Info("☑️ maker.Redis: 开始构建 Redis 资源...")
	logger.Debug("☑️ maker.Redis: 开始构建 Redis 资源..., opt = %#v", o)
	logger.Debug("☑️ maker.Redis: 创建目录 %s", redisDir)
	if err := os.MkdirAll(redisDir, 0755); err != nil {
		logger.Debug("❌ maker.Redis: 创建目录失败: %v", err)
		return err
	}
	logger.Debug("✅ maker.Redis: 创建目录 %s 成功", redisDir)

	logger.Debug("☑️ maker.Redis: 下载 Redis chart..., url = %s, dest = %s", chartURL, chartFile)
	if err := downloader.Download(
		ctx,
		chartURL,
		chartFile,
		downloader.WithInsecureSkipVerify(),
	); err != nil {
		logger.Debug("❌ maker.Redis: 下载 Redis chart 失败, url = %s, err = %v", chartURL, err)
		return err
	}
	logger.Debug("✅ maker.Redis: 下载 Redis chart 成功, url = %s", chartURL)

	logger.Debug("☑️ maker.Redis: 写入 values.yaml 文件..., dest = %s", valuesFile)
	bs := fmt.Sprintf(valuesTemplate, o.Password, o.Storage, o.ReplicaCount, o.Storage)
	if err := os.WriteFile(valuesFile, []byte(bs), 0644); err != nil {
		logger.Debug("❌ maker.Redis: 写入 values.yaml 文件失败, dest = %s, err = %v", valuesFile, err)
		return err
	}
	logger.Debug("✅ maker.Redis: 写入 values.yaml 文件成功, dest = %s", valuesFile)

	logger.Info("✅ maker.Redis: 构建 Redis 资源成功!!!")

	return nil
}
