// 管理员查看指定日期后30天内的所有咨询
func (rl *ReservationLogic) GetReservationsMonthlyByAdmin(from string, userId string, userType models.UserType) ([]*models.Reservation, error) {
	if len(userId) == 0 {
		return nil, errors.New("请先登录")
	} else if userType != models.ADMIN {
		return nil, errors.New("权限不足")
	}
	admin, err := models.GetUserById(userId)
	if err != nil || admin.UserType != models.ADMIN {
		return nil, errors.New("管理员账户出错,请联系技术支持")
	}
	fromDate, err := time.ParseInLocation(utils.DATE_PATTERN, from, utils.Location)
	if err != nil {
		return nil, errors.New("时间格式错误")
	}
	toDate := fromDate.AddDate(0, 0, 30)
	reservations, err := models.GetReservationsBetweenTime(fromDate, toDate)
	if err != nil {
		return nil, errors.New("获取数据失败")
	}
	var result []*models.Reservation
	for _, r := range reservations {
		if r.Status == models.AVAILABLE && r.StartTime.Before(time.Now().In(utils.Location)) {
			continue
		}
		result = append(result, r)
	}
	return result, nil
}
func main() {
	appEnv := flag.String("app-env", "STAGING", "app environment")
	smsUid := flag.String("sms-uid", "", "sms uid")
	smsKey := flag.String("sms-key", "", "sms key")
	flag.Parse()
	utils.APP_ENV = *appEnv
	utils.SMS_UID = *smsUid
	utils.SMS_KEY = *smsKey
	// 数据库连接
	mongoDbDialInfo := mgo.DialInfo{
		Addrs:    []string{"127.0.0.1:27017"},
		Timeout:  60 * time.Second,
		Database: "admin",
		Username: "******",
		Password: "******",
	}
	var session *mgo.Session
	var err error
	if utils.APP_ENV == "ONLINE" {
		session, err = mgo.DialWithInfo(&mongoDbDialInfo)
	} else {
		session, err = mgo.Dial("127.0.0.1:27017")
	}
	if err != nil {
		fmt.Printf("连接数据库失败:%v\n", err)
		return
	}
	defer session.Close()
	session.SetMode(mgo.Monotonic, true)
	models.Mongo = session.DB("appointment")
	// 时区
	location, err := time.LoadLocation("Asia/Shanghai")
	if err != nil {
		fmt.Printf("初始化时区失败:%v\n", err)
		return
	}
	// Reminder
	now := time.Now().In(location)
	year, month, day := now.Date()
	today := time.Date(year, month, day, 0, 0, 0, 0, location)
	from := today.AddDate(0, 0, 1)
	to := today.AddDate(0, 0, 2)
	reservations, err := models.GetReservationsBetweenTime(from, to)
	if err != nil {
		fmt.Errorf("获取咨询列表失败:%v", err)
		return
	}
	for _, reservation := range reservations {
		if reservation.Status == models.RESERVATED {
			utils.SendReminderSMS(reservation)
		}
	}
}
// 学生查看前后一周内的所有咨询
func (rl *ReservationLogic) GetReservationsByStudent() ([]*models.Reservation, error) {
	from := time.Now().In(utils.Location).AddDate(0, 0, -7)
	to := time.Now().In(utils.Location).AddDate(0, 0, 8)
	reservations, err := models.GetReservationsBetweenTime(from, to)
	if err != nil {
		return nil, errors.New("获取数据失败")
	}
	var result []*models.Reservation
	for _, r := range reservations {
		if r.Status == models.AVAILABLE && r.StartTime.Before(time.Now().In(utils.Location)) {
			continue
		}
		result = append(result, r)
	}
	return result, nil
}
// 咨询师编辑咨询
func (tl *TeacherLogic) EditReservationByTeacher(reservationId string, startTime string, endTime string,
	teacherFullname string, teacherMobile string, userId string, userType models.UserType) (*models.Reservation, error) {
	if len(userId) == 0 {
		return nil, errors.New("请先登录")
	} else if userType != models.TEACHER {
		return nil, errors.New("权限不足")
	} else if len(reservationId) == 0 {
		return nil, errors.New("咨询已下架")
	} else if len(startTime) == 0 {
		return nil, errors.New("开始时间为空")
	} else if len(endTime) == 0 {
		return nil, errors.New("结束时间为空")
	} else if len(teacherFullname) == 0 {
		return nil, errors.New("咨询师姓名为空")
	} else if len(teacherMobile) == 0 {
		return nil, errors.New("咨询师手机号为空")
	} else if !utils.IsMobile(teacherMobile) {
		return nil, errors.New("咨询师手机号格式不正确")
	}
	reservation, err := models.GetReservationById(reservationId)
	if err != nil || reservation.Status == models.DELETED {
		return nil, errors.New("咨询已下架")
	} else if reservation.Status == models.RESERVATED {
		return nil, errors.New("不能编辑已被预约的咨询")
	}
	start, err := time.ParseInLocation(utils.TIME_PATTERN, startTime, utils.Location)
	if err != nil {
		return nil, errors.New("开始时间格式错误")
	}
	end, err := time.ParseInLocation(utils.TIME_PATTERN, endTime, utils.Location)
	if err != nil {
		return nil, errors.New("结束时间格式错误")
	}
	if start.After(end) {
		return nil, errors.New("开始时间不能晚于结束时间")
	} else if end.Before(time.Now().In(utils.Location)) {
		return nil, errors.New("不能编辑已过期咨询")
	}
	teacher, err := models.GetUserById(userId)
	if err != nil {
		return nil, errors.New("咨询师账户失效")
	} else if teacher.UserType != models.TEACHER {
		return nil, errors.New("权限不足")
	} else if !strings.EqualFold(teacher.Username, reservation.TeacherUsername) {
		return nil, errors.New("只能编辑本人开设的咨询")
	}
	if !strings.EqualFold(teacher.Fullname, teacherFullname) || !strings.EqualFold(teacher.Mobile, teacherMobile) {
		teacher.Fullname = teacherFullname
		teacher.Mobile = teacherMobile
		if err = models.UpsertUser(teacher); err != nil {
			return nil, errors.New("数据获取失败")
		}
	}
	// 检查当天的咨询师时间是否有冲突
	theDay := time.Date(start.Year(), start.Month(), start.Day(), 0, 0, 0, 0, utils.Location)
	nextDay := theDay.AddDate(0, 0, 1)
	theDayReservations, err := models.GetReservationsBetweenTime(theDay, nextDay)
	if err != nil {
		return nil, errors.New("数据获取失败")
	}
	for _, r := range theDayReservations {
		if !strings.EqualFold(r.Id.Hex(), reservation.Id.Hex()) &&
			strings.EqualFold(r.TeacherUsername, teacher.Username) {
			if (start.After(r.StartTime) && start.Before(r.EndTime)) ||
				(end.After(r.StartTime) && end.Before(r.EndTime)) ||
				(!start.After(r.StartTime) && !end.Before(r.EndTime)) {
				return nil, errors.New("咨询师时间有冲突")
			}
		}
	}
	reservation.StartTime = start
	reservation.EndTime = end
	reservation.TeacherFullname = teacherFullname
	reservation.TeacherMobile = teacherMobile
	if err = models.UpsertReservation(reservation); err != nil {
		return nil, errors.New("数据获取失败")
	}
	return reservation, nil
}
// 管理员添加咨询
func (al *AdminLogic) AddReservationByAdmin(startTime string, endTime string, teacherUsername string,
	teacherFullname string, teacherMobile string, userId string, userType models.UserType) (*models.Reservation, error) {
	if len(userId) == 0 {
		return nil, errors.New("请先登录")
	} else if userType != models.ADMIN {
		return nil, errors.New("权限不足")
	} else if len(startTime) == 0 {
		return nil, errors.New("开始时间为空")
	} else if len(endTime) == 0 {
		return nil, errors.New("结束时间为空")
	} else if len(teacherUsername) == 0 {
		return nil, errors.New("咨询师工号为空")
	} else if len(teacherFullname) == 0 {
		return nil, errors.New("咨询师姓名为空")
	} else if len(teacherMobile) == 0 {
		return nil, errors.New("咨询师手机号为空")
	} else if !utils.IsMobile(teacherMobile) {
		return nil, errors.New("咨询师手机号格式不正确")
	}
	admin, err := models.GetUserById(userId)
	if err != nil || admin.UserType != models.ADMIN {
		return nil, errors.New("管理员账户出错,请联系技术支持")
	}
	start, err := time.ParseInLocation(utils.TIME_PATTERN, startTime, utils.Location)
	if err != nil {
		return nil, errors.New("开始时间格式错误")
	}
	end, err := time.ParseInLocation(utils.TIME_PATTERN, endTime, utils.Location)
	if err != nil {
		return nil, errors.New("结束时间格式错误")
	}
	if start.After(end) {
		return nil, errors.New("开始时间不能晚于结束时间")
	}
	teacher, err := models.GetUserByUsername(teacherUsername)
	if err != nil {
		if teacher, err = models.AddFullUser(teacherUsername, TeacherDefaultPassword, teacherFullname,
			teacherMobile, models.TEACHER); err != nil {
			return nil, errors.New("获取数据失败")
		}
	} else if teacher.UserType != models.TEACHER {
		return nil, errors.New("权限不足")
	} else if !strings.EqualFold(teacher.Fullname, teacherFullname) || !strings.EqualFold(teacher.Mobile, teacherMobile) {
		teacher.Fullname = teacherFullname
		teacher.Mobile = teacherMobile
		if err = models.UpsertUser(teacher); err != nil {
			return nil, errors.New("数据获取失败")
		}
	}
	// 检查当天的咨询师时间是否有冲突
	theDay := time.Date(start.Year(), start.Month(), start.Day(), 0, 0, 0, 0, utils.Location)
	nextDay := theDay.AddDate(0, 0, 1)
	theDayReservations, err := models.GetReservationsBetweenTime(theDay, nextDay)
	if err != nil {
		return nil, errors.New("数据获取失败")
	}
	for _, r := range theDayReservations {
		if strings.EqualFold(r.TeacherUsername, teacher.Username) {
			if (start.After(r.StartTime) && start.Before(r.EndTime)) ||
				(end.After(r.StartTime) && end.Before(r.EndTime)) ||
				(!start.After(r.StartTime) && !end.Before(r.EndTime)) {
				return nil, errors.New("咨询师时间有冲突")
			}
		}
	}
	reservation, err := models.AddReservation(start, end, teacher.Fullname, teacher.Username, teacher.Mobile)
	if err != nil {
		return nil, errors.New("数据获取失败")
	}
	return reservation, nil
}