package console

import (
	"context"

	"github.com/tidbcloud/dataflow-service/app/models/crrf"
	"github.com/tidbcloud/dataflow-service/app/models/domain"
	"github.com/tidbcloud/dataflow-service/idl/pbgen/proto/dataflow"
	"github.com/tidbcloud/dataflow-service/pkg/log"
	"github.com/tidbcloud/pkgv2/db"
	"go.uber.org/zap"
)

// CRRFController handles CRRF (Cross-Region Replication based Failover) API requests.
type CRRFController interface {
	dataflow.CRRFConsoleServiceServer
}

type crrfControllerImpl struct {
	dataflow.UnimplementedCRRFConsoleServiceServer
	*BaseController

	crrfModel crrf.CRRFModel
}

func NewCRRFController(
	trans db.TransProvider,
	crrfModel crrf.CRRFModel,
) CRRFController {
	return &crrfControllerImpl{
		BaseController: NewBaseController(trans),
		crrfModel:      crrfModel,
	}
}

func (c *crrfControllerImpl) EnableCRRF(
	ctx context.Context, req *dataflow.EnableCRRFRequest,
) (*dataflow.EnableCRRFResponse, error) {
	ctx = log.WithTraceID(ctx)
	logger := log.GetLogger(ctx)

	logger.Info("EnableCRRF request",
		zap.Uint64("clusterID", req.ClusterId),
		zap.String("secondaryRegion", req.SecondaryRegion))

	err := c.crrfModel.EnableCRRF(ctx, &domain.EnableCRRFReq{
		ClusterID:       req.ClusterId,
		ProjectID:       req.ProjectId,
		TenantID:        req.OrgId,
		SecondaryRegion: req.SecondaryRegion,
	})
	if err != nil {
		logger.Error("EnableCRRF failed", zap.Error(err))
		return nil, err
	}

	return &dataflow.EnableCRRFResponse{
		Status:  dataflow.CRRFStatus_CRRF_STATUS_ENABLING,
		Message: "CRRF enable workflow started",
	}, nil
}

func (c *crrfControllerImpl) QueryCRRF(
	ctx context.Context, req *dataflow.QueryCRRFRequest,
) (*dataflow.QueryCRRFResponse, error) {
	ctx = log.WithTraceID(ctx)
	logger := log.GetLogger(ctx)

	info, err := c.crrfModel.QueryCRRF(ctx, req.ClusterId)
	if err != nil {
		logger.Error("QueryCRRF failed", zap.Error(err))
		return nil, err
	}

	return &dataflow.QueryCRRFResponse{
		ClusterId:         info.ClusterID,
		Status:            entityStatusToCRRFProtoStatus(info.Status),
		SecondaryRegion:   info.SecondaryRegion,
		MasterBucketId:    info.MasterBucketID,
		SecondaryBucketId: info.SecondaryBucketID,
		ErrorMessage:      info.ErrorMessage,
	}, nil
}

func (c *crrfControllerImpl) DisableCRRF(
	ctx context.Context, req *dataflow.DisableCRRFRequest,
) (*dataflow.DisableCRRFResponse, error) {
	ctx = log.WithTraceID(ctx)
	logger := log.GetLogger(ctx)

	logger.Info("DisableCRRF request", zap.Uint64("clusterID", req.ClusterId))

	err := c.crrfModel.DisableCRRF(ctx, &domain.DisableCRRFReq{
		ClusterID: req.ClusterId,
		ProjectID: req.ProjectId,
		TenantID:  req.OrgId,
	})
	if err != nil {
		logger.Error("DisableCRRF failed", zap.Error(err))
		return nil, err
	}

	return &dataflow.DisableCRRFResponse{
		Status:  dataflow.CRRFStatus_CRRF_STATUS_DISABLING,
		Message: "CRRF disable workflow started",
	}, nil
}
