package newagentconv

import (
	"github.com/LoveLosita/smartflow/backend/model"
	schedule "github.com/LoveLosita/smartflow/backend/newAgent/tools/schedule"
	"github.com/LoveLosita/smartflow/backend/respond"
)

// ApplyPlacedItems 将前端提交的绝对时间放置项应用到 ScheduleState。
//
// 职责边界：
// 1. 只修改 source=task_item 的任务，source=event 的课程不受影响；
// 2. 不在请求中的任务保持原样（slots/status/embed 不变）；
// 3. 不校验 Slots 的业务合法性（冲突等由 execute 节点兜底）；
// 4. 返回 respond.XXX 错误，调用方可直接透传给 DealWithError。
func ApplyPlacedItems(
	state *schedule.ScheduleState,
	items []model.SaveScheduleStatePlacedItem,
) error {
	// 1. 构建索引。
	sourceIDToTask := make(map[int]*schedule.ScheduleTask, len(state.Tasks))
	eventSourceIDToTask := make(map[int]*schedule.ScheduleTask)
	for i := range state.Tasks {
		t := &state.Tasks[i]
		if t.Source == "task_item" {
			sourceIDToTask[t.SourceID] = t
		} else if t.Source == "event" {
			eventSourceIDToTask[t.SourceID] = t
		}
	}

	// 2. 去重检查。
	seen := make(map[int]struct{}, len(items))
	for _, item := range items {
		if _, dup := seen[item.TaskItemID]; dup {
			return respond.ScheduleStateDuplicateTaskItem
		}
		seen[item.TaskItemID] = struct{}{}
	}

	// 3. 逐个处理 item。
	for _, item := range items {
		// 3.1 绝对坐标 → 相对 day_index。
		dayIndex, ok := state.WeekDayToDay(item.Week, item.DayOfWeek)
		if !ok {
			return respond.ScheduleStateInvalidCoordinates
		}

		// 3.2 在快照中查找对应的 task_item。
		task, found := sourceIDToTask[item.TaskItemID]
		if !found {
			return respond.ScheduleStateTaskItemNotFound
		}

		// 3.3 清除旧嵌入关系。
		if task.EmbedHost != nil {
			oldHost := state.TaskByStateID(*task.EmbedHost)
			if oldHost != nil {
				oldHost.EmbeddedBy = nil
			}
			task.EmbedHost = nil
		}

		// 3.4 设置新嵌入关系。
		if item.EmbedCourseEventID != 0 {
			hostEvent := eventSourceIDToTask[item.EmbedCourseEventID]
			if hostEvent == nil {
				return respond.ScheduleStateEventNotFound
			}
			hostStateID := hostEvent.StateID
			guestStateID := task.StateID
			task.EmbedHost = &hostStateID
			hostEvent.EmbeddedBy = &guestStateID
		}

		// 3.5 更新 Slots。
		task.Slots = []schedule.TaskSlot{{
			Day:       dayIndex,
			SlotStart: item.StartSection,
			SlotEnd:   item.EndSection,
		}}

		// 3.6 pending → suggested。
		if task.Status == schedule.TaskStatusPending {
			task.Status = schedule.TaskStatusSuggested
		}
	}

	return nil
}
