package service

import (
	"errors"
	"fmt"
	"strings"
	"time"

	"XT_New/models"
)

func GetInspectionReference(orgId int64, inspect_type int64) (reference []*models.InspectionReference, err error) {
	if inspect_type == 0 {
		var count int
		err = readDb.Model(&models.InspectionReference{}).Where("org_id=? and status=1 and inspection_type = 0", orgId).Count(&count).Error
		if count > 0 {
			err = readDb.Model(&models.InspectionReference{}).Where("org_id=? and status=1 and inspection_type = 0", orgId).Order("project_id,created_time").Find(&reference).Error
		} else {
			err = readDb.Model(&models.InspectionReference{}).Where("org_id=0 and status=1 and inspection_type = 0").Order("project_id,created_time").Find(&reference).Error
		}
	} else {
		var count int
		err = readDb.Model(&models.InspectionReference{}).Where("org_id=? and status=1 and inspection_type = ?", orgId, inspect_type).Count(&count).Error
		if count > 0 {
			err = readDb.Model(&models.InspectionReference{}).Where("org_id=? and status=1 and inspection_type = ?", orgId, inspect_type).Order("project_id,created_time").Find(&reference).Error
		} else {
			err = readDb.Model(&models.InspectionReference{}).Where("org_id=0 and status=1 and inspection_type = ?", inspect_type).Order("project_id,created_time").Find(&reference).Error
		}
	}
	return
}

func GetPatientInspectionProjectCount(orgId, patientId int64) (projectCounts []*models.UserInspectionProjectCount, err error) {
	err = readDb.Model(&models.Inspection{}).Where("patient_id=? and org_id=? and status=1", patientId, orgId).Select("count(distinct inspect_date) as count, project_id, patient_id").Group("project_id").Scan(&projectCounts).Error
	return
}

func GetPatientInspectionByDate(orgId, patientId, date, projectId int64) (inspections []models.Inspection, err error) {
	err = readDb.Model(&models.Inspection{}).Where("patient_id=? and org_id=? and project_id =? and inspect_date =? and status=1", patientId, orgId, projectId, date).Order("created_time desc").Find(&inspections).Error
	return
}

func GetAdvices(orgid int64, patientid int64, recorddate int64) (advcie []*models.DoctorAdvice, err error) {
	err = XTReadDB().Model(&models.DoctorAdvice{}).Where("patient_id = ? and user_org_id = ? and record_date = ? and status =1", patientid, orgid, recorddate).Find(&advcie).Error
	return
}
func GetAdvicesByPrescription(orgid int64, patientid int64, recorddate int64) (models.DoctorAdvice, error) {
	advice := models.DoctorAdvice{}
	err = XTReadDB().Where("patient_id = ? and user_org_id = ? and record_date = ? and status =1 and is_prescription = 1", patientid, orgid, recorddate).Find(&advice).Error
	return advice, err
}
func UpdateDoctorAdvieById(id int64, prescription_number float64) (models.DoctorAdvice, error) {
	advice := models.DoctorAdvice{}
	err := XTWriteDB().Model(&advice).Where("id=? and status= 1", id).Updates(map[string]interface{}{"prescribing_number": prescription_number}).Error
	return advice, err
}
func UpdateDoctorAdvieByIdOne(id int64, prescription_number float64, single_dose float64) (models.DoctorAdvice, error) {
	advice := models.DoctorAdvice{}
	err := XTWriteDB().Model(&advice).Where("id=? and status= 1 ", id).Updates(map[string]interface{}{"prescribing_number": prescription_number, "single_dose": single_dose}).Error
	return advice, err
}
func CreatePatientInspection(inspectins []models.Inspection) (err error) {
	if len(inspectins) == 0 {
		err = errors.New("Inspections Cant be nil.")
		return
	}
	thisSQL := "INSERT INTO xt_inspection (patient_id, org_id, project_id, item_id, item_name, project_name, inspect_type, inspect_value, inspect_date, status, created_time, updated_time) VALUES "
	insertParams := make([]string, 0)
	insertData := make([]interface{}, 0)
	for _, inspectin := range inspectins {
		insertParams = append(insertParams, "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
		insertData = append(insertData, inspectin.PatientId)
		insertData = append(insertData, inspectin.OrgId)
		insertData = append(insertData, inspectin.ProjectId)
		insertData = append(insertData, inspectin.ItemId)
		insertData = append(insertData, inspectin.ItemName)
		insertData = append(insertData, inspectin.ProjectName)
		insertData = append(insertData, inspectin.InspectType)
		insertData = append(insertData, inspectin.InspectValue)
		insertData = append(insertData, inspectin.InspectDate)
		insertData = append(insertData, 1)
		insertData = append(insertData, inspectin.CreatedTime)
		insertData = append(insertData, inspectin.UpdatedTime)
	}
	thisSQL += strings.Join(insertParams, ", ")
	err = writeDb.Exec(thisSQL, insertData...).Error
	return
}
func SavePatientInspection(inspectin models.Inspection) (err error) {
	err = writeDb.Save(&inspectin).Error
	return
}
func DeleteInspectionTwo(id int64) {
	err = writeDb.Model(&models.Inspection{}).Where("id = ?", id).Updates(map[string]interface{}{"status": 0}).Error
	return
}
func EditPatientInspection(add []models.Inspection, edit []models.Inspection, noDeleteIDs []int64, patientId, orgId, projectId, date int64) (err error) {
	if len(add) == 0 && len(edit) == 0 && len(noDeleteIDs) == 0 {
		err = errors.New(" Cant be nil.")
		return
	}

	tx := writeDb.Begin()

	if len(noDeleteIDs) > 0 {
		err = tx.Model(&models.Inspection{}).Where("patient_id=? and org_id=? and project_id =? and inspect_date =? and id NOT IN (?) and status=1", patientId, orgId, projectId, date, noDeleteIDs).Update(map[string]interface{}{"Status": 0, "UpdatedTime": time.Now().Unix()}).Error
		if err != nil {
			tx.Rollback()
			return
		}
	}

	if len(edit) > 0 {
		for _, item := range edit {
			fmt.Println("o----------------------", item.ItemId)
			fmt.Println("value----------------------", item.InspectValue)
			err = tx.Save(&item).Error
			if err != nil {
				tx.Rollback()
				return
			}
		}
	}
	if len(add) > 0 {
		thisSQL := "INSERT INTO xt_inspection (patient_id, org_id, project_id, item_id, item_name, project_name, inspect_type, inspect_value, inspect_date, status, created_time, updated_time) VALUES "
		insertParams := make([]string, 0)
		insertData := make([]interface{}, 0)
		for _, inspectin := range add {
			insertParams = append(insertParams, "(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")
			insertData = append(insertData, inspectin.PatientId)
			insertData = append(insertData, inspectin.OrgId)
			insertData = append(insertData, inspectin.ProjectId)
			insertData = append(insertData, inspectin.ItemId)
			insertData = append(insertData, inspectin.ItemName)
			insertData = append(insertData, inspectin.ProjectName)
			insertData = append(insertData, inspectin.InspectType)
			insertData = append(insertData, inspectin.InspectValue)
			insertData = append(insertData, inspectin.InspectDate)
			insertData = append(insertData, 1)
			insertData = append(insertData, inspectin.CreatedTime)
			insertData = append(insertData, inspectin.UpdatedTime)
		}
		thisSQL += strings.Join(insertParams, ", ")
		err = tx.Exec(thisSQL, insertData...).Error
		if err != nil {
			tx.Rollback()
			return
		}
	}
	tx.Commit()

	return
}

func DeletePatientInspection(orgId, patientId, projectId, date int64) (err error) {
	err = writeDb.Model(&models.Inspection{}).Where("patient_id=? and org_id=? and project_id =? and inspect_date =? and status=1", patientId, orgId, projectId, date).Update(map[string]interface{}{"Status": 0, "UpdatedTime": time.Now().Unix()}).Error
	return
}

func GetPatientInspections(orgId, patientId, projectId, page int64) (inspections []models.Inspection, total int64, date int64, err error) {
	var projectCount models.UserInspectionProjectCount
	err = readDb.Model(&models.Inspection{}).Where("patient_id=? and org_id=? and project_id=? and status=1", patientId, orgId, projectId).Select("count(distinct inspect_date) as count, project_id, patient_id").Order("inspect_date desc").Scan(&projectCount).Error
	if err != nil {
		return
	}
	total = projectCount.Count
	if total == 0 || page > total {
		return
	}
	var Id models.InspectionDate
	err = readDb.Model(&models.Inspection{}).Where("patient_id=? and org_id=? and project_id=? and status=1", patientId, orgId, projectId).Select("inspect_date").Group("inspect_date").Order("inspect_date desc").Offset(page - 1).Limit(1).Scan(&Id).Error
	if err != nil {
		return
	}
	if Id.InspectDate == 0 {
		return
	}

	date = Id.InspectDate

	inspections, err = GetPatientInspectionByDate(orgId, patientId, Id.InspectDate, projectId)
	if err != nil {
		return
	}

	return

}

type DateViewModel struct {
	inspect_date int64 `gorm:"column:inspect_date" json:"inspect_date"`
	project_id   int64 `gorm:"column:project_id" json:"project_id"`
}

func FindLastRecordDate(orgId int64, patientId int64, project_id int64) (inspections models.Inspection, err error) {
	err = readDb.Raw("SELECT max(inspect_date) as inspect_date,project_id   FROM `xt_inspection`  WHERE (status = 1 AND org_id = ? AND project_id = ?  AND patient_id = ?) ORDER BY `xt_inspection`.`id` ASC LIMIT 1", orgId, project_id, patientId).Scan(&inspections).Error
	return
}

func UpDateInfectiousRecordTime(orgId int64, patientId int64, time int64, remind_cycle int64) (err error) {
	err = writeDb.Model(&models.Patients{}).Where("status = 1 AND user_org_id = ? AND id = ?", orgId, patientId).Updates(map[string]interface{}{"infectious_next_record_time": time, "remind_cycle": remind_cycle}).Error
	return
}

func CreateRemind(remind models.XtCheckRemind) (err error) {
	err = writeDb.Create(&remind).Error
	return
}

func UpDateCheckRemindRecordTime(orgId int64, patientId int64, time int64, project_id int64, remind_cycle int64) (err error) {
	err = writeDb.Model(&models.XtCheckRemind{}).Where("status = 1 AND user_org_id = ? AND patient_id = ? and project_id = ?", orgId, patientId, project_id).Updates(map[string]interface{}{"last_remind_date": time, "remind_cycle": remind_cycle}).Error
	return
}

func UpDateCheckRemindRecordTimeTwo(orgId int64, patientId int64, time int64, project_id int64) (err error) {
	err = writeDb.Model(&models.XtCheckRemind{}).Where("status = 1 AND user_org_id = ? AND patient_id = ? and project_id = ?", orgId, patientId, project_id).Updates(map[string]interface{}{"last_remind_date": time}).Error
	return
}

func GetCheckRemindRecordTime(orgId int64, patientId int64, project_id int64) (remind models.XtCheckRemind, err error) {
	err = writeDb.Model(&models.XtCheckRemind{}).Where("status = 1 AND user_org_id = ? AND patient_id = ? and project_id = ?", orgId, patientId, project_id).First(&remind).Error
	return
}

func GetAllPatientInspection(orgId, patientId, page int64, projectId int64, start_time int64, end_time int64) (inspections []models.Inspection, date int64, err error) {

	//var projectCount models.UserInspectionProjectCount
	//err = readDb.Model(&models.Inspection{}).Where("patient_id=? and org_id=? and project_id in (?)  and status=1", patientId, orgId,projectId).Select("count(distinct inspect_date) as count, project_id, patient_id").Scan(&projectCount).Error
	//
	//if err != nil {
	//	return
	//}
	//
	//total = projectCount.Count
	//if total == 0 || page > total {
	//	return
	//}

	var Id models.InspectionDate
	err = readDb.Model(&models.Inspection{}).Where("patient_id=? and org_id=? and project_id=? and status=1 and inspect_date >= ? and inspect_date <= ?", patientId, orgId, projectId, start_time, end_time).Select("inspect_date").Group("inspect_date").Order("inspect_date desc").Offset(page - 1).Limit(1).Scan(&Id).Error
	if err != nil {
		return
	}
	if Id.InspectDate == 0 {
		return
	}

	date = Id.InspectDate

	inspections, err = GetPatientInspectionByDate(orgId, patientId, Id.InspectDate, projectId)
	if err != nil {
		return
	}

	return

}

func GetAllInspectionReference(orgId int64) (inspectionReference []*models.InspectionReference, err error) {
	err = readDb.Model(&models.InspectionReference{}).Where("org_id = ? AND status = 1", orgId).Find(&inspectionReference).Error
	return
}

func GetInspectionReferenceByOrgId(orgid int64) (insepciton []*models.XtInspectionReference, err error) {

	err = readDb.Model(&insepciton).Where("org_id = ? and status = 1 and project_name = '传染病检查'", orgid).Find(&insepciton).Error
	return insepciton, err
}

func GetInspectionReferenceById(id int64) (insepciton models.XtInspectionReference, err error) {

	err = readDb.Model(&insepciton).Where("id = ?", id).First(&insepciton).Error
	return insepciton, err
}

func GetInspectionReferenceTwo(project_id int64) (reference []*models.InspectionReference, err error) {
	err = readDb.Model(&models.InspectionReference{}).Where("project_id = ? and status = 1", project_id).Order("project_id").Find(&reference).Error
	return
}

func GetInspectionReferenceThree(project_id int64, item_id int64) (reference models.InspectionReference, err error) {
	err = readDb.Model(&models.InspectionReference{}).Where("project_id = ? and id = ? and status = 1  and org_id = 0", project_id, item_id).Order("project_id").Find(&reference).Error
	return
}

func GetInspectionReferenceFour(project_id int64, item_id int64, org_id int64) (reference models.InspectionReference, err error) {
	err = readDb.Model(&models.InspectionReference{}).Where("project_id = ? and item_id = ? and status = 1 and org_id = ?", project_id, item_id, org_id).Order("project_id").Find(&reference).Error
	return
}

func GetInspectionReferenceFive(project_id int64, item_id int64, org_id int64) (reference models.InspectionReference, err error) {
	err = readDb.Model(&models.InspectionReference{}).Where("project_id = ? and id = ? and status = 1 and org_id = ?", project_id, item_id, 0).Order("project_id").Find(&reference).Error
	return
}
func GetInspectionTwo(startime int64, endtime int64, orgid int64, projectid int64, itemid int64) (inspection []*models.Inspection, total int64, err error) {
	db := XTReadDB().Table("xt_inspection as x").Where("x.status = 1")
	db = db.Where("project_id = ? and item_id = ?", projectid, itemid)
	if startime > 0 {
		db = db.Where("x.inspect_date >= ?", startime)
	}
	if endtime > 0 {
		db = db.Where("x.inspect_date<=?", endtime)
	}
	if orgid > 0 {
		db = db.Where("x.org_id = ?", orgid)
	}
	if projectid > 0 {
		db = db.Where("x.project_id = ?", projectid)
	}
	err = db.Count(&total).Order("x.inspect_date desc").Group("x.id").
		Select("x.id,x.patient_id,x.org_id,x.project_id,x.item_id,x.item_name,x.project_name,x.inspect_type,x.inspect_value,x.inspect_date,x.created_time").Find(&inspection).Error
	return inspection, total, err
}

// 查出日期差小于3天的数据
func GetAllInspectionRemind(org_id int64, patient_id int64) (check []models.XtCheckRemind, err error) {
	err = readDb.Model(&models.XtCheckRemind{}).Preload("InspectionReference", "status = 1").Where("patient_id = ? and status = 1  and user_org_id = ? and DATEDIFF(FROM_UNIXTIME(last_remind_date),NOW()) < 3 and last_remind_date <> 0", patient_id, org_id).Find(&check).Error
	return
}

func GetLastInspection(patientid int64, date int64, projectid int64, orgid int64) (models.Inspection, error) {
	inspection := models.Inspection{}
	err := XTReadDB().Group("inspect_date").Order("inspect_date asc").Where("patient_id = ? and inspect_date < ? and project_id =? and status=1 and org_id= ?", patientid, date, projectid, orgid).Limit(1).Find(&inspection).Error
	return inspection, err

}

func GetNextInspection(patientid int64, date int64, projectid int64, orgid int64) (models.Inspection, error) {
	inspection := models.Inspection{}
	err := XTReadDB().Group("inspect_date").Order("inspect_date asc").Where("patient_id = ? and inspect_date > ? and project_id =? and status=1 and org_id= ?", patientid, date, projectid, orgid).Limit(1).Find(&inspection).Error
	return inspection, err
}

func GetLastInspectionDetail(patientid int64, date int64, projectid int64, orgid int64) (inspection []*models.Inspections, err error) {
	db := XTReadDB().Table("xt_inspection as x").Where("x.status =1")
	if patientid > 0 {
		db = db.Where("x.patient_id = ?", patientid)
	}
	if date > 0 {
		db = db.Where("x.inspect_date = ?", date)
	}
	if orgid > 0 {
		db = db.Where("x.org_id = ?", orgid)
	}
	if projectid > 0 {
		db = db.Where("x.project_id = ?", projectid)
	}
	err = db.Order("inspect_date asc").Group("x.id").Select("x.id,x.patient_id,x.org_id,x.project_id,x.item_id,x.item_name,x.project_name,x.inspect_type,x.inspect_value,x.inspect_date,x.status,x.created_time,x.updated_time,r.range_type,r.range_min,r.range_max,r.range_value,r.range_options,r.unit").Joins("left join xt_inspection_reference as r on (r.item_id = x.item_id AND r.org_id = x.org_id) OR ( x.item_id = r.id AND r.org_id = 0)   ").Scan(&inspection).Error
	return inspection, err
}

func GetInsepctionConfigurationList(orgid int64) (standard []*models.QualityControlStandard, err error) {
	db := XTReadDB().Table("xt_quality_control_standard as x").Where("x.status =1")
	db = db.Where("x.user_org_id = ? and x.is_status =1", orgid)
	err = db.Order("x.sort asc,x.created_time desc").Group("x.id").Select("x.id,x.inspection_major,x.inspection_minor,x.min_range,x.large_range,x.sort,x.user_org_id,x.range_value,x.range_type,s.unit,s.project_name,s.item_name,x.is_status").
		Joins("left join xt_inspection_reference as s on s.item_id = x.inspection_minor and s.project_id = x.inspection_major").Where("s.org_id = ? and s.status = 1", orgid).Scan(&standard).Error
	return standard, err
}

func GetInsepctionConfigurationListTwo(orgid int64) (standard []*models.QualityControlStandard, err error) {
	db := XTReadDB().Table("xt_quality_control_standard as x").Where("x.status =1")
	db = db.Where("x.user_org_id = ? and x.is_status =1", orgid)
	err = db.Order("x.sort asc,x.created_time desc").Group("x.id").Select("x.id,x.inspection_major,x.inspection_minor,x.min_range,x.large_range,x.sort,x.user_org_id,x.range_value,x.range_type,s.unit,s.project_name,s.item_name,x.is_status").
		Joins("left join xt_inspection_reference as s on s.id = x.inspection_minor and s.project_id = x.inspection_major").Where("s.org_id = 0 and s.status = 1").Scan(&standard).Error
	return standard, err
}

func GetInspectionGroup(patient_id int64, org_id int64) (inspection []*models.NewInspection, err error) {

	db := XTReadDB().Table("xt_inspection").Where("status =1")

	if patient_id > 0 {
		db = db.Where("patient_id = ?", patient_id)
	}
	if org_id > 0 {
		db = db.Where("org_id = ?", org_id)
	}

	err = db.Order("inspect_date asc").Group("project_id").Scan(&inspection).Error
	return inspection, err
}

func GetInspectionGroupOne(org_id int64) (inspection []*models.XtInspectionOne, err error) {

	//XTReadDB().Model(&inspection).Where("(org_id = ? or org_id = 0) and status=1", patient_id, org_id).Find()

	err = readDb.Raw("SELECT r.project_name,r.project_id,x.inspect_date FROM xt_inspection as x LEFT JOIN xt_inspection_reference as r on r.project_id = x.project_id WHERE (x.org_id = ? or x.org_id = 0) and x.project_id >0 GROUP BY r.project_id ", org_id).Scan(&inspection).Error

	return inspection, err
}

func GetLastInspectionProject(patient_id int64, org_id int64, project_id int64) (models.XtInspection, error) {

	inspection := models.XtInspection{}

	err := XTReadDB().Where("patient_id = ? and org_id = ? and project_id = ? and status=1", patient_id, org_id, project_id).Last(&inspection).Error

	return inspection, err
}

func GetInspectionByProjectId(patient_id int64, org_id int64, project_id int64) (inspection []*models.NewInspection, err error) {

	db := XTReadDB().Table("xt_inspection").Where("status =1")

	if patient_id > 0 {
		db = db.Where("patient_id = ?", patient_id)
	}
	if org_id > 0 {
		db = db.Where("org_id = ?", org_id)
	}
	if project_id > 0 {
		db = db.Where("project_id = ?", project_id)
	}

	err = db.Order("id asc").Group("inspect_date").Scan(&inspection).Error
	return inspection, err

}

func GetInSpctionRerefce(project_id int64, user_org_id int64) (inspct []*models.InspectionReference, err error) {

	err = XTReadDB().Where("project_id = ? and (org_id = ? or org_id=0) and status =1", project_id, user_org_id).Order("sort desc").Find(&inspct).Error
	return inspct, err
}

func GetInspectionGroupByRecordDate(patient_id int64, project_id int64, org_id int64) (inspetion []*models.Inspection, err error) {

	err = XTReadDB().Where("patient_id = ? and project_id = ? and org_id = ? and status=1", patient_id, project_id, org_id).Order("inspect_date desc").Limit(10).Group("inspect_date").Find(&inspetion).Error

	return inspetion, err
}

func GetInspectionByProject(patient_id int64, project_id int64, org_id int64, record_date int64) (inspection []*models.Inspection, err error) {

	err = XTReadDB().Where("patient_id = ? and project_id = ? and org_id = ? and status=1 and inspect_date =?", patient_id, project_id, org_id, record_date).Order("id desc").Group("item_id").Find(&inspection).Error

	return inspection, err
}

func GetNewInspectionList(patient_id int64, project_id int64, user_org_id int64) (inspection []*models.Inspection, err error) {

	err = XTReadDB().Where("patient_id = ? and project_id = ? and org_id = ?", patient_id, project_id, user_org_id).Find(&inspection).Error

	return inspection, err
}

func GetNewGroupInspectionList(patient_id int64, project_id int64, user_org_id int64) (inspection []*models.Inspection, err error) {

	err = XTReadDB().Where("patient_id = ? and project_id = ? and org_id = ?", patient_id, project_id, user_org_id).Group("item_id").Find(&inspection).Error

	return inspection, err
}

func GetNewGroupInspectionInspectionList(patient_id int64, project_id int64, user_org_id int64) (inspection []*models.Inspection, err error) {

	err = XTReadDB().Where("patient_id = ? and project_id = ? and org_id = ?", patient_id, project_id, user_org_id).Group("inspect_date").Order("inspect_date asc").Find(&inspection).Error
	return inspection, err
}

func GetNewInspectionDetailList(project_id int64, inspect_value int64, patient_id int64) (inpection []*models.Inspection, err error) {

	err = XTReadDB().Where("project_id =? and inspect_date = ? and patient_id = ?", project_id, inspect_value, patient_id).Find(&inpection).Error

	return inpection, err
}