package controllers

import (
	"Xcx_New/enums"
	"Xcx_New/models"
	"Xcx_New/service"
	"Xcx_New/utils"
	"encoding/json"
	"time"

	"github.com/astaxie/beego"
)

func PatientScheduleTemplateAPIControllerRegistRouters() {
	beego.Router("/api/schtemp/p/initdata", &PatientScheduleTemplateAPIController{}, "get:InitData")
	beego.Router("/api/schtemp/p/setmode", &PatientScheduleTemplateAPIController{}, "post:SetMode")
	beego.Router("/api/schtemp/p/update_sch", &PatientScheduleTemplateAPIController{}, "post:UpdateSchedules")

	// beego.Router("/api/test", &TestCtr{}, "get:Test")
}

// type TestCtr struct {
// 	BaseAPIController
// }

// func (this *TestCtr) Test() {
// 	now := time.Now().AddDate(0, 0, 7)

// 	weekday := int(now.Weekday())
// 	if weekday == 0 {
// 		weekday = 7
// 	}

// 	monday := now.AddDate(0, 0, 1-weekday)
// 	sunday := now.AddDate(0, 0, 7-weekday)

// 	// this.TraceLog("%v", weekday)
// 	this.ServeSuccessJSON(map[string]interface{}{
// 		"weekday": weekday,
// 		"monday":  monday.Format("2006-01-02"),
// 		"sunday":  sunday.Format("2006-01-02"),
// 	})
// }

// ------- 患者排班模板 --------
type PatientScheduleTemplateAPIController struct {
	BaseAuthAPIController
}

// /api/schtemp/p/initdata [get]
func (this *PatientScheduleTemplateAPIController) InitData() {
	adminUserInfo := this.GetAdminUserInfo()

	mode, getModeErr := service.GetOrgPatientScheduleTemplateMode(adminUserInfo.CurrentOrgId)
	if getModeErr != nil {
		this.ErrorLog("获取排班模板启用模式失败：%v", getModeErr)
		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
		return
	}
	now := time.Now()
	if mode == nil {
		mode = &models.PatientScheduleTemplateMode{
			OrgID:        adminUserInfo.CurrentOrgId,
			Mode:         0,
			ExecuteTimes: 0,
			Status:       1,
			CreateTime:   now.Unix(),
			ModifyTime:   now.Unix(),
		}
		createModeErr := service.SavePatientScheduleTemplateMode(mode)
		if createModeErr != nil {
			this.ErrorLog("创建排班模板启用模式失败：%v", createModeErr)
			this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
			return
		}
	}

	deviceNumbers, getDeviceNumbersErr := service.GetScheduleValidDeviceNumbers(adminUserInfo.CurrentOrgId)
	if getDeviceNumbersErr != nil {
		this.ErrorLog("获取床位号失败：%v", getDeviceNumbersErr)
		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
		return
	}

	templates, getTemplatesErr := service.GetOrgPatientScheduleTemplateItems(adminUserInfo.CurrentOrgId)
	if getTemplatesErr != nil {
		this.ErrorLog("获取排班模板及其排班列表失败：%v", getTemplatesErr)
		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
		return
	}
	if len(templates) == 0 {
		firstTemp, secondTemp, createTempErr := service.CreateTwoPatientScheduleTemplates(adminUserInfo.CurrentOrgId)
		if createTempErr != nil {
			this.ErrorLog("创建两个排班模板失败：%v", createTempErr)
			this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
			return
		}
		templates = append(templates, firstTemp, secondTemp)

	} else if len(templates) == 1 {
		temp, createTempErr := service.CreatePatientScheduleTemplate(adminUserInfo.CurrentOrgId)
		if createTempErr != nil {
			this.ErrorLog("创建两个排班模板失败：%v", createTempErr)
			this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
			return
		}
		templates = append(templates, temp)
	}

	patients, getPatientsErr := service.PatientScheduleTemplateGetAllValidPatient(adminUserInfo.CurrentOrgId)
	if getPatientsErr != nil {
		this.ErrorLog("获取患者列表失败失败：%v", getPatientsErr)
		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
		return
	}

	// 获取本周的排班
	monday, sunday := utils.GetMondayAndSundayOfWeekDate(&now)
	schedules, getScheduleErr := service.GetWeekSchedule(adminUserInfo.CurrentOrgId, monday.Unix(), sunday.Unix())
	if getScheduleErr != nil {
		this.ErrorLog("获取本周排班失败：%v", getScheduleErr)
		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
		return
	}

	this.ServeSuccessJSON(map[string]interface{}{
		"template_mode":  mode,
		"device_numbers": deviceNumbers,
		"templates":      templates,
		"patients":       patients,
		"schedules":      schedules,
	})
}

// /api/schtemp/p/setmode [post]
// @param mode:int 0.不启用模板 1.单周模板 2.双周模板
func (this *PatientScheduleTemplateAPIController) SetMode() {
	mode, _ := this.GetInt8("mode")
	if mode != 1 && mode != 2 && mode != 0 && mode != 3 && mode != 4 {
		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
		return
	}

	adminUserInfo := this.GetAdminUserInfo()

	templateMode, getTemplateModeErr := service.GetOrgPatientScheduleTemplateMode(adminUserInfo.CurrentOrgId)
	if getTemplateModeErr != nil {
		this.ErrorLog("获取排班模板启用模式失败：%v", getTemplateModeErr)
		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
		return
	} else if templateMode == nil {
		this.ErrorLog("获取不到排班模板启用模式")
		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
		return
	}

	if mode != templateMode.Mode {
		if templateMode.Mode == 0 { // 0 -> 1 或 0 -> 2 则直接清除下两周的排班
			templateMode.Mode = mode
			templateMode.ExecuteTimes = 0
			templateMode.ModifyTime = time.Now().Unix()
			updateErr := service.SavePatientScheduleTemplateModeAndClearNextTwoWeekSchedules(templateMode)
			if updateErr != nil {
				this.ErrorLog("更新排班模板启用方式（0 -> 1 或 0 -> 2）时失败：%v", updateErr)
				this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
				return
			}

		} else if mode == 0 { // 1 -> 0 或 2 -> 0 则不处理排班，但清除所有模板item
			templateMode.Mode = mode
			templateMode.ExecuteTimes = 0
			templateMode.ModifyTime = time.Now().Unix()
			updateErr := service.SavePatientScheduleTemplateModeAndClearAllTemplateItems(templateMode)
			if updateErr != nil {
				this.ErrorLog("更新排班模板启用方式（1 -> 0 或 2 -> 0）时失败：%v", updateErr)
				this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
				return
			}

		} else if templateMode.Mode == 1 && mode == 2 { // 1 -> 2 清除第二周排班
			templateMode.Mode = mode
			templateMode.ExecuteTimes = 0
			templateMode.ModifyTime = time.Now().Unix()
			updateErr := service.SavePatientScheduleTemplateModeAndClearNextSecondWeekSchedules(templateMode)
			if updateErr != nil {
				this.ErrorLog("更新排班模板启用方式（1 -> 2）时失败：%v", updateErr)
				this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
				return
			}

		} else if templateMode.Mode == 2 && mode == 1 { // 2 -> 1 清除第二周模板item，清除第二周排班，将第一周的排班重复到第二周
			templateIDs, getTemplateIDsErr := service.GetOrgPatientScheduleTemplateIDs(adminUserInfo.CurrentOrgId)
			if getTemplateIDsErr != nil {
				this.ErrorLog("获取排班模板失败：%v", getTemplateIDsErr)
				this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
				return
			}

			firstWeekItems, getFirstWeekItemsErr := service.GetOrgPatientScheduleTemplateItemsWithoutPatientByTemplateID(adminUserInfo.CurrentOrgId, templateIDs[0].ID)
			if getFirstWeekItemsErr != nil {
				this.ErrorLog("获取排班模板排班失败：%v", getFirstWeekItemsErr)
				this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
				return
			}

			templateMode.Mode = mode
			templateMode.ExecuteTimes = 0
			templateMode.ModifyTime = time.Now().Unix()
			updateErr := service.SavePatientScheduleTemplateMode2To1(templateMode, templateIDs[1].ID, firstWeekItems)
			if updateErr != nil {
				this.ErrorLog("更新排班模板启用方式（1 -> 2）时失败：%v", updateErr)
				this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
				return
			}
		}
	}
	this.ServeSuccessJSON(nil)
}

// /api/schtemp/p/update_sch [post]
// @param template_id:int
// @param add_schs:array'json ([ {device_number_id, patient_id, mode(treat_mode), weekday, time_type} ])
// @param del_schs:array'json ([ {device_number_id, weekday, time_type} ])
// @param change_schs:array'json ([ {device_number_id, patient_id, mode(treat_mode), weekday, time_type} ])
func (this *PatientScheduleTemplateAPIController) UpdateSchedules() {
	templateID, _ := this.GetInt64("template_id")
	addSchedulesJSON := this.GetString("add_schs")
	delSchedulesJSON := this.GetString("del_schs")
	changeSchedulesJSON := this.GetString("change_schs")
	if templateID <= 0 || len(addSchedulesJSON) == 0 || len(delSchedulesJSON) == 0 || len(changeSchedulesJSON) == 0 {
		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
		return
	}

	var addSchedules []*ParamModelSchedule
	var delSchedules []*ParamModelSchedule
	var changeSchedules []*ParamModelSchedule
	parseErr := json.Unmarshal([]byte(addSchedulesJSON), &addSchedules)
	if parseErr != nil {
		this.ErrorLog("解析增加排班的数组参数失败：%v", parseErr)
		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
		return
	}
	parseErr = json.Unmarshal([]byte(delSchedulesJSON), &delSchedules)
	if parseErr != nil {
		this.ErrorLog("解析删除排班的数组参数失败：%v", parseErr)
		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
		return
	}
	parseErr = json.Unmarshal([]byte(changeSchedulesJSON), &changeSchedules)
	if parseErr != nil {
		this.ErrorLog("解析修改排班的数组参数失败：%v", parseErr)
		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
		return
	}

	adminUserInfo := this.GetAdminUserInfo()
	templateIDs, getTemplateIDsErr := service.GetOrgPatientScheduleTemplateIDs(adminUserInfo.CurrentOrgId)
	if getTemplateIDsErr != nil {
		this.ErrorLog("获取排班模板失败：%v", getTemplateIDsErr)
		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
		return
	} else {
		isTemplateIDExist := false
		for _, templateIDObject := range templateIDs {
			if templateIDObject.ID == templateID {
				isTemplateIDExist = true
				break
			}
		}
		if isTemplateIDExist == false {
			this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeScheduleTemplateNotExist)
			return
		}
	}

	addTemplateItems := make([]*models.PatientScheduleTemplateItem, 0, len(addSchedules))
	delTemplateItems := make([]*models.PatientScheduleTemplateItem, 0, len(delSchedules))
	changeTemplateItems := make([]*models.PatientScheduleTemplateItem, 0, len(changeSchedules))
	for _, sch := range addSchedules {
		if sch.DeviceNumberID <= 0 || sch.PatientID <= 0 || sch.Weekday < 1 || sch.Weekday > 7 || sch.TimeType < 1 || sch.TimeType > 3 {
			this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
			return
		}
		addTemplateItems = append(addTemplateItems, &models.PatientScheduleTemplateItem{
			DeviceNumberID: sch.DeviceNumberID,
			PatientID:      sch.PatientID,
			TreatMode:      sch.Mode,
			Weekday:        sch.Weekday,
			TimeType:       sch.TimeType,
		})
	}
	for _, sch := range delSchedules {
		if sch.DeviceNumberID <= 0 || sch.Weekday < 1 || sch.Weekday > 7 || sch.TimeType < 1 || sch.TimeType > 3 {
			this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
			return
		}
		delTemplateItems = append(delTemplateItems, &models.PatientScheduleTemplateItem{
			DeviceNumberID: sch.DeviceNumberID,
			Weekday:        sch.Weekday,
			TimeType:       sch.TimeType,
		})
	}
	for _, sch := range changeSchedules {
		if sch.DeviceNumberID <= 0 || sch.PatientID <= 0 || sch.Weekday < 1 || sch.Weekday > 7 || sch.TimeType < 1 || sch.TimeType > 3 {
			this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
			return
		}
		changeTemplateItems = append(changeTemplateItems, &models.PatientScheduleTemplateItem{
			DeviceNumberID: sch.DeviceNumberID,
			PatientID:      sch.PatientID,
			TreatMode:      sch.Mode,
			Weekday:        sch.Weekday,
			TimeType:       sch.TimeType,
		})
	}

	templateMode, getTemplateModeErr := service.GetOrgPatientScheduleTemplateMode(adminUserInfo.CurrentOrgId)
	if getTemplateModeErr != nil {
		this.ErrorLog("获取排班模板启用模式失败：%v", getTemplateModeErr)
		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
		return
	} else if templateMode == nil {
		this.ErrorLog("获取不到排班模板启用模式")
		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
		return
	}

	shouldUpdateNextWeekSchedules := false
	shouldUpdateNextSecondWeekSchedules := false
	if templateMode.Mode == 0 {
		this.ErrorLog("当前未开启排班模板，所以更新模板的操作将被无视")
		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
		return
	}
	templateIDIndex := 1
	for index, templateIDObject := range templateIDs {
		if templateIDObject.ID == templateID {
			templateIDIndex = index + 1
		}
	}
	if templateMode.Mode == 1 {
		if templateIDIndex == 1 {
			shouldUpdateNextWeekSchedules = true
			shouldUpdateNextSecondWeekSchedules = true
		} else {
			this.ErrorLog("当前开启的是单周模板，所以不会更新第二个模板")
			this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeParamWrong)
			return
		}

	} else { // mode == 2 => 开启双周模板时，只需更新一周排班
		if templateIDIndex == 1 {
			if templateMode.ExecuteTimes%2 == 0 {
				shouldUpdateNextWeekSchedules = true
				shouldUpdateNextSecondWeekSchedules = false
			} else {
				shouldUpdateNextWeekSchedules = false
				shouldUpdateNextSecondWeekSchedules = true
			}

		} else {
			if templateMode.ExecuteTimes%2 == 0 {
				shouldUpdateNextWeekSchedules = false
				shouldUpdateNextSecondWeekSchedules = true
			} else {
				shouldUpdateNextWeekSchedules = true
				shouldUpdateNextSecondWeekSchedules = false
			}

		}
	}

	updateErr := service.UpdateScheduleTemplate(adminUserInfo.CurrentOrgId, templateID, addTemplateItems, delTemplateItems, changeTemplateItems, shouldUpdateNextWeekSchedules, shouldUpdateNextSecondWeekSchedules)
	if updateErr != nil {
		this.ErrorLog("更新排班模板排班失败：%v", updateErr)
		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDBUpdate)
		return
	}

	newItems, getTemplateItemsErr := service.GetOrgPatientScheduleTemplateItemsByTemplateID(adminUserInfo.CurrentOrgId, templateID)
	if getTemplateItemsErr != nil {
		this.ErrorLog("获取排班模板排班失败：%v", getTemplateItemsErr)
		this.ServeFailJSONWithSGJErrorCode(enums.ErrorCodeDataException)
		return
	}
	this.ServeSuccessJSON(map[string]interface{}{
		"items": newItems,
	})
}

type ParamModelSchedule struct {
	DeviceNumberID int64 `json:"device_number_id"`
	PatientID      int64 `json:"patient_id"`
	Mode           int64 `json:"mode"`
	Weekday        int8  `json:"weekday"`
	TimeType       int8  `json:"time_type"`
}
