package maintenancewindow

import (
	"context"

	tidbmgmtservicev1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_mgmt_service/v1"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
)

func (svc *service) UpdateMaintenanceWindow(
	ctx context.Context,
	req *tidbmgmtservicev1.UpdateMaintenanceWindowRequest,
) (*tidbmgmtservicev1.MaintenanceWindow, bizerr.BizError) {
	ctx, span := tracer.Start(ctx, "Domain.UpdateMaintenanceWindowSvc")
	defer span.End()

	if err := checkUpdateMaintenanceWindow(req); err != nil {
		return nil, err
	}

	// query time zone of tenant
	utcOffset, err := svc.accountCli.GetTimeZoneByProjectID(ctx, req.GetMaintenanceWindow().GetProjectId())
	if err != nil {
		return nil, bizerr.WrapGrpcError(err, "failed to get time zone by project id")
	}

	// if there is no maintenance window, create a new one
	maintenanceWindowWithTimeZone := buildDefaultMaintenanceWindowWithTimeZone(
		req.GetMaintenanceWindow().GetProjectId(),
		utcOffset,
	)
	maintenanceWindowWithTimeZone.WeekDay = req.GetMaintenanceWindow().GetWeekDay()
	maintenanceWindowWithTimeZone.DayHour = req.GetMaintenanceWindow().GetDayHour()
	maintenanceWindowWithTimeZone.HourMinute = req.GetMaintenanceWindow().GetHourMinute()

	window, berr := svc.mwRepo.LoadByProjectID(ctx, req.GetMaintenanceWindow().GetProjectId())
	if berr != nil {
		if berr.RawErrCode() != bizerr.ErrCodeRecordNotFound {
			return nil, berr
		}
	} else {
		maintenanceWindowWithTimeZone.ID = window.ID
	}

	maintenanceWindow := buildMaintenanceWindow(maintenanceWindowWithTimeZone)

	if err := svc.mwRepo.Save(ctx, maintenanceWindow); err != nil {
		return nil, bizerr.WrapGormError(err, "failed to save maintenance window")
	}

	return &maintenanceWindow.MaintenanceWindow, nil
}

func checkUpdateMaintenanceWindow(req *tidbmgmtservicev1.UpdateMaintenanceWindowRequest) bizerr.BizError {
	window := req.MaintenanceWindow
	if window == nil {
		return bizerr.New(bizerr.ErrCodeParams, "maintenance window parameter is required")
	}

	if window.ProjectId == 0 {
		return bizerr.New(bizerr.ErrCodeParams, "project_id is required")
	}

	if window.WeekDay < 0 || window.WeekDay > 6 {
		return bizerr.New(bizerr.ErrCodeParams, "day_of_week must be between 0 and 6")
	}
	if window.DayHour < 0 || window.DayHour > 23 {
		return bizerr.New(bizerr.ErrCodeParams, "hour_of_day must be between 0 and 23")
	}
	if window.HourMinute < 0 || window.HourMinute > 59 {
		return bizerr.New(bizerr.ErrCodeParams, "minute_of_hour must be between 0 and 59")
	}
	return nil
}
