package book_recommendations

import (
	"context"
	"server/internal/dao"
	"server/internal/model"
	"server/internal/model/do"
	"server/internal/service"
	"server/utility/ecode"
	"server/utility/oss"

	"github.com/gogf/gf/v2/net/ghttp"
)

type sBookRecommendations struct{}

func New() service.IBookRecommendations {
	return &sBookRecommendations{}
}

func init() {
	service.RegisterBookRecommendations(New())
}

// List 获取推荐列表
func (s *sBookRecommendations) List(ctx context.Context, in *model.BookRecommendationsListIn) (out *model.BookRecommendationsListOut, err error) {
	out = &model.BookRecommendationsListOut{}
	m := dao.BookRecommendations.Ctx(ctx)
	if in.Type != 0 {
		m = m.Where(dao.BookRecommendations.Columns().Type, in.Type)
	}
	if in.Status != 0 {
		m = m.Where(dao.BookRecommendations.Columns().Status, in.Status)
	}
	if in.BookId != 0 {
		m = m.Where(dao.BookRecommendations.Columns().BookId, in.BookId)
	}
	m = m.Order(dao.BookRecommendations.Columns().SortOrder)
	if err = m.Page(in.Page, in.Size).WithAll().ScanAndCount(&out.List, &out.Total, false); err != nil {
		return nil, ecode.Fail.Sub("book_recommendation_query_failed")
	}
	return out, nil
}

// AppList 获取APP端推荐列表
func (s *sBookRecommendations) AppList(ctx context.Context, in *model.BookRecommendationsListIn) (out *model.BookRecommendationsAppListOut, err error) {
	out = &model.BookRecommendationsAppListOut{}
	m := dao.BookRecommendations.Ctx(ctx)
	// 直接筛选状态为1的记录
	m = m.Where(dao.BookRecommendations.Columns().Status, 1)
	// 根据排序字段排序
	m = m.Order(dao.BookRecommendations.Columns().SortOrder)
	var list []model.RecommendAppItem
	if err = m.Page(in.Page, in.Size).ScanAndCount(&list, &out.Total, false); err != nil {
		return nil, ecode.Fail.Sub("book_recommendation_query_failed")
	}
	out.List = list
	return out, nil
}

// Create 新增推荐
func (s *sBookRecommendations) Create(ctx context.Context, in *model.BookRecommendationsCreateIn) (out *model.BookRecommendationsCRUDOut, err error) {
	// 检查同类型同书籍是否已存在（未软删除）
	exist, err := dao.BookRecommendations.Ctx(ctx).
		Where(dao.BookRecommendations.Columns().BookId, in.BookId).
		Where(dao.BookRecommendations.Columns().Type, in.Type).
		Exist()
	if err != nil {
		return nil, ecode.Fail.Sub("book_recommendation_query_failed")
	}
	if exist {
		return nil, ecode.Params.Sub("book_recommendation_exists")
	}
	// 插入数据
	_, err = dao.BookRecommendations.Ctx(ctx).Data(do.BookRecommendations{
		BookId:    in.BookId,
		Type:      in.Type,
		CoverUrl:  in.CoverUrl,
		SortOrder: in.SortOrder,
		Status:    in.Status,
	}).Insert()
	if err != nil {
		return nil, ecode.Fail.Sub("book_recommendation_create_failed")
	}
	return &model.BookRecommendationsCRUDOut{Success: true}, nil
}

// Update 编辑推荐
func (s *sBookRecommendations) Update(ctx context.Context, in *model.BookRecommendationsUpdateIn) (out *model.BookRecommendationsCRUDOut, err error) {
	// 检查是否存在
	exist, err := dao.BookRecommendations.Ctx(ctx).
		Where(dao.BookRecommendations.Columns().Id, in.Id).
		Exist()
	if err != nil {
		return nil, ecode.Fail.Sub("book_recommendation_query_failed")
	}
	if !exist {
		return nil, ecode.NotFound.Sub("book_recommendation_not_found")
	}
	// 检查同类型同书籍是否有重复（排除自己）
	repeat, err := dao.BookRecommendations.Ctx(ctx).
		Where(dao.BookRecommendations.Columns().BookId, in.BookId).
		Where(dao.BookRecommendations.Columns().Type, in.Type).
		WhereNot(dao.BookRecommendations.Columns().Id, in.Id).
		Exist()
	if err != nil {
		return nil, ecode.Fail.Sub("book_recommendation_query_failed")
	}
	if repeat {
		return nil, ecode.Params.Sub("book_recommendation_exists")
	}
	_, err = dao.BookRecommendations.Ctx(ctx).
		Where(dao.BookRecommendations.Columns().Id, in.Id).
		Data(do.BookRecommendations{
			BookId:    in.BookId,
			Type:      in.Type,
			CoverUrl:  in.CoverUrl,
			SortOrder: in.SortOrder,
			Status:    in.Status,
		}).Update()
	if err != nil {
		return nil, ecode.Fail.Sub("book_recommendation_update_failed")
	}
	return &model.BookRecommendationsCRUDOut{Success: true}, nil
}

// Delete 删除推荐
func (s *sBookRecommendations) Delete(ctx context.Context, in *model.BookRecommendationsDeleteIn) (out *model.BookRecommendationsCRUDOut, err error) {
	// 检查是否存在
	exist, err := dao.BookRecommendations.Ctx(ctx).
		Where(dao.BookRecommendations.Columns().Id, in.Id).
		Exist()
	if err != nil {
		return nil, ecode.Fail.Sub("book_recommendation_query_failed")
	}
	if !exist {
		return nil, ecode.NotFound.Sub("book_recommendation_not_found")
	}
	// 直接调用 Delete
	_, err = dao.BookRecommendations.Ctx(ctx).
		Where(dao.BookRecommendations.Columns().Id, in.Id).
		Delete()
	if err != nil {
		return nil, ecode.Fail.Sub("book_recommendation_delete_failed")
	}
	return &model.BookRecommendationsCRUDOut{Success: true}, nil
}

// SetStatus 启用/禁用推荐
func (s *sBookRecommendations) SetStatus(ctx context.Context, in *model.BookRecommendationsSetStatusIn) (out *model.BookRecommendationsCRUDOut, err error) {
	// 检查是否存在
	exist, err := dao.BookRecommendations.Ctx(ctx).
		Where(dao.BookRecommendations.Columns().Id, in.Id).
		Exist()
	if err != nil {
		return nil, ecode.Fail.Sub("book_recommendation_query_failed")
	}
	if !exist {
		return nil, ecode.NotFound.Sub("book_recommendation_not_found")
	}
	_, err = dao.BookRecommendations.Ctx(ctx).
		Where(dao.BookRecommendations.Columns().Id, in.Id).
		Data(do.BookRecommendations{
			Status: in.Status,
		}).Update()
	if err != nil {
		return nil, ecode.Fail.Sub("book_recommendation_update_failed")
	}
	return &model.BookRecommendationsCRUDOut{Success: true}, nil
}

// SortOrder 设置排序
func (s *sBookRecommendations) SortOrder(ctx context.Context, in *model.BookRecommendationsSortOrderIn) (out *model.BookRecommendationsCRUDOut, err error) {
	// 检查是否存在
	exist, err := dao.BookRecommendations.Ctx(ctx).
		Where(dao.BookRecommendations.Columns().Id, in.Id).
		Exist()
	if err != nil {
		return nil, ecode.Fail.Sub("book_recommendation_query_failed")
	}
	if !exist {
		return nil, ecode.NotFound.Sub("book_recommendation_not_found")
	}
	_, err = dao.BookRecommendations.Ctx(ctx).
		Where(dao.BookRecommendations.Columns().Id, in.Id).
		Data(do.BookRecommendations{
			SortOrder: in.SortOrder,
		}).Update()
	if err != nil {
		return nil, ecode.Fail.Sub("book_recommendation_update_failed")
	}
	return &model.BookRecommendationsCRUDOut{Success: true}, nil
}

// UploadCover 上传推荐封面图
func (s *sBookRecommendations) UploadCover(ctx context.Context, file *ghttp.UploadFile) (url string, err error) {
	if file == nil {
		return "", ecode.Params.Sub("image_file_required")
	}
	// 校验文件类型（只允许图片）
	contentType := file.Header.Get("Content-Type")
	if contentType == "" || contentType[:6] != "image/" {
		return "", ecode.Params.Sub("image_type_invalid")
	}
	allowedTypes := map[string]bool{
		"image/jpeg": true,
		"image/png":  true,
		"image/gif":  true,
		"image/webp": true,
	}
	if !allowedTypes[contentType] {
		return "", ecode.Params.Sub("image_format_invalid")
	}
	if file.Size > 1*1024*1024 {
		return "", ecode.Params.Sub("image_size_exceeded")
	}
	client := oss.GetOSSClient("amazon_s3")
	if client == nil {
		return "", ecode.Fail.Sub("server_error")
	}
	url, err = client.Upload(file, "recommend")
	if err != nil {
		return "", ecode.Fail.Sub("image_upload_failed")
	}
	return url, nil
}
