package models

import (
	"WorldEpcho/src/datasource"
	"WorldEpcho/src/utils"
	"errors"
	"fmt"
	"github.com/go-xorm/xorm"
	"time"
)

type UserInvitationRelationship struct {
	ID         int64 `xorm:"id pk autoincr" json:"id"`
	InviterID  int64 `xorm:"inviter_id" json:"inviter_id"` // 邀请人ID
	InviteeID  int64 `xorm:"invitee_id" json:"invitee_id"` // 被邀请人ID
	CreateTime int64 `xorm:"createtime" json:"createtime"`
}

// 生成邀请码并更新用户表
func GenerateInviteCode(userID int64) (string, error) {
	// 生成新的邀请码
	inviteCode := utils.GenerateInviteCode(userID)
	// 更新用户的邀请码
	user := &User{Id: userID}
	user.InviteCode = inviteCode
	_, err := datasource.Engine.ID(user.Id).Cols("invite_code").Update(user)
	if err != nil {
		return "", errors.New("用户表保存邀请码失败!")
	}

	return inviteCode, nil
}

// QueryInviteCode 查询用户的邀请码
func QueryInviteCode(userID int64) (string, error) {
	user := &User{Id: userID}
	has, err := datasource.Engine.Get(user)
	if err != nil {
		return "", err
	}
	if !has {
		return "", fmt.Errorf("用户不存在")
	}
	return user.InviteCode, nil
}

// ResetInviteCode 重置用户的邀请码
func ResetInviteCode(userID int64) (string, error) {
	// 生成新的邀请码
	inviteCode := utils.GenerateInviteCode(userID)

	// 更新用户的邀请码
	user := &User{Id: userID}
	user.InviteCode = inviteCode

	_, err := datasource.Engine.Where("id = ?", user.Id).Cols("invite_code").Update(user)
	if err != nil {
		return "", err
	}
	return inviteCode, nil
}

// QueryInviterIDByInviteCode 查询邀请码对应的邀请人ID
func QueryInviterIDByInviteCode(session *xorm.Session, inviteCode string) (*User, error) {
	user := &User{}
	has, err := session.Where("invite_code = ?", inviteCode).Get(user)
	if err != nil {
		return nil, err
	}
	if !has {
		return nil, fmt.Errorf("邀请码对应的用户不存在")
	}
	return user, nil
}

// QueryDirectInviter 查询直接邀请人的函数
func GetDirectInviter(userID int64) (*User, error) {
	//user := new(User)

	var inviter User
	exist, err := datasource.Engine.Table("user").
		Join("INNER", "user_invitation_relationship", "user.id = user_invitation_relationship.inviter_id").
		Where("user_invitation_relationship.invitee_id = ?", userID).
		Get(&inviter)

	if err != nil {
		return nil, errors.New("获取直接邀请人出错")
	}
	if !exist {
		return nil, errors.New("不存在直接邀请人")
	}
	return &inviter, nil
}

// QueryIndirectInviters 查询间接邀请人 A --> B --> C

//查询间接邀请的人 A --> B --> C
//               A --> B --> D

// 递归查询被间接邀请的人
/*
 func GetIndirectInvitees(inviterID int64) ([]int64, error) {
	//var inviteeIds []int64
	inviteeIds := make([]int64, 0)
	var relationships []UserInvitationRelationship
	err := datasource.Engine.Where("inviter_id = ?", inviterID).Find(&relationships)
	if err != nil {
		return inviteeIds, err
	}

	for _, relationship := range relationships {
		inviteeID := relationship.InviteeID
		inviteeIds = append(inviteeIds, inviteeID) //第二层

		indirectInviteeIds, err := GetIndirectInvitees(inviteeID)
		if err != nil {
			continue // 忽略无间接邀请的人，继续遍历下一个邀请关系
		}
		inviteeIds = append(inviteeIds, indirectInviteeIds...)
	}

	return inviteeIds, nil
}*/

/*
  根据邀请人id查询用户信息
*/

func GetIndirectInvitees1(inviterID int64) ([]int64, error) {
	var inviteeIds []int64

	// 构造 SQL 查询
	query := `
			WITH RECURSIVE indirect_invites AS (
			  SELECT inviter_id, invitee_id
			  FROM user_invitation_relationship
			  WHERE inviter_id = ?   -- 用户A的ID
			  UNION ALL
			  SELECT ir.inviter_id, ir.invitee_id
			  FROM user_invitation_relationship  ir
			  INNER JOIN indirect_invites  ii  ON   ii.invitee_id = ir.inviter_id
			)
			SELECT DISTINCT invitee_id
			FROM indirect_invites
			WHERE invitee_id NOT IN (
			  SELECT invitee_id
			  FROM user_invitation_relationship
			  WHERE inviter_id = ?  -- 用户A的ID
			);
     `
	// 执行查询并获取结果
	err := datasource.Engine.SQL(query, inviterID, inviterID).Find(&inviteeIds)
	if err != nil {
		return nil, err
	}

	return inviteeIds, nil
}

// GetIndirectInvitees 通过存储过程获取间接邀请人

// Invitee 是一个用于存储存储过程返回结果的结构体
type Invitee struct {
	InviteeID int64 `xorm:"invitee_id"`
}

// GetIndirectInvitees 通过存储过程获取间接邀请人
func GetIndirectInvitees2(inviterID int64) ([]int64, error) {
	// 创建用于存储结果的切片
	var results []Invitee

	// 使用Session来执行存储过程
	session := datasource.Engine.NewSession()
	defer session.Close()

	// 调用存储过程并将结果保存到 results
	err := session.SQL("CALL GetIndirectInvites(?)", inviterID).Find(&results)
	if err != nil {
		// 注意这里不再是 log.Fatalf，因为我们需要返回错误而不是立即退出程序
		return nil, errors.New("调用查询间接邀请人的存储过程报错: " + err.Error())
	}

	// 如果结果数组为空，则返回一个空数组而不是错误
	if len(results) == 0 {
		return []int64{}, nil
	}

	// 将结果转换为 int64 数组
	var inviteeIds []int64
	for _, result := range results {
		inviteeIds = append(inviteeIds, result.InviteeID)
	}

	return inviteeIds, nil
}

//获取间接邀请人使用go程序执行mysql的一个存储过程
func GetIndirectInvitees(inviterID int64) ([]int64, error) {
	var inviteeIds []int64

	session := datasource.Engine.NewSession()
	defer session.Close()

	err := session.SQL("CALL GetIndirectInvites(?)", inviterID).Find(&inviteeIds)
	if err != nil {
		return nil, errors.New("调用查询间接邀请人的存储过程出错: " + err.Error())
	}

	return inviteeIds, nil
}

// 保存邀请人和被邀请人的信息到数据库
func SaveInvitationRelationship(session *xorm.Session, inviterID int64, inviteeId int64) error {
	relationship := &UserInvitationRelationship{
		InviterID:  inviterID,
		InviteeID:  inviteeId,
		CreateTime: time.Now().Unix(),
	}
	_, err := session.Insert(relationship)
	if err != nil {
		return fmt.Errorf("保存用户邀请关系数据失败!")
	}
	return nil
}

// 根据用户id，查询该用户所有直接邀请的人的id
//根据邀请人的ID查询所有被邀请人的ID
func GetInviteesByInviterID(inviterID int64) ([]int64, error) {
	var relationships []UserInvitationRelationship

	err := datasource.Engine.Table("user_invitation_relationship").
		Where("inviter_id = ?", inviterID).
		Find(&relationships)

	if err != nil {
		return nil, err
	}

	var invitees []int64
	for _, relationship := range relationships {
		invitees = append(invitees, relationship.InviteeID)
	}
	return invitees, nil
}

//根据被邀请人的id获取邀请人
func GetDirectInviter1(inviteeID int64) (*User, error) {
	relationship := &UserInvitationRelationship{}
	has, err := datasource.Engine.Where("invitee_id = ?", inviteeID).Get(relationship)
	if err != nil {
		return nil, err
	}
	if !has {
		return nil, nil
	}

	inviter := &User{}
	has, err = datasource.Engine.ID(relationship.InviterID).Get(inviter)
	if err != nil {
		return nil, err
	}
	if !has {
		return nil, nil
	}

	return inviter, nil
}
