package models

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

/*
ID 世界名称 简介 角色 背景 标签 世界基数 粉丝量 话题数 平行世界量 交互量 创建时间
*/

type WorldInfo struct {
	ID             int64    `xorm:"'id' pk autoincr" json:"id"`
	Name           string   `xorm:"'name' unique" json:"name"`
	Description    string   `xorm:"'description'" json:"description"`
	Role           string   `xorm:"'role'" json:"role"`
	Background     string   `xorm:"'background'" json:"background"`
	Tags           []string `xorm:"'tags' json" json:"tags"`
	Creator        int64    `xorm:"'creator'" json:"creator" `
	BaseNumber     int      `xorm:"'base_number'" json:"baseNumber"`
	Fans           int      `xorm:"'fans'" json:"fans"`
	TopicCount     int      `xorm:"'topic_count'" json:"topicCount"`
	ParallelWorlds int      `xorm:"'parallel_worlds'" json:"parallelWorlds"`
	Interaction    int      `xorm:"'interaction'" json:"interaction"`
	ShowHome       string   `xorm:"show_home" json:"ShowHome"`                     //首页展示 onTitle bool
	WorldHeader    string   `xorm:"world_header" json:"worldHeader"`               //世界标头 varchar
	WorldParameter string   `xorm:" 'world_parameter' json" json:"worldParameter"` //	显化参量 JSON
	CreatedAt      int64    `xorm:"'created_at' created" json:"createdAt"`
	ConfigData     string   `xorm:" 'config_data' json" json:"configData"` //保存考核定制面板的参数数据json
}

//世界信息增删改查
// AddWorldInfo adds new world information to the datasource and returns the newly added world ID upon success
func AddWorldInfo(session *xorm.Session, worldInfo *WorldInfo) (int64, error) {
	_, err := session.Insert(worldInfo)
	if err != nil {
		return 0, err // Return 0 if there's an error since ID cannot be negative
	}
	return worldInfo.ID, nil // Return the new world's ID

}

//根据世界id查询世界信息
func GetWorld(session *xorm.Session, id int64) (*WorldInfo, error) {
	world := &WorldInfo{}
	_, err := session.ID(id).Get(world)
	return world, err
}

// GetWorldInfoByName 根据世界名称查询世界对象
func GetWorldInfoByName(worldName string) (*WorldInfo, error) {
	var worldInfo WorldInfo
	has, err := datasource.Engine.Where("name = ?", worldName).Get(&worldInfo)
	if err != nil {
		return nil, err
	}
	if !has {
		return nil, nil
	}
	return &worldInfo, nil
}

//根据世界名称查询世界信息
func GetWorldInfoByName_Tx(session *xorm.Session, worldName string) (*WorldInfo, bool, error) {
	var worldInfo WorldInfo
	has, err := session.Where("name = ?", worldName).Get(&worldInfo)
	if err != nil {
		return nil, false, err
	}
	if !has {
		return nil, false, nil
	}
	return &worldInfo, true, nil
}

//根据世界Id查询世界信息
func GetWorldInfoById_Tx(session *xorm.Session, id int64) (*WorldInfo, bool, error) {
	var worldInfo WorldInfo
	has, err := session.Where("id = ?", id).Get(&worldInfo)
	if err != nil {
		return nil, false, err
	}
	if !has {
		return nil, false, nil
	}
	return &worldInfo, true, nil
}
func GetWorldInfoById(id int64) (*WorldInfo, bool, error) {
	var worldInfo WorldInfo
	has, err := datasource.Engine.Where("id = ?", id).Get(&worldInfo)
	if err != nil {
		return nil, false, err
	}
	if !has {
		return nil, false, nil
	}
	return &worldInfo, true, nil
}

func UpdateWorld(session *xorm.Session, w *WorldInfo) error {
	affected, err := session.ID(w.ID).Update(w)
	return err
	if affected == 0 {
		return errors.New("修改世界信息出错")
	}
	return nil
}

func DeleteWorld(id int64) error {
	_, err := datasource.Engine.ID(id).Delete(&WorldInfo{})
	return err
}

// 查询所有世界信息
func ListWorlds() ([]*WorldInfo, error) {
	var worlds []*WorldInfo
	err := datasource.Engine.Find(&worlds)
	return worlds, err
}

// 根据世界名称模糊查询所有世界信息
func QueryWorldsByLikeName(name string) ([]WorldInfo, error) {
	var worlds []WorldInfo
	err := datasource.Engine.Where("name like ?", "%"+name+"%").Find(&worlds)
	if err != nil {
		return nil, err
	}
	return worlds, nil
}

// WorldInfoAndAsset 结构体用于联表查询的结果封装
type WorldInfoAndAsset struct {
	WorldInfo  `xorm:"extends"`
	WorldAsset `xorm:"extends"`
}

// GetWorldInfoAndAssetByID 根据世界ID获取世界信息和资产信息
func GetWorldInfoAndAssetByID_Tx(session *xorm.Session, worldId int64) (*WorldInfoAndAsset, error) {
	// 定义查询结果的结构体
	var worldInfoAndAsset WorldInfoAndAsset

	// 进行联表查询
	has, err := session.Table("world_info").
		Join("LEFT", "world_asset", "world_info.id = world_asset.world_id").
		Where("world_info.id = ?", worldId).Get(&worldInfoAndAsset)
	if err != nil {
		return nil, err
	}

	if !has {
		return nil, errors.New("没有找到对应的世界信息")
	}

	// 封装查询结果返回
	return &worldInfoAndAsset, nil
}

func GetWorldInfoAndAssetByID(worldId int64) (*WorldInfoAndAsset, error) {
	// 定义查询结果的结构体
	var worldInfoAndAsset WorldInfoAndAsset

	// 进行联表查询
	has, err := datasource.Engine.Table("world_info").
		Join("LEFT", "world_asset", "world_info.id = world_asset.world_id").
		Where("world_info.id = ?", worldId).Get(&worldInfoAndAsset)
	if err != nil {
		return nil, err
	}

	if !has {
		return nil, errors.New("没有找到对应的世界信息")
	}

	// 封装查询结果返回
	return &worldInfoAndAsset, nil
}

// QueryWorldsByLikeName 根据世界名称模糊查询所有世界信息和世界资产信息
func QueryWorldsByLikeName2(name string) ([]WorldInfoAndAsset, error) {
	var worldInfoAndAssets []WorldInfoAndAsset
	// 需要确保在 WorldInfo 和 WorldAsset 中 WorldID 是关联的键
	err := datasource.Engine.Table("world_info").Alias("wi").
		Join("INNER", []string{"world_asset", "wa"}, "wi.id = wa.world_id").
		Where("wi.name like ?", "%"+name+"%").
		Find(&worldInfoAndAssets)
	if err != nil {
		return nil, err
	}
	return worldInfoAndAssets, nil
}

//根据世界id获取世界配置信息
func GetWorldConfigDataByID(id int64) (string, error) {
	var world WorldInfo
	has, err := datasource.Engine.Where("id = ?", id).Get(&world)
	if err != nil {
		return "", err
	}
	if !has {
		return "", fmt.Errorf("no world found with ID %d", id)
	}

	configData := world.ConfigData
	return configData, nil
}

// FindWorldsByTagAndName
func FindWorldsByTagAndName(WorldName string, tag string) (*WorldInfo, string, error) {
	var world WorldInfo
	// 确保 tag 被引号包围，形成有效的 JSON 字符串
	tagJSON := fmt.Sprintf("[\"%s\"]", tag) // 将tag转换为JSON格式的字符串，并确保使用双引号
	has, err := datasource.Engine.Table("world_info").
		Where("name = ? ", WorldName).And("JSON_CONTAINS(tags, ?)", tagJSON).Get(&world)
	if err != nil {
		return nil, "", err // 数据库查询错误
	}
	if !has {
		return nil, "", nil // 未找到记录
	}
	return &world, world.ConfigData, nil
}

// 根据世界名称模糊查询和包含的世界标签查询世界信息
func FindWorldsByTagAndName2(WorldName string, tag string) ([]WorldInfo, string, error) {
	var world []WorldInfo

	// 构建查询条件
	query := datasource.Engine.Table("world_info")
	if WorldName != "" {
		query = query.Where("name LIKE ?", "%"+WorldName+"%")
	}
	if tag != "" {
		tagJSON := fmt.Sprintf("[\"%s\"]", tag) // 将 tag 转换为 JSON 格式的字符串，并确保使用双引号
		query = query.And("JSON_CONTAINS(tags, ?)", tagJSON)
	}

	// 执行查询
	err := query.Find(&world)
	if err != nil {
		return nil, "", err // 数据库查询错误
	}

	if len(world) == 0 {
		return nil, "", nil // 没有找到任何世界信息
	}

	return world, world[0].ConfigData, nil // 假设 ConfigData 存储在每个 WorldInfo 结构中，并假设至少有一个结果
}

func FindWorldsByTagAndName3(WorldName string, tags []string) ([]WorldInfo, string, error) {
	var world []WorldInfo

	// 构建查询条件
	query := datasource.Engine.Table("world_info")
	if WorldName != "" {
		query = query.Where("name LIKE ?", "%"+WorldName+"%")
	}
	if len(tags) > 0 {
		tagsJSON, err := json.Marshal(tags) // 将 tags 列表转换为 JSON 数组
		if err != nil {
			return nil, "", err // JSON 格式化错误
		}
		query = query.And("JSON_CONTAINS(tags, ?)", string(tagsJSON))
	}

	// 执行查询
	err := query.Find(&world)
	if err != nil {
		return nil, "", err // 数据库查询错误
	}

	if len(world) == 0 {
		return nil, "", nil // 没有找到任何世界信息
	}

	return world, world[0].ConfigData, nil // 假设 ConfigData 存储在每个 WorldInfo 结构中，并假设至少有一个结果
}

func FindWorlds(name string, tags []string) ([]WorldInfo, error) {
	var worlds []WorldInfo
	query := datasource.Engine.Table("world_info")
	if name != "" {
		query = query.Where("name = ?", name)
	}

	if len(tags) > 0 {
		for _, tag := range tags {
			tagJSON := fmt.Sprintf("\"%s\"", tag) // 使用双引号确保格式正确
			query = query.And("JSON_CONTAINS(tags, ?)", tagJSON)
		}
	}

	err := query.Find(&worlds)
	if err != nil {
		return nil, err
	}

	return worlds, nil
}

func FindWorlds2(name string, tags []string) ([]WorldInfo, error) {
	var worlds []WorldInfo
	query := datasource.Engine.Table("world_info")
	if name != "" {
		query = query.Where("name = ?", name)
	}

	if len(tags) > 0 {
		for _, tag := range tags {
			tagJSON := fmt.Sprintf("\"%s\"", tag) // 使用双引号确保格式正确
			// 确保只对有有效 JSON 的记录进行查询
			query = query.Where("JSON_VALID(tags) = 1").And("JSON_CONTAINS(tags, ?)", tagJSON)
		}
	}

	err := query.Find(&worlds)
	if err != nil {
		return nil, err
	}

	return worlds, nil
}
