/*
 * Copyright 2025 coze-dev Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Code generated by hertz generator.

package coze

import (
	"context"
	"strconv"

	"github.com/coze-dev/coze-studio/backend/api/model/ocean/cloud/workflow"
	appworkflow "github.com/coze-dev/coze-studio/backend/application/workflow"

	"github.com/cloudwego/hertz/pkg/app"
	"github.com/cloudwego/hertz/pkg/protocol/consts"

	"github.com/coze-dev/coze-studio/backend/api/model/ocean/cloud/developer_api"

	"github.com/coze-dev/coze-studio/backend/api/model/flow/marketplace/product_common"
	"github.com/coze-dev/coze-studio/backend/api/model/flow/marketplace/product_public_api"
	"github.com/coze-dev/coze-studio/backend/api/model/ocean/cloud/bot_common"
	"github.com/coze-dev/coze-studio/backend/api/model/ocean/cloud/playground"
	appApplication "github.com/coze-dev/coze-studio/backend/application/app"
	"github.com/coze-dev/coze-studio/backend/application/modelmgr"
	"github.com/coze-dev/coze-studio/backend/application/plugin"
	"github.com/coze-dev/coze-studio/backend/application/search"
	"github.com/coze-dev/coze-studio/backend/application/singleagent"
	"github.com/coze-dev/coze-studio/backend/application/template"
)

// PublicGetProductList .
// @router /api/marketplace/product/list [GET]
func PublicGetProductList(ctx context.Context, c *app.RequestContext) {
	var err error
	var req product_public_api.GetProductListRequest
	err = c.BindAndValidate(&req)
	if err != nil {
		invalidParamRequestResponse(c, err.Error())
		return
	}

	var resp *product_public_api.GetProductListResponse
	switch req.GetEntityType() {
	case product_common.ProductEntityType_Plugin:
		resp, err = plugin.PluginApplicationSVC.PublicGetProductList(ctx, &req)
		if err != nil {
			internalServerErrorResponse(ctx, c, err)
			return
		}

	case product_common.ProductEntityType_TemplateCommon:
		resp, err = template.ApplicationSVC.PublicGetProductList(ctx, &req)
		if err != nil {
			internalServerErrorResponse(ctx, c, err)
			return
		}
	}

	c.JSON(consts.StatusOK, resp)
}

// PublicGetProductDetail .
// @router /api/marketplace/product/detail [GET]
func PublicGetProductDetail(ctx context.Context, c *app.RequestContext) {
	var err error
	var req product_public_api.GetProductDetailRequest
	err = c.BindAndValidate(&req)
	if err != nil {
		invalidParamRequestResponse(c, err.Error())
		return
	}

	if req.GetProductID() <= 0 {
		invalidParamRequestResponse(c, "productID is invalid")
		return
	}

	resp, err := plugin.PluginApplicationSVC.PublicGetProductDetail(ctx, &req)
	if err != nil {
		internalServerErrorResponse(ctx, c, err)
		return
	}

	c.JSON(consts.StatusOK, resp)
}

// PublicFavoriteProduct .
// @router /api/marketplace/product/favorite [POST]
func PublicFavoriteProduct(ctx context.Context, c *app.RequestContext) {
	var err error
	var req product_public_api.FavoriteProductRequest
	err = c.BindAndValidate(&req)
	if err != nil {
		invalidParamRequestResponse(c, err.Error())
		return
	}

	if req.GetEntityID() <= 0 {
		invalidParamRequestResponse(c, "entityID is invalid")
		return
	}

	// check entity id is valid
	if req.GetEntityType() == product_common.ProductEntityType_Bot {
		_, err = singleagent.SingleAgentSVC.ValidateAgentDraftAccess(ctx, req.GetEntityID())
	} else if req.GetEntityType() == product_common.ProductEntityType_Project {
		_, err = appApplication.APPApplicationSVC.ValidateDraftAPPAccess(ctx, req.GetEntityID())
	}

	if err != nil {
		internalServerErrorResponse(ctx, c, err)
		return
	}

	resp, err := search.SearchSVC.PublicFavoriteProduct(ctx, &req)
	if err != nil {
		internalServerErrorResponse(ctx, c, err)
		return
	}

	c.JSON(consts.StatusOK, resp)
}

// PublicGetUserFavoriteListV2 .
// @router /api/marketplace/product/favorite/list.v2 [GET]
func PublicGetUserFavoriteListV2(ctx context.Context, c *app.RequestContext) {
	var err error
	var req product_public_api.GetUserFavoriteListV2Request
	err = c.BindAndValidate(&req)
	if err != nil {
		invalidParamRequestResponse(c, err.Error())
		return
	}

	if req.GetPageSize() <= 0 {
		invalidParamRequestResponse(c, "pageSize is invalid")
		return
	}
	if req.GetEntityType() <= 0 {
		invalidParamRequestResponse(c, "entityType is invalid")
		return
	}

	resp, err := search.SearchSVC.PublicGetUserFavoriteList(ctx, &req)
	if err != nil {
		internalServerErrorResponse(ctx, c, err)
		return
	}

	c.JSON(consts.StatusOK, resp)
}

// PublicDuplicateProduct .
// @router /api/marketplace/product/duplicate [POST]
func PublicDuplicateProduct(ctx context.Context, c *app.RequestContext) {
	var err error
	var req product_public_api.DuplicateProductRequest
	err = c.BindAndValidate(&req)
	if err != nil {
		invalidParamRequestResponse(c, err.Error())
		return
	}

	resp := new(product_public_api.DuplicateProductResponse)
	resp.Data = new(product_public_api.DuplicateProductData)

	switch req.GetEntityType() {
	case product_common.ProductEntityType_BotTemplate:
		modelListResp, err := modelmgr.ModelmgrApplicationSVC.GetModelList(ctx, &developer_api.GetTypeListRequest{})
		if err != nil {
			internalServerErrorResponse(ctx, c, err)
			return
		}
		if modelListResp == nil || modelListResp.Data == nil || len(modelListResp.Data.ModelList) == 0 {
			invalidParamRequestResponse(c, "no model found")
			return
		}

		bot, err := singleagent.SingleAgentSVC.DuplicateDraftBot(ctx, &developer_api.DuplicateDraftBotRequest{
			BotID:   req.GetProductID(),
			SpaceID: req.GetSpaceID(),
		})
		if err != nil {
			internalServerErrorResponse(ctx, c, err)
			return
		}

		botInfo, err := singleagent.SingleAgentSVC.GetAgentBotInfo(ctx, &playground.GetDraftBotInfoAgwRequest{
			BotID: bot.Data.BotID,
		})
		if err != nil {
			internalServerErrorResponse(ctx, c, err)
			return
		}
		if botInfo.Data == nil || botInfo.Data.BotInfo == nil {
			invalidParamRequestResponse(c, "no bot info found")
			return
		}

		modelInfo := botInfo.GetData().GetBotInfo().GetModelInfo()
		if modelInfo == nil {
			invalidParamRequestResponse(c, "no model info found in agent")
			return
		}
		modelInfo.ModelId = &modelListResp.Data.ModelList[0].ModelType

		if req.Name != nil {
			_, err = singleagent.SingleAgentSVC.UpdateSingleAgentDraft(ctx, &playground.UpdateDraftBotInfoAgwRequest{
				BotInfo: &bot_common.BotInfoForUpdate{
					BotId:     &bot.Data.BotID,
					Name:      req.Name,
					ModelInfo: modelInfo,
				},
			})
			if err != nil {
				internalServerErrorResponse(ctx, c, err)
				return
			}
		}

		resp.Data.NewEntityID = bot.Data.BotID

	case product_common.ProductEntityType_WorkflowTemplateV2:
		workflowResp, err := appworkflow.SVC.CopyWorkflow(ctx, &workflow.CopyWorkflowRequest{
			WorkflowID: strconv.FormatInt(req.GetProductID(), 10),
			SpaceID:    strconv.FormatInt(req.GetSpaceID(), 10),
		})
		if err != nil {
			internalServerErrorResponse(ctx, c, err)
			return
		}

		newWorkflowID, err := strconv.ParseInt(workflowResp.Data.WorkflowID, 10, 64)
		if err != nil {
			internalServerErrorResponse(ctx, c, err)
			return
		}
		resp.Data.NewEntityID = newWorkflowID
		resp.Data.NewPluginID = &newWorkflowID

		if req.Name != nil {
			_, err = appworkflow.SVC.UpdateWorkflowMeta(ctx, &workflow.UpdateWorkflowMetaRequest{
				WorkflowID: workflowResp.Data.WorkflowID,
				SpaceID:    strconv.FormatInt(req.GetSpaceID(), 10),
				Name:       req.Name,
			})
			if err != nil {
				internalServerErrorResponse(ctx, c, err)
				return
			}
		}
	}

	c.JSON(consts.StatusOK, resp)
}
