package services

import (
	"database/sql"
	"errors"
	"fmt"
	"gin-vue-admin/common"
	"gin-vue-admin/models"
	"gin-vue-admin/repository"
	"gin-vue-admin/utils"
	"gin-vue-admin/utils/saas_file"
	"time"
)

func ConsumerAnalysisService(phone, t string) (interface{}, error) {

	// 1. 查询当前手机号是否有默认医院
	chainCode, _, err := repository.QueryChainCodeAndLocalIDByPhone(phone)
	if err != nil {
		return nil, err
	}

	if chainCode == "" {
		return nil, errors.New("请设置默认医院")
	}

	// 2. 拿到db
	safeMap := common.NewSafeMap()
	db, err := safeMap.GetOrStore(chainCode)
	if err != nil {
		return nil, err
	}

	return repository.ConsumerAnalysisRes(db, t)
}

func SourceDistributeService(phone string) (interface{}, error) {

	chainCode, _, err := repository.QueryChainCodeAndLocalIDByPhone(phone)
	if err != nil {
		return nil, err
	}

	if chainCode == "" {
		return nil, errors.New("请设置默认医院")
	}

	// 2. 拿到db
	safeMap := common.NewSafeMap()
	db, err := safeMap.GetOrStore(chainCode)
	if err != nil {
		return nil, err
	}

	return repository.SourceDistributeRes(db)
}

func ConsumptionRankService(phone, t string) (interface{}, error) {

	chainCode, _, err := repository.QueryChainCodeAndLocalIDByPhone(phone)
	if err != nil {
		return nil, err
	}

	if chainCode == "" {
		return nil, errors.New("请设置默认医院")
	}

	// 2. 拿到db
	safeMap := common.NewSafeMap()
	db, err := safeMap.GetOrStore(chainCode)
	if err != nil {
		return nil, err
	}

	return repository.ConsumptionRankRes(db, t)
}

func CardPreviewService(phone, t string) (interface{}, error) {

	chainCode, employeeID, err := repository.QueryChainCodeAndLocalIDByPhone(phone)
	if err != nil {
		return nil, err
	}

	if chainCode == "" {
		return nil, errors.New("请设置默认医院")
	}

	// 2. 拿到db
	safeMap := common.NewSafeMap()
	db, err := safeMap.GetOrStore(chainCode)
	if err != nil {
		return nil, err
	}

	hospitalID, err := repository.QueryHospitalLocalIDByEmployeeLocalID(db, employeeID)

	return repository.CardPreviewRes(db, t, hospitalID)
}

func CardPreviewChartService(phone, t string) (interface{}, error) {

	chainCode, _, err := repository.QueryChainCodeAndLocalIDByPhone(phone)
	if err != nil {
		return nil, err
	}

	if chainCode == "" {
		return nil, errors.New("请设置默认医院")
	}

	// 2. 拿到db
	safeMap := common.NewSafeMap()
	db, err := safeMap.GetOrStore(chainCode)
	if err != nil {
		return nil, err
	}

	return repository.CardPreviewChartRes(db, t)
}

func CardTypeService(phone string) (interface{}, error) {

	chainCode, _, err := repository.QueryChainCodeAndLocalIDByPhone(phone)
	if err != nil {
		return nil, err
	}

	if chainCode == "" {
		return nil, errors.New("请设置默认医院")
	}

	// 2. 拿到db
	safeMap := common.NewSafeMap()
	db, err := safeMap.GetOrStore(chainCode)
	if err != nil {
		return nil, err
	}

	return repository.CardTypeRes(db)
}

func CardDetailByIDService(phone, t string, cardID int) (interface{}, error) {

	chainCode, _, err := repository.QueryChainCodeAndLocalIDByPhone(phone)
	if err != nil {
		return nil, err
	}

	if chainCode == "" {
		return nil, errors.New("请设置默认医院")
	}

	// 2. 拿到db
	safeMap := common.NewSafeMap()
	db, err := safeMap.GetOrStore(chainCode)
	if err != nil {
		return nil, err
	}

	return repository.CardDetailByIDRes(db, t, cardID)
}

func AddConsumerAndPet(phone string, p *models.CreateConsumer) (interface{}, error) {

	chainCode, userId, err := repository.QueryChainCodeAndLocalIDByPhone(phone)
	if err != nil {
		return nil, err
	}

	if chainCode == "" {
		return nil, errors.New("请设置默认医院")
	}

	// 2. 拿到db
	safeMap := common.NewSafeMap()
	db, err := safeMap.GetOrStore(chainCode)
	if err != nil {
		return nil, err
	}

	hospitalId, err := repository.QueryHospitalLocalIDByEmployeeLocalID(db, userId)
	if err != nil {
		return nil, err
	}

	hospitalCode, err := repository.QueryHospitalCodeByEmployeeLocalID(db, hospitalId)
	if err != nil {
		return nil, err
	}

	addTime := time.Now().Format("2006-01-02 15:04:05")

	have, err := repository.CheckPhoneIsHave(db, p.ConsumerDetail.Telephone, hospitalId)
	if err != nil {
		return nil, err
	}

	if have > 0 {
		return nil, errors.New("手机号已经存在")
	}

	tx, err := db.Begin()
	if err != nil {
		return nil, err
	}

	queryRepeatCodeSQL := `select count(*) from his_pet 
where delflag = 0 and sys_hospital_id = ? and _code = ?`

	var repeatCodeCount int

	err = tx.QueryRow(queryRepeatCodeSQL, hospitalId, p.PetDetail.PetCode).Scan(&repeatCodeCount)
	if err != nil {
		return nil, err
	}
	if repeatCodeCount > 0 {
		return nil, errors.New("宠物编号不能重复")
	}

	queryConsumerCount := `select count(*) from his_consumer 
	where delflag = 0 and telephone = ?`

	var isConsumerCount int

	err = tx.QueryRow(queryConsumerCount, p.ConsumerDetail.Telephone).Scan(&isConsumerCount)
	if err != nil {
		return nil, err
	}
	if isConsumerCount > 0 {
		return nil, errors.New("顾客不能重复")
	}

	insertConsumerSQL := `insert his_consumer set creater = ?, sys_hospital_id = ?, _name = ?, namepy = ?, sex = ?,
telephone = ?,  birthday = ?, address = ?, understand = ?, email = ?, addtime = ?,is_cloud=1`

	insertPetSQL := `insert his_pet set creater = ?, sys_hospital_id = ?, his_consumer_id = ?, con_kind_id = ?, kind = ?, con_species_id = ?, species = ?,
_code = ?, _name = ?, namepy = ?, birthday = ?, sex = ?, coatcolor = ?, is_dead = ?, is_immunity = ?, is_sterilized = ?, is_insecticide = ?,
discription = ?, addtime = ?, sys_file_id = ?`

	consumerStmt, err := tx.Prepare(insertConsumerSQL)
	if err != nil {
		return nil, err
	}

	petStmt, err := tx.Prepare(insertPetSQL)
	if err != nil {
		return nil, err
	}

	result, err := consumerStmt.Exec(userId, hospitalId, p.ConsumerDetail.Name, p.ConsumerDetail.Namepy, p.ConsumerDetail.Sex,
		p.ConsumerDetail.Telephone, p.ConsumerDetail.Age, p.ConsumerDetail.Address, p.ConsumerDetail.Understand, p.ConsumerDetail.Email, addTime)
	if err != nil {
		return nil, err
	}
	consumerId, err := result.LastInsertId()
	if err != nil {
		tx.Rollback()
		return nil, err
	}

	// 判断是否是新增品种
	if p.PetDetail.ConSpeciesID == 0 && p.PetDetail.Species != "" {

		// 查询品种名称是否相同、相同则不能保存
		var speciesCount int
		err := db.QueryRow(`select count(id) from con_species
where _name = ? and delflag=0`, p.PetDetail.Species).Scan(&speciesCount)
		if err != nil {
			return nil, err
		}
		if speciesCount > 0 {
			return nil, errors.New("品种名称不能相同")
		}

		latestSpeciesCode, err := GetLatestCode(db, hospitalId, "")
		if err != nil {
			return nil, err
		}

		insertSpeciesSQL := "insert con_species set ordervalue = ?, creater = ?, sys_hospital_id = ?, _name = ?, namepy = ?, sys_kind_id = ?"
		result, err := tx.Exec(insertSpeciesSQL, latestSpeciesCode, userId, hospitalId, p.PetDetail.Species, p.PetDetail.SpeciesPy, p.PetDetail.ConKindId)
		if err != nil {
			tx.Rollback()
			return nil, err
		}
		speciesId, err := result.LastInsertId()
		if err != nil {
			tx.Rollback()
			return nil, err
		}
		p.PetDetail.ConSpeciesID = int(speciesId)
	}

	petResult, err := petStmt.Exec(userId, hospitalId, consumerId, p.PetDetail.ConKindId, p.PetDetail.Kind, p.PetDetail.ConSpeciesID,
		p.PetDetail.Species, p.PetDetail.PetCode, p.PetDetail.PetName, p.PetDetail.PetNamepy, p.PetDetail.PetBirthday, p.PetDetail.PetSex, p.PetDetail.CoatColor,
		p.PetDetail.IsDead, p.PetDetail.IsImmunity, p.PetDetail.IsSterilized, p.PetDetail.IsInsecticide, p.PetDetail.Discription, addTime, p.PetDetail.SysFileID)
	if err != nil {
		tx.Rollback()
		return nil, err
	}

	_, err = petResult.LastInsertId()
	if err != nil {
		tx.Rollback()
		return nil, err
	}

	go func() {
		cu := &models.ConsumerUploadModel{}
		cu.Address = p.ConsumerDetail.Address
		cu.Addtime = p.ConsumerDetail.AddTime
		cu.Birthday = p.ConsumerDetail.Birthday
		cu.ConsumerLocalID = consumerId
		cu.Email = p.ConsumerDetail.Email
		cu.Hospitalcode = hospitalCode
		cu.Name = p.ConsumerDetail.Name
		cu.Sex = p.ConsumerDetail.Sex
		cu.Telephone = p.ConsumerDetail.Telephone
		resp, err := utils.CustomHttpRequestUpload("POST", "https://gateway.pet-dbc.cn/gateway/hospital/consumer/add", cu, utils.GetReqHeaderSignData(chainCode, hospitalCode))
		if err == nil {
			if param, ok := resp.(models.Data); ok {
				if param.Code == 0 {
					db.Exec("update his_consumer set is_cloud=0 where id=?", cu.ConsumerLocalID)
				}
			}
		}
	}()

	err = tx.Commit()
	if err != nil {
		return nil, err
	}

	return consumerId, nil
}

func GetLatestCode(db *sql.DB, hospitalId int, tableName string) (interface{}, error) {

	queryLatestCodeSQL := fmt.Sprintf(`select ordervalue from %s 
where delflag = 0
ORDER BY ordervalue desc
limit 1`, tableName)

	var orderValue int
	err := db.QueryRow(queryLatestCodeSQL).Scan(&orderValue)
	switch {
	case err == sql.ErrNoRows:
		return 1, nil
	case err != nil:
		return nil, err
	}

	orderValue = orderValue + 1

	return orderValue, nil
}

func GetConsumerList(phone string, p *models.ConsumerListCondition) (interface{}, error) {

	chainCode, userId, err := repository.QueryChainCodeAndLocalIDByPhone(phone)
	if err != nil {
		return nil, err
	}

	if chainCode == "" {
		return nil, errors.New("请设置默认医院")
	}

	// 2. 拿到db
	safeMap := common.NewSafeMap()
	db, err := safeMap.GetOrStore(chainCode)
	if err != nil {
		return nil, err
	}

	hospitalId, err := repository.QueryHospitalLocalIDByEmployeeLocalID(db, userId)
	if err != nil {
		return nil, err
	}

	total, err := repository.GetConsumerTotalByCondition(db, p, int64(hospitalId))
	if err != nil {
		return nil, err
	}

	pageSize, page, pageData := utils.GetPageData(p.Page, p.PageSize, total)

	data, err := repository.GetConsumerListByCondition(db, p, int64(hospitalId), page, pageSize)
	if err != nil {
		return nil, err
	}

	pageData.Data = data

	var r models.Response

	r.PageData = pageData

	return r, nil

}

func GetConsumerDetail(phone string, consumerId string) (interface{}, error) {

	chainCode, userId, err := repository.QueryChainCodeAndLocalIDByPhone(phone)
	if err != nil {
		return nil, err
	}

	if chainCode == "" {
		return nil, errors.New("请设置默认医院")
	}

	if consumerId == "" {
		return nil, errors.New("参数有误")
	}

	// 2. 拿到db
	safeMap := common.NewSafeMap()
	db, err := safeMap.GetOrStore(chainCode)
	if err != nil {
		return nil, err
	}

	hospitalId, err := repository.QueryHospitalLocalIDByEmployeeLocalID(db, userId)
	if err != nil {
		return nil, err
	}

	data, err := repository.GetConsumerDetailById(db, consumerId, int64(hospitalId))
	if err != nil {
		return nil, err
	}

	return data, nil

}

func GetPetCode(phone string) (interface{}, error) {

	chainCode, userId, err := repository.QueryChainCodeAndLocalIDByPhone(phone)
	if err != nil {
		return nil, err
	}

	if chainCode == "" {
		return nil, errors.New("请设置默认医院")
	}

	// 2. 拿到db
	safeMap := common.NewSafeMap()
	db, err := safeMap.GetOrStore(chainCode)
	if err != nil {
		return nil, err
	}

	hospitalID, err := repository.QueryHospitalLocalIDByEmployeeLocalID(db, userId)
	if err != nil {
		return nil, err
	}

	return repository.GetLastPetCode(db, hospitalID)

}

func GetSpeciesList(phone, speciesId string) (interface{}, error) {

	chainCode, userId, err := repository.QueryChainCodeAndLocalIDByPhone(phone)
	if err != nil {
		return nil, err
	}

	if chainCode == "" {
		return nil, errors.New("请设置默认医院")
	}

	// 2. 拿到db
	safeMap := common.NewSafeMap()
	db, err := safeMap.GetOrStore(chainCode)
	if err != nil {
		return nil, err
	}

	hospitalID, err := repository.QueryHospitalLocalIDByEmployeeLocalID(db, userId)
	if err != nil {
		return nil, err
	}

	return repository.GetSpeciesList(db, hospitalID, speciesId)

}

func CreateAppointment(phone string, p *models.AppointmentParam) (interface{}, error) {

	chainCode, userId, err := repository.QueryChainCodeAndLocalIDByPhone(phone)
	if err != nil {
		return nil, err
	}

	if chainCode == "" {
		return nil, errors.New("请设置默认医院")
	}

	// 2. 拿到db
	safeMap := common.NewSafeMap()
	db, err := safeMap.GetOrStore(chainCode)
	if err != nil {
		return nil, err
	}

	hospitalId, err := repository.QueryHospitalLocalIDByEmployeeLocalID(db, userId)
	if err != nil {
		return nil, err
	}

	return repository.AddAppointment(db, p, hospitalId)

}

func GetFileByConsumerIDAndPetID(phone string, p *models.PreviewFileParam) (interface{}, error) {

	chainCode, userId, err := repository.QueryChainCodeAndLocalIDByPhone(phone)
	if err != nil {
		return nil, err
	}

	if chainCode == "" {
		return nil, errors.New("请设置默认医院")
	}

	if p.ConsumerId == "" || p.PetId == "" {
		return nil, errors.New("参数有误")
	}

	// 2. 拿到db
	safeMap := common.NewSafeMap()
	db, err := safeMap.GetOrStore(chainCode)
	if err != nil {
		return nil, err
	}

	hospitalId, err := repository.QueryHospitalLocalIDByEmployeeLocalID(db, userId)
	if err != nil {
		return nil, err
	}

	hospitalCode, err := repository.QueryHospitalCodeByEmployeeLocalID(db, hospitalId)
	if err != nil {
		return nil, err
	}

	file, err := saas_file.LOCAL_SAAS_FILE.ToPreviewFile(chainCode, hospitalCode, p.ConsumerId, p.PetId)
	if err != nil {
		return nil, err
	}

	return file, nil

}

func AppointmentTypeService(phone string) (interface{}, error) {

	chainCode, userId, err := repository.QueryChainCodeAndLocalIDByPhone(phone)
	if err != nil {
		return nil, err
	}

	if chainCode == "" {
		return nil, errors.New("请设置默认医院")
	}

	// 2. 拿到db
	safeMap := common.NewSafeMap()
	db, err := safeMap.GetOrStore(chainCode)
	if err != nil {
		return nil, err
	}

	var a models.AppointmentInfo

	hospitalId, err := repository.QueryHospitalLocalIDByEmployeeLocalID(db, userId)
	if err != nil {
		return nil, err
	}

	d := make([]models.AppointmentType, 0)

	names := []string{
		"基础免疫",
		"加强免疫",
		"驱虫",
		"门诊",
		"美容洗澡",
		"其它",
		"手术预约",
		"弓形虫基础免疫",
		"弓形虫加强免疫",
		"其它免疫",
		"抗体检测",
	}

	for k, v := range names {

		if k > 2 {
			k++
		}
		var t models.AppointmentType
		t.ID = k
		t.Name = v
		d = append(d, t)

	}

	reMind, err := repository.GetRemind(db, hospitalId)
	if err != nil {
		return nil, err
	}

	a.AppointmentType = d
	a.ReminderList = reMind

	return a, nil

}

func CheckPhoneIsHave(phone string, checkPhone string) (interface{}, error) {

	chainCode, userId, err := repository.QueryChainCodeAndLocalIDByPhone(phone)
	if err != nil {
		return nil, err
	}

	if chainCode == "" {
		return nil, errors.New("请设置默认医院")
	}

	// 2. 拿到db
	safeMap := common.NewSafeMap()
	db, err := safeMap.GetOrStore(chainCode)
	if err != nil {
		return nil, err
	}

	hospitalId, err := repository.QueryHospitalLocalIDByEmployeeLocalID(db, userId)
	if err != nil {
		return nil, err
	}

	return repository.CheckPhoneIsHave(db, checkPhone, hospitalId)

}
