package dao

import (
	"fmt"
	"time"

	"git.rosy.net.cn/baseapi/utils"
	"git.rosy.net.cn/jx-callback/business/jxutils"
	"git.rosy.net.cn/jx-callback/business/model"
)

type StoreWithCityName struct {
	model.Store
	CityName    string         `json:"cityName"`
	VendorStore []StoreMapList `json:"vendorStore"`
}

type UserDeliveryAddressEx struct {
	model.UserDeliveryAddress

	UserName     string `json:"userName"`
	CityName     string `json:"cityName"`
	DistrictName string `json:"districtName"`
	ParentCode   int    `json:"parentCode"`
}

type StoreMapList struct {
	JxStoreId     int    `json:"jx_store_id"`
	VendorStoreId string `json:"vendor_store_id"`
	VendorId      int    `json:"vendor_id"`
	VendorOrgCode string `json:"vendor_org_code"`
}

type GetSelfInfoResult struct {
	model.User
	UserMembers []*model.UserMember `json:"userMembers"`
}

func GetUserByID(db *DaoDB, fieldName, fieldValue string) (user *model.User, err error) {
	sql := fmt.Sprintf(`
	SELECT *
	FROM user t1
	WHERE t1.deleted_at = ? AND t1.status = ? AND t1.%s = ?  
	`, fieldName)
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
		model.UserStatusNormal,
		fieldValue,
	}
	err = GetRow(db, &user, sql, sqlParams...)
	return user, err
}

func GetUserByIDWithMembers(db *DaoDB, fieldName, fieldValue string) (getSelfInfoResult *GetSelfInfoResult, err error) {
	sql := fmt.Sprintf(`
	SELECT *
	FROM user t1
	WHERE t1.deleted_at = ? AND t1.status = ? AND t1.%s = ?
	`, fieldName)
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
		model.UserStatusNormal,
		fieldValue,
	}
	err = GetRow(db, &getSelfInfoResult, sql, sqlParams...)
	return getSelfInfoResult, err
}

func GetUsers(db *DaoDB, userType int, keyword string, userIDs, userID2s, mobiles []string, offset, pageSize int) (userList []*model.User, totalCount int, err error) {
	offset = jxutils.FormalizePageOffset(offset)
	pageSize = jxutils.FormalizePageSize(pageSize)
	if userType == 0 {
		userType = 255
	}
	sql := `
	SELECT SQL_CALC_FOUND_ROWS
	t1.*
	FROM user t1
	WHERE t1.status = 1 AND t1.deleted_at = ? AND t1.type & ? <> 0`
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
		userType,
	}
	if len(userIDs) > 0 {
		sql += " AND t1.user_id IN (" + GenQuestionMarks(len(userIDs)) + ")"
		sqlParams = append(sqlParams, userIDs)
	}
	if len(userID2s) > 0 {
		sql += " AND t1.user_id2 IN (" + GenQuestionMarks(len(userID2s)) + ")"
		sqlParams = append(sqlParams, userID2s)
	}
	if len(mobiles) > 0 {
		sql += " AND t1.mobile IN (" + GenQuestionMarks(len(mobiles)) + ")"
		sqlParams = append(sqlParams, mobiles)
	}
	if keyword != "" {
		keywordLike := "%" + keyword + "%"
		sql += " AND (t1.user_id LIKE ? OR t1.user_id2 LIKE ? OR t1.mobile LIKE ? OR t1.email LIKE ? OR t1.name LIKE ?)"
		sqlParams = append(sqlParams, keywordLike, keywordLike, keywordLike, keywordLike, keywordLike)
	}
	sql += " LIMIT ? OFFSET ?"
	sqlParams = append(sqlParams, pageSize, offset)
	txDB, _ := Begin(db)
	defer Commit(db, txDB)
	if err = GetRowsTx(txDB, &userList, sql, sqlParams...); err == nil {
		totalCount = GetLastTotalRowCount2(db, txDB)
	}
	return userList, totalCount, err
}

func DeleteUsers(db *DaoDB, userIDs []string) (num int64, err error) {
	if len(userIDs) > 0 {
		sql := `
	UPDATE user t1
	JOIN auth_bind t2 ON t2.user_id = t1.user_id
	SET
	t1.deleted_at = ?,
	t2.deleted_at = ?
	WHERE t1.user_id IN (` + GenQuestionMarks(len(userIDs)) + ");"
		now := time.Now()
		sqlParams := []interface{}{
			now,
			now,
			userIDs,
		}
		num, err = ExecuteSQL(db, sql, sqlParams...)
	}
	return num, err
}

// func GetStoreListByMobile(db *DaoDB, mobile string) (storeList []*StoreWithCityName, err error) {
// 	if mobile != "" {
// 		sql := `
// 		SELECT
// 		DISTINCT t1.*, t2.name city_name
// 		FROM (
// 			SELECT *
// 			FROM store t1
// 			WHERE (t1.market_man_phone = ? OR t1.operator_phone = ? OR t1.operator_phone2 = ? OR t1.operator_phone3 = ?)
// 			UNION DISTINCT
// 			SELECT t1.*
// 			FROM store t1
// 			JOIN weixins t2 ON t2.jxstoreid = t1.id AND t2.parentid = -1
// 			LEFT JOIN weixins t3 ON t3.parentid = t2.id
// 			WHERE (t2.tel = ? OR t3.tel = ?)
// 		) t1
// 		LEFT JOIN place t2 ON t2.code = t1.city_code
// 		WHERE t1.deleted_at = ?
// 		ORDER BY t1.name`
// 		sqlParams := []interface{}{
// 			mobile, mobile, mobile, mobile,
// 			mobile, mobile,
// 			utils.DefaultTimeValue,
// 		}
// 		err = GetRows(db, &storeList, sql, sqlParams...)
// 	}
// 	return storeList, err
// }

func GetStoreListByMobileOrStoreIDs(db *DaoDB, mobile string, shortRoleNameList []string, storeIDs []int) (storeList []*StoreWithCityName, err error) {
	sql := `
		SELECT t1.*, t2.name city_name
		FROM store t1
		LEFT JOIN place t2 ON t2.code = t1.city_code
		WHERE t1.deleted_at = ? AND ( 1 = 0`
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
	}
	if mobile != "" {
		sql += " OR t1.tel1 = ? OR t1.tel2 = ? OR t1.market_man_phone = ? OR t1.operator_phone = ? OR t1.operator_phone2 = ? OR t1.operator_phone3 = ?"
		sqlParams = append(sqlParams, mobile, mobile, mobile, mobile, mobile, mobile)
	}
	if len(shortRoleNameList) > 0 {
		questionMarks := GenQuestionMarks(len(shortRoleNameList))
		sql += " OR t1.market_man_role IN (" + questionMarks + ") OR t1.operator_role IN (" + questionMarks + ") OR t1.operator_role2 IN (" + questionMarks + ") OR t1.operator_role3 IN (" + questionMarks + ")"
		sqlParams = append(sqlParams, shortRoleNameList, shortRoleNameList, shortRoleNameList, shortRoleNameList)
	}
	if len(storeIDs) > 0 {
		sql += " OR t1.id IN (" + GenQuestionMarks(len(storeIDs)) + ")"
		sqlParams = append(sqlParams, storeIDs)
	}
	sql += ")"
	err = GetRows(db, &storeList, sql, sqlParams...)
	return storeList, err
}

func QueryUserDeliveryAddress(db *DaoDB, addressID int64, userIDs []string, offset, pageSize int) (addressList []*UserDeliveryAddressEx, totalCount int, err error) {
	sql := `
	SELECT SQL_CALC_FOUND_ROWS
	t1.*,
	t2.name user_name,
	district.name district_name,
	city.name city_name,
	cp.code parent_code
	FROM user_delivery_address t1
	LEFT JOIN user t2 ON t2.user_id = t1.user_id
	LEFT JOIN place district ON district.code = t1.district_code
	LEFT JOIN place city ON city.code = t1.city_code
	LEFT JOIN place cp ON cp.code = city.parent_code
	WHERE t1.deleted_at = ?
	`
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
	}
	if addressID > 0 {
		sql += " AND t1.id = ? "
		sqlParams = append(sqlParams, addressID)
	}
	if len(userIDs) > 0 {
		sql += " AND t1.user_id IN (" + GenQuestionMarks(len(userIDs)) + ")"
		sqlParams = append(sqlParams, userIDs)
	}
	offset = jxutils.FormalizePageOffset(offset)
	pageSize = jxutils.FormalizePageSize(pageSize)
	sql += `
	ORDER BY t1.is_default DESC, t1.consignee_name
	LIMIT ? OFFSET ?`
	sqlParams = append(sqlParams, pageSize, offset)

	txDB, _ := Begin(db)
	defer Commit(db, txDB)
	if err = GetRowsTx(txDB, &addressList, sql, sqlParams...); err == nil {
		totalCount = GetLastTotalRowCount2(db, txDB)
	}
	return addressList, totalCount, err
}

func ClearUserDeliveryAddressDefault(db *DaoDB, userID string, defAddressID int) (err error) {
	sql := `
	UPDATE user_delivery_address t1
	SET t1.is_default = 0
	WHERE t1.deleted_at = ? AND t1.user_id = ?
	`
	sqlParams := []interface{}{
		utils.DefaultTimeValue,
		userID,
	}
	if defAddressID > 0 {
		sql += " AND t1.id <> ?"
		sqlParams = append(sqlParams, defAddressID)
	}
	_, err = ExecuteSQL(db, sql, sqlParams...)
	return err
}

func GetUserAgreement(db *DaoDB, name, idNumber, bankNumber, mobile string) (userAgrs []*model.UserAgreement, err error) {
	sql := `
		SELECT * 
		FROM user_agreement
		WHERE deleted_at = ? 
	`
	sqlParams := []interface{}{utils.DefaultTimeValue}
	if name != "" {
		sql += " AND name like ?"
		sqlParams = append(sqlParams, "%"+name+"%")
	}
	if idNumber != "" {
		sql += " AND idNumber like ?"
		sqlParams = append(sqlParams, "%"+idNumber+"%")
	}
	if bankNumber != "" {
		sql += " AND bankNumber like ?"
		sqlParams = append(sqlParams, "%"+bankNumber+"%")
	}
	if mobile != "" {
		sql += " AND mobile like ?"
		sqlParams = append(sqlParams, "%"+mobile+"%")
	}
	err = GetRows(db, &userAgrs, sql, sqlParams)
	return userAgrs, err
}

func GetUserOrderSMS(db *DaoDB, mobile, name string) (userOrderSms *model.UserOrderSms, err error) {
	sql := `
		SELECT * 
		  FROM user_order_sms
		 WHERE 1=1 
	`
	sqlParams := []interface{}{}
	if mobile != "" {
		sql += " AND mobile = ?"
		sqlParams = append(sqlParams, mobile)
	}
	if name != "" {
		sql += " AND name like ?"
		sqlParams = append(sqlParams, "%"+name+"%")
	}
	err = GetRow(db, &userOrderSms, sql, sqlParams)
	return userOrderSms, err
}

func GetUserMember(db *DaoDB, userID, vendorOrderID, mobile string, vendorID, memberType, isPay int) (userMembers []*model.UserMember, err error) {
	sql := `
		SELECT * 
		  FROM user_member
		 WHERE deleted_at = ? 
	`
	sqlParams := []interface{}{utils.DefaultTimeValue}
	if userID != "" {
		sql += " AND user_id = ?"
		sqlParams = append(sqlParams, userID)
	}
	if vendorOrderID != "" {
		sql += " AND vendor_order_id = ?"
		sqlParams = append(sqlParams, vendorOrderID)
	}
	if mobile != "" {
		sql += " AND mobile = ?"
		sqlParams = append(sqlParams, mobile)
	}
	if memberType != 0 {
		sql += " AND member_type = ?"
		sqlParams = append(sqlParams, memberType)
	}
	if isPay != -1 {
		sql += " AND is_pay = ?"
		sqlParams = append(sqlParams, isPay)
	}
	if vendorID != -1 {
		sql += " AND vendor_id = ?"
		sqlParams = append(sqlParams, vendorID)
	}
	err = GetRows(db, &userMembers, sql, sqlParams)
	return userMembers, err
}

func GetUserMemberWithoutDeleted(db *DaoDB, vendorID int) (userMembers []*model.UserMember, err error) {
	sql := `
		SELECT * 
		  FROM user_member
		WHERE 1 = 1
	`
	sqlParams := []interface{}{}
	if vendorID != -1 {
		sql += " AND vendor_id = ?"
		sqlParams = append(sqlParams, vendorID)
	}
	err = GetRows(db, &userMembers, sql, sqlParams)
	return userMembers, err
}
