package chapter

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

	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/os/gtime"
)

type sChapter struct{}

func New() service.IChapter {
	return &sChapter{}
}

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

// List retrieves a paginated list of chapters
func (s *sChapter) List(ctx context.Context, in *model.ChapterListIn) (out *model.ChapterListOut, err error) {
	out = &model.ChapterListOut{}
	m := dao.Chapters.Ctx(ctx)
	if in.BookId != 0 {
		m = m.Where(dao.Chapters.Columns().BookId, in.BookId)
	}
	if in.Title != "" {
		m = m.Where(dao.Chapters.Columns().Title+" like ?", "%"+in.Title+"%")
	}
	if in.IsLocked != 0 {
		m = m.Where(dao.Chapters.Columns().IsLocked, in.IsLocked)
	}
	if err = m.Page(in.Page, in.Size).ScanAndCount(&out.List, &out.Total, false); err != nil {
		return
	}
	return
}

// Create creates a new chapter
func (s *sChapter) Create(ctx context.Context, in *model.ChapterAddIn) (out *model.ChapterCRUDOut, err error) {
	if _, err := dao.Chapters.Ctx(ctx).Data(do.Chapters{
		BookId:        in.BookId,
		Title:         in.Title,
		Content:       in.Content,
		WordCount:     in.WordCount,
		Sort:          in.Sort,
		IsLocked:      in.IsLocked,
		RequiredScore: in.RequiredScore,
	}).Insert(); err != nil {
		return nil, ecode.Fail.Sub("chapter_create_failed")
	}
	return &model.ChapterCRUDOut{Success: true}, nil
}

// Update updates an existing chapter
func (s *sChapter) Update(ctx context.Context, in *model.ChapterEditIn) (out *model.ChapterCRUDOut, err error) {
	exist, err := dao.Chapters.Ctx(ctx).
		WherePri(in.Id).
		Exist()
	if err != nil {
		return nil, ecode.Fail.Sub("chapter_query_failed")
	}
	if !exist {
		return nil, ecode.NotFound.Sub("chapter_not_found")
	}
	_, err = dao.Chapters.Ctx(ctx).
		WherePri(in.Id).
		Data(do.Chapters{
			BookId:        in.BookId,
			Title:         in.Title,
			Content:       in.Content,
			WordCount:     in.WordCount,
			Sort:          in.Sort,
			IsLocked:      in.IsLocked,
			RequiredScore: in.RequiredScore,
		}).Update()
	if err != nil {
		return nil, ecode.Fail.Sub("chapter_update_failed")
	}
	return &model.ChapterCRUDOut{Success: true}, nil
}

// Delete deletes a chapter by ID
func (s *sChapter) Delete(ctx context.Context, in *model.ChapterDelIn) (out *model.ChapterCRUDOut, err error) {
	exist, err := dao.Chapters.Ctx(ctx).
		WherePri(in.Id).
		Exist()
	if err != nil {
		return nil, ecode.Fail.Sub("chapter_query_failed")
	}
	if !exist {
		return nil, ecode.NotFound.Sub("chapter_not_found")
	}

	// 开启事务，删除章节及相关数据
	err = dao.Chapters.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		// 1. 删除章节相关的用户阅读记录
		_, err := dao.UserReadRecords.Ctx(ctx).TX(tx).
			Where(dao.UserReadRecords.Columns().ChapterId, in.Id).
			Delete()
		if err != nil {
			return ecode.Fail.Sub("read_record_delete_failed")
		}

		// 2. 删除章节相关的购买记录
		_, err = dao.UserChapterPurchases.Ctx(ctx).TX(tx).
			Where(dao.UserChapterPurchases.Columns().ChapterId, in.Id).
			Delete()
		if err != nil {
			return ecode.Fail.Sub("purchase_delete_failed")
		}

		// 3. 最后删除章节
		_, err = dao.Chapters.Ctx(ctx).TX(tx).WherePri(in.Id).Delete()
		if err != nil {
			return ecode.Fail.Sub("chapter_delete_failed")
		}

		return nil
	})

	if err != nil {
		return nil, err
	}

	return &model.ChapterCRUDOut{Success: true}, nil
}

// AppList retrieves chapter list for app without content
func (s *sChapter) AppList(ctx context.Context, in *model.ChapterAppListIn) (out *model.ChapterAppListOut, err error) {
	out = &model.ChapterAppListOut{}

	// 构建查询条件
	m := dao.Chapters.Ctx(ctx)

	// 必须指定 bookId
	if in.BookId == 0 {
		return nil, ecode.Fail.Sub("chapter_book_id_required")
	}
	m = m.Where(dao.Chapters.Columns().BookId, in.BookId)

	// 根据 isDesc 字段排序
	if in.IsDesc {
		m = m.OrderDesc(dao.Chapters.Columns().Sort)
	}

	// 执行分页查询，获取列表和总数
	if err = m.Page(in.Page, in.Size).ScanAndCount(&out.List, &out.Total, false); err != nil {
		return nil, ecode.Fail.Sub("chapter_query_failed")
	}

	// 如果指定了用户ID，查询阅读进度
	if in.UserId > 0 {
		// 获取所有章节ID
		chapterIds := make([]int64, 0, len(out.List))
		for _, item := range out.List {
			chapterIds = append(chapterIds, item.Id)
		}

		if len(chapterIds) > 0 {
			// 查询阅读记录
			readRecords := make([]struct {
				ChapterId int64       `json:"chapterId"`
				ReadAt    *gtime.Time `json:"readAt"`
			}, 0)

			err = dao.UserReadRecords.Ctx(ctx).
				Fields("chapter_id, read_at").
				Where(dao.UserReadRecords.Columns().UserId, in.UserId).
				Where(dao.UserReadRecords.Columns().BookId, in.BookId).
				WhereIn(dao.UserReadRecords.Columns().ChapterId, chapterIds).
				Scan(&readRecords)
			if err != nil {
				return nil, ecode.Fail.Sub("read_record_query_failed")
			}

			// 查询购买记录
			purchaseRecords := make([]struct {
				ChapterId int64 `json:"chapterId"`
			}, 0)

			err = dao.UserChapterPurchases.Ctx(ctx).
				Fields("chapter_id").
				Where(dao.UserChapterPurchases.Columns().UserId, in.UserId).
				Where(dao.UserChapterPurchases.Columns().BookId, in.BookId).
				WhereIn(dao.UserChapterPurchases.Columns().ChapterId, chapterIds).
				Scan(&purchaseRecords)
			if err != nil {
				return nil, ecode.Fail.Sub("purchase_record_query_failed")
			}

			// 构建阅读记录映射
			readMap := make(map[int64]*gtime.Time)
			for _, record := range readRecords {
				readMap[record.ChapterId] = record.ReadAt
			}

			// 构建购买记录映射
			purchaseMap := make(map[int64]bool)
			for _, record := range purchaseRecords {
				purchaseMap[record.ChapterId] = true
			}

			// 为每个章节设置阅读进度和购买状态
			for i := range out.List {
				if readAt, exists := readMap[out.List[i].Id]; exists {
					out.List[i].ReadAt = readAt
					out.List[i].ReadProgress = 100 // 有阅读记录表示已读
				} else {
					out.List[i].ReadProgress = 0 // 未读
					out.List[i].ReadAt = nil
				}

				// 设置购买状态
				if out.List[i].IsLocked == 0 {
					// 免费章节，直接设置为已购买
					out.List[i].IsPurchased = true
				} else {
					// 付费章节，根据购买记录设置
					if purchaseMap[out.List[i].Id] {
						out.List[i].IsPurchased = true
					} else {
						out.List[i].IsPurchased = false
					}
				}
			}
		}
	}

	return out, nil
}

// AppDetail retrieves chapter detail for app
func (s *sChapter) AppDetail(ctx context.Context, in *model.ChapterAppDetailIn) (out *model.ChapterAppDetailOut, err error) {
	out = &model.ChapterAppDetailOut{}

	// 构建查询条件
	m := dao.Chapters.Ctx(ctx)

	// 必须指定章节ID
	if in.Id == 0 {
		return nil, ecode.Fail.Sub("chapter_id_required")
	}
	m = m.Where(dao.Chapters.Columns().Id, in.Id)

	// 执行查询
	if err = m.Scan(out); err != nil {
		return nil, ecode.Fail.Sub("chapter_query_failed")
	}

	// 检查章节是否存在
	if out.Id == 0 {
		return nil, ecode.NotFound.Sub("chapter_not_found")
	}

	return out, nil
}

// AppPurchase purchases chapter for app
func (s *sChapter) AppPurchase(ctx context.Context, in *model.ChapterAppPurchaseIn) (out *model.ChapterAppPurchaseOut, err error) {
	out = &model.ChapterAppPurchaseOut{}

	// 必须指定章节ID
	if in.Id == 0 {
		return nil, ecode.Fail.Sub("chapter_id_required")
	}

	// 必须指定用户ID
	if in.UserId == 0 {
		return nil, ecode.Fail.Sub("user_id_required")
	}

	// 查询章节信息
	chapter := &entity.Chapters{}
	err = dao.Chapters.Ctx(ctx).Where(dao.Chapters.Columns().Id, in.Id).Scan(chapter)
	if err != nil {
		return nil, ecode.Fail.Sub("chapter_query_failed")
	}

	// 检查章节是否存在
	if chapter.Id == 0 {
		return nil, ecode.NotFound.Sub("chapter_not_found")
	}

	// 检查章节是否锁定
	if chapter.IsLocked == 0 {
		// 章节免费，直接返回成功
		out.Success = true
		return out, nil
	}

	// 查询用户信息
	user := &entity.Users{}
	err = dao.Users.Ctx(ctx).Where(dao.Users.Columns().Id, in.UserId).Scan(user)
	if err != nil {
		return nil, ecode.Fail.Sub("user_query_failed")
	}

	// 检查用户是否存在
	if user.Id == 0 {
		return nil, ecode.NotFound.Sub("user_not_found")
	}

	// 检查用户积分是否足够
	if user.Points < uint64(chapter.RequiredScore) {
		return nil, ecode.Fail.Sub("insufficient_points")
	}

	// 检查是否已经购买过该章节
	exist, err := dao.UserChapterPurchases.Ctx(ctx).
		Where(dao.UserChapterPurchases.Columns().UserId, in.UserId).
		Where(dao.UserChapterPurchases.Columns().ChapterId, in.Id).
		Exist()
	if err != nil {
		return nil, ecode.Fail.Sub("purchase_query_failed")
	}

	if exist {
		// 已经购买过，直接返回成功
		out.Success = true
		return out, nil
	}

	// 开启事务处理
	if err := dao.UserChapterPurchases.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		// 扣除用户积分
		_, err := dao.Users.Ctx(ctx).TX(tx).Where(dao.Users.Columns().Id, in.UserId).Decrement(dao.Users.Columns().Points, chapter.RequiredScore)
		if err != nil {
			return ecode.Fail.Sub("score_deduction_failed")
		}

		// 记录购买记录
		purchaseId, err := dao.UserChapterPurchases.Ctx(ctx).TX(tx).Data(do.UserChapterPurchases{
			UserId:       in.UserId,
			ChapterId:    in.Id,
			BookId:       chapter.BookId,
			PointsUsed:   chapter.RequiredScore,
			PurchaseTime: gtime.Now(),
		}).InsertAndGetId()
		if err != nil {
			return ecode.Fail.Sub("purchase_record_failed")
		}

		// 记录用户积分日志
		_, err = dao.UserPointsLogs.Ctx(ctx).TX(tx).Data(do.UserPointsLogs{
			UserId:         in.UserId,
			ChangeType:     1, // 消费
			PointsChange:   -chapter.RequiredScore,
			RelatedOrderId: purchaseId,
			Description:    "购买章节：" + chapter.Title,
			CreatedAt:      gtime.Now(),
		}).Insert()
		if err != nil {
			return ecode.Fail.Sub("point_log_failed")
		}

		return nil
	}); err != nil {
		return nil, err
	}

	out.Success = true
	return out, nil
}

// AppProgress uploads reading progress for app
func (s *sChapter) AppProgress(ctx context.Context, in *model.ChapterAppProgressIn) (out *model.ChapterAppProgressOut, err error) {
	out = &model.ChapterAppProgressOut{}

	// 必须指定用户ID
	if in.UserId == 0 {
		return nil, ecode.Fail.Sub("user_id_required")
	}

	// 必须指定书籍ID
	if in.BookId == 0 {
		return nil, ecode.Fail.Sub("book_id_required")
	}

	// 必须指定章节ID
	if in.ChapterId == 0 {
		return nil, ecode.Fail.Sub("chapter_id_required")
	}

	// 验证进度范围
	if in.Progress < 0 || in.Progress > 100 {
		return nil, ecode.Fail.Sub("progress_invalid")
	}

	// 检查章节是否存在
	exist, err := dao.Chapters.Ctx(ctx).Where(dao.Chapters.Columns().Id, in.ChapterId).Exist()
	if err != nil {
		return nil, ecode.Fail.Sub("chapter_query_failed")
	}
	if !exist {
		return nil, ecode.NotFound.Sub("chapter_not_found")
	}

	// 检查用户是否存在
	exist, err = dao.Users.Ctx(ctx).Where(dao.Users.Columns().Id, in.UserId).Exist()
	if err != nil {
		return nil, ecode.Fail.Sub("user_query_failed")
	}
	if !exist {
		return nil, ecode.NotFound.Sub("user_not_found")
	}

	// 开启事务处理
	if err := dao.UserReadRecords.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		// 1. 更新或创建阅读记录
		exist, err := dao.UserReadRecords.Ctx(ctx).TX(tx).
			Where(dao.UserReadRecords.Columns().UserId, in.UserId).
			Where(dao.UserReadRecords.Columns().BookId, in.BookId).
			Where(dao.UserReadRecords.Columns().ChapterId, in.ChapterId).
			Exist()
		if err != nil {
			return ecode.Fail.Sub("read_record_query_failed")
		}

		if exist {
			// 更新现有记录
			_, err = dao.UserReadRecords.Ctx(ctx).TX(tx).
				Where(dao.UserReadRecords.Columns().UserId, in.UserId).
				Where(dao.UserReadRecords.Columns().BookId, in.BookId).
				Where(dao.UserReadRecords.Columns().ChapterId, in.ChapterId).
				Data(do.UserReadRecords{
					Progress: in.Progress,
					ReadAt:   gtime.Now(),
				}).Update()
			if err != nil {
				return ecode.Fail.Sub("read_record_update_failed")
			}
		} else {
			// 创建新记录
			_, err = dao.UserReadRecords.Ctx(ctx).TX(tx).Data(do.UserReadRecords{
				UserId:    in.UserId,
				BookId:    in.BookId,
				ChapterId: in.ChapterId,
				Progress:  in.Progress,
				ReadAt:    gtime.Now(),
			}).Insert()
			if err != nil {
				return ecode.Fail.Sub("read_record_create_failed")
			}
		}

		// 2. 更新或创建历史记录
		exist, err = dao.UserReadHistory.Ctx(ctx).TX(tx).
			Where(dao.UserReadHistory.Columns().UserId, in.UserId).
			Where(dao.UserReadHistory.Columns().BookId, in.BookId).
			Exist()
		if err != nil {
			return ecode.Fail.Sub("history_query_failed")
		}

		if exist {
			// 更新现有历史记录
			_, err = dao.UserReadHistory.Ctx(ctx).TX(tx).
				Where(dao.UserReadHistory.Columns().UserId, in.UserId).
				Where(dao.UserReadHistory.Columns().BookId, in.BookId).
				Data(do.UserReadHistory{
					ChapterId: in.ChapterId,
					ReadAt:    gtime.Now(),
				}).Update()
			if err != nil {
				return ecode.Fail.Sub("history_update_failed")
			}
		} else {
			// 创建新历史记录
			_, err = dao.UserReadHistory.Ctx(ctx).TX(tx).Data(do.UserReadHistory{
				UserId:    in.UserId,
				BookId:    in.BookId,
				ChapterId: in.ChapterId,
				ReadAt:    gtime.Now(),
			}).Insert()
			if err != nil {
				return ecode.Fail.Sub("history_create_failed")
			}
		}

		// 3. 更新书架记录（如果存在）
		exist, err = dao.Bookshelves.Ctx(ctx).TX(tx).
			Where(dao.Bookshelves.Columns().UserId, in.UserId).
			Where(dao.Bookshelves.Columns().BookId, in.BookId).
			Exist()
		if err != nil {
			return ecode.Fail.Sub("bookshelf_query_failed")
		}

		if exist {
			// 计算阅读进度百分比
			totalChapters, err := dao.Chapters.Ctx(ctx).TX(tx).
				Where(dao.Chapters.Columns().BookId, in.BookId).
				Count()
			if err != nil {
				return ecode.Fail.Sub("chapter_count_failed")
			}

			var readChapters int
			if totalChapters > 0 {
				readChapters, err = dao.UserReadRecords.Ctx(ctx).TX(tx).
					Where(dao.UserReadRecords.Columns().UserId, in.UserId).
					Where(dao.UserReadRecords.Columns().BookId, in.BookId).
					WhereGT(dao.UserReadRecords.Columns().ChapterId, 0).
					Count()
				if err != nil {
					return ecode.Fail.Sub("read_chapter_count_failed")
				}
			}

			readPercent := 0.0
			if totalChapters > 0 {
				readPercent = float64(readChapters) / float64(totalChapters) * 100
				if readPercent > 100 {
					readPercent = 100
				}
			}

			// 判断是否为最后一章
			lastChapter, err := dao.Chapters.Ctx(ctx).TX(tx).
				Where(dao.Chapters.Columns().BookId, in.BookId).
				OrderDesc(dao.Chapters.Columns().Sort).
				One()
			if err != nil {
				return ecode.Fail.Sub("chapter_query_failed")
			}

			readStatus := 1 // 默认为正在读
			if lastChapter != nil && lastChapter["id"].Int64() == in.ChapterId {
				readStatus = 2 // 如果是最后一章，标记为已读完
			}

			// 更新书架记录
			_, err = dao.Bookshelves.Ctx(ctx).TX(tx).
				Where(dao.Bookshelves.Columns().UserId, in.UserId).
				Where(dao.Bookshelves.Columns().BookId, in.BookId).
				Data(do.Bookshelves{
					LastReadChapterId: in.ChapterId,
					LastReadPercent:   readPercent,
					LastReadAt:        gtime.Now(),
					ReadStatus:        readStatus,
				}).Update()
			if err != nil {
				return ecode.Fail.Sub("bookshelf_update_failed")
			}
		}

		return nil
	}); err != nil {
		return nil, err
	}

	out.Success = true
	return out, nil
}

// AppBatchProgress uploads batch reading progress for app
func (s *sChapter) AppBatchProgress(ctx context.Context, in *model.ChapterAppBatchProgressIn) (out *model.ChapterAppProgressOut, err error) {
	out = &model.ChapterAppProgressOut{}

	// 必须指定用户ID
	if in.UserId == 0 {
		return nil, ecode.Fail.Sub("user_id_required")
	}

	// 必须指定书籍ID
	if in.BookId == 0 {
		return nil, ecode.Fail.Sub("book_id_required")
	}

	// 必须指定章节列表
	if len(in.Chapters) == 0 {
		return nil, ecode.Fail.Sub("chapters_required")
	}

	// 检查用户是否存在
	exist, err := dao.Users.Ctx(ctx).Where(dao.Users.Columns().Id, in.UserId).Exist()
	if err != nil {
		return nil, ecode.Fail.Sub("user_query_failed")
	}
	if !exist {
		return nil, ecode.NotFound.Sub("user_not_found")
	}

	// 验证所有章节进度
	for _, chapter := range in.Chapters {
		if chapter.ChapterId == 0 {
			return nil, ecode.Fail.Sub("chapter_id_required")
		}
		if chapter.Progress < 0 || chapter.Progress > 100 {
			return nil, ecode.Fail.Sub("progress_invalid")
		}
	}

	// 检查所有章节是否存在
	chapterIds := make([]int64, 0)
	for _, chapter := range in.Chapters {
		chapterIds = append(chapterIds, chapter.ChapterId)
	}

	exist, err = dao.Chapters.Ctx(ctx).
		WhereIn(dao.Chapters.Columns().Id, chapterIds).
		Where(dao.Chapters.Columns().BookId, in.BookId).
		Exist()
	if err != nil {
		return nil, ecode.Fail.Sub("chapter_query_failed")
	}
	if !exist {
		return nil, ecode.NotFound.Sub("chapter_not_found")
	}

	// 开启事务处理
	if err := dao.UserReadRecords.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		// 批量处理每个章节的进度
		for _, chapter := range in.Chapters {
			// 1. 更新或创建阅读记录
			exist, err := dao.UserReadRecords.Ctx(ctx).TX(tx).
				Where(dao.UserReadRecords.Columns().UserId, in.UserId).
				Where(dao.UserReadRecords.Columns().BookId, in.BookId).
				Where(dao.UserReadRecords.Columns().ChapterId, chapter.ChapterId).
				Exist()
			if err != nil {
				return ecode.Fail.Sub("read_record_query_failed")
			}

			if exist {
				// 更新现有记录
				_, err = dao.UserReadRecords.Ctx(ctx).TX(tx).
					Where(dao.UserReadRecords.Columns().UserId, in.UserId).
					Where(dao.UserReadRecords.Columns().BookId, in.BookId).
					Where(dao.UserReadRecords.Columns().ChapterId, chapter.ChapterId).
					Data(do.UserReadRecords{
						Progress: chapter.Progress,
						ReadAt:   gtime.Now(),
					}).Update()
				if err != nil {
					return ecode.Fail.Sub("read_record_update_failed")
				}
			} else {
				// 创建新记录
				_, err = dao.UserReadRecords.Ctx(ctx).TX(tx).Data(do.UserReadRecords{
					UserId:    in.UserId,
					BookId:    in.BookId,
					ChapterId: chapter.ChapterId,
					Progress:  chapter.Progress,
					ReadAt:    gtime.Now(),
				}).Insert()
				if err != nil {
					return ecode.Fail.Sub("read_record_create_failed")
				}
			}
		}

		// 2. 更新或创建历史记录（使用最后一个章节作为当前阅读章节）
		lastChapter := in.Chapters[len(in.Chapters)-1]
		exist, err = dao.UserReadHistory.Ctx(ctx).TX(tx).
			Where(dao.UserReadHistory.Columns().UserId, in.UserId).
			Where(dao.UserReadHistory.Columns().BookId, in.BookId).
			Exist()
		if err != nil {
			return ecode.Fail.Sub("history_query_failed")
		}

		if exist {
			// 更新现有历史记录
			_, err = dao.UserReadHistory.Ctx(ctx).TX(tx).
				Where(dao.UserReadHistory.Columns().UserId, in.UserId).
				Where(dao.UserReadHistory.Columns().BookId, in.BookId).
				Data(do.UserReadHistory{
					ChapterId: lastChapter.ChapterId,
					ReadAt:    gtime.Now(),
				}).Update()
			if err != nil {
				return ecode.Fail.Sub("history_update_failed")
			}
		} else {
			// 创建新历史记录
			_, err = dao.UserReadHistory.Ctx(ctx).TX(tx).Data(do.UserReadHistory{
				UserId:    in.UserId,
				BookId:    in.BookId,
				ChapterId: lastChapter.ChapterId,
				ReadAt:    gtime.Now(),
			}).Insert()
			if err != nil {
				return ecode.Fail.Sub("history_create_failed")
			}
		}

		// 3. 更新书架记录（如果存在）
		exist, err = dao.Bookshelves.Ctx(ctx).TX(tx).
			Where(dao.Bookshelves.Columns().UserId, in.UserId).
			Where(dao.Bookshelves.Columns().BookId, in.BookId).
			Exist()
		if err != nil {
			return ecode.Fail.Sub("bookshelf_query_failed")
		}

		if exist {
			// 计算阅读进度百分比
			totalChapters, err := dao.Chapters.Ctx(ctx).TX(tx).
				Where(dao.Chapters.Columns().BookId, in.BookId).
				Count()
			if err != nil {
				return ecode.Fail.Sub("chapter_count_failed")
			}

			var readChapters int
			if totalChapters > 0 {
				readChapters, err = dao.UserReadRecords.Ctx(ctx).TX(tx).
					Where(dao.UserReadRecords.Columns().UserId, in.UserId).
					Where(dao.UserReadRecords.Columns().BookId, in.BookId).
					WhereGT(dao.UserReadRecords.Columns().ChapterId, 0).
					Count()
				if err != nil {
					return ecode.Fail.Sub("read_chapter_count_failed")
				}
			}

			readPercent := 0.0
			if totalChapters > 0 {
				readPercent = float64(readChapters) / float64(totalChapters) * 100
				if readPercent > 100 {
					readPercent = 100
				}
			}

			// 判断是否为最后一章
			lastChapterInfo, err := dao.Chapters.Ctx(ctx).TX(tx).
				Where(dao.Chapters.Columns().BookId, in.BookId).
				OrderDesc(dao.Chapters.Columns().Sort).
				One()
			if err != nil {
				return ecode.Fail.Sub("chapter_query_failed")
			}

			readStatus := 1 // 默认为正在读
			if lastChapterInfo != nil && lastChapterInfo["id"].Int64() == lastChapter.ChapterId {
				readStatus = 2 // 如果是最后一章，标记为已读完
			}

			// 更新书架记录
			_, err = dao.Bookshelves.Ctx(ctx).TX(tx).
				Where(dao.Bookshelves.Columns().UserId, in.UserId).
				Where(dao.Bookshelves.Columns().BookId, in.BookId).
				Data(do.Bookshelves{
					LastReadChapterId: lastChapter.ChapterId,
					LastReadPercent:   readPercent,
					LastReadAt:        gtime.Now(),
					ReadStatus:        readStatus,
				}).Update()
			if err != nil {
				return ecode.Fail.Sub("bookshelf_update_failed")
			}
		}

		return nil
	}); err != nil {
		return nil, err
	}

	out.Success = true
	return out, nil
}
