package svc

import (
	"backend/internal/config"
	mgo "backend/pkg/library/mongo"
	cfg "backend/pkg/member/domain/config"
	"backend/pkg/member/domain/usecase"
	"backend/pkg/member/repository"
	uc "backend/pkg/member/usecase"
	"context"

	"github.com/zeromicro/go-zero/core/logx"

	"github.com/zeromicro/go-zero/core/stores/cache"
	"github.com/zeromicro/go-zero/core/stores/mon"
	"github.com/zeromicro/go-zero/core/stores/redis"
)

func NewAccountUC(c *config.Config, rds *redis.Redis) usecase.AccountUseCase {
	// 準備Mongo Config
	conf := &mgo.Conf{
		Schema:                           c.Mongo.Schema,
		Host:                             c.Mongo.Host,
		Database:                         c.Mongo.Database,
		MaxStaleness:                     c.Mongo.MaxStaleness,
		MaxPoolSize:                      c.Mongo.MaxPoolSize,
		MinPoolSize:                      c.Mongo.MinPoolSize,
		MaxConnIdleTime:                  c.Mongo.MaxConnIdleTime,
		Compressors:                      c.Mongo.Compressors,
		EnableStandardReadWriteSplitMode: c.Mongo.EnableStandardReadWriteSplitMode,
		ConnectTimeoutMs:                 c.Mongo.ConnectTimeoutMs,
	}
	if c.Mongo.User != "" {
		conf.User = c.Mongo.User
		conf.Password = c.Mongo.Password
	}

	// 快取選項
	cacheOpts := []cache.Option{
		cache.WithExpiry(c.CacheExpireTime),
		cache.WithNotFoundExpiry(c.CacheWithNotFoundExpiry),
	}
	dbOpts := []mon.Option{
		mgo.SetCustomDecimalType(),
		mgo.InitMongoOptions(*conf),
	}

	ac := repository.NewAccountRepository(repository.AccountRepositoryParam{
		Conf:      conf,
		CacheConf: c.Cache,
		CacheOpts: cacheOpts,
		DBOpts:    dbOpts,
	})

	u := repository.NewUserRepository(repository.UserRepositoryParam{
		Conf:      conf,
		CacheConf: c.Cache,
		CacheOpts: cacheOpts,
		DBOpts:    dbOpts,
	})
	guid := repository.NewAutoIDRepository(repository.AutoIDRepositoryParam{
		Conf:   conf,
		DBOpts: dbOpts,
	})
	auid := repository.NewAccountUIDRepository(repository.AccountUIDRepositoryParam{
		Conf:      conf,
		CacheConf: c.Cache,
		CacheOpts: cacheOpts,
		DBOpts:    dbOpts,
	})

	_, _ = ac.Index20241226001UP(context.Background())
	_, _ = u.Index20241226001UP(context.Background())
	_, _ = guid.Index20241226001UP(context.Background())
	_, _ = auid.Index20241226001UP(context.Background())

	return uc.MustMemberUseCase(uc.MemberUseCaseParam{
		Account:         ac,
		User:            u,
		AccountUID:      auid,
		VerifyCodeModel: repository.NewVerifyCodeRepository(rds),
		GenerateUID:     guid,
		Config:          prepareCfg(c),
		Logger:          MustLogger(logx.WithContext(context.Background())),
	})
}

func prepareCfg(c *config.Config) cfg.Config {
	return cfg.Config{
		Bcrypt: struct{ Cost int }{Cost: c.Bcrypt.Cost},
		GoogleAuth: struct {
			ClientID string
			AuthURL  string
		}{
			ClientID: c.GoogleAuth.ClientID,
			AuthURL:  c.GoogleAuth.AuthURL,
		},

		LineAuth: struct {
			ClientID     string
			ClientSecret string
			RedirectURI  string
		}{
			ClientID:     c.LineAuth.ClientID,
			ClientSecret: c.LineAuth.ClientSecret,
			RedirectURI:  c.LineAuth.RedirectURI,
		},
	}
}
