package models

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

//应用实体
type Application struct {
	AppId          int64   `xorm:"app_id pk autoincr" json:"app_id"`              // 应用ID
	AppName        string  `xorm:"app_name unique" json:"app_name"`               // 应用名称
	Description    string  `xorm:"description" json:"description"`                // 应用简介
	ConfigData     string  `xorm:"'config_data' json" json:"config_data"`         // 配置数据，以JSON格式存储
	CreatorId      int64   `xorm:"creator_id" json:"creator_id"`                  // 创建者ID
	ParticipatorId []int64 `xorm:"'participator_id' json" json:"participator_id"` // 参与者ID，存储为JSON数组
	CreatedAt      int64   `xorm:"created"`                                       // 创建时间
	UpdatedAt      int64   `xorm:"updated"`                                       // 更新时间
}

// AppIDName 结构体用于存储查询到的应用ID和应用名
type AppIDName struct {
	AppId   int64  `json:"app_id"`
	AppName string `json:"app_name"`
}

// GetAppIDNames 是一个封装的函数，用于从数据库检索所有应用的ID和名称
func GetAppIDNames() ([]AppIDName, error) {
	var apps []AppIDName
	if err := datasource.Engine.Table("application").Cols("app_id", "app_name").Find(&apps); err != nil {
		return nil, fmt.Errorf("failed to query application ID and names: %w", err)
	}
	return apps, nil
}

/*
  Application 结构体的增删改查函数
*/
//添加应用

func AddApplication(app *Application) error {
	var existingApp Application
	// 根据应用ID和应用名称查询是否已存在该应用
	has, err := datasource.Engine.Where("app_name = ?", app.AppName).Get(&existingApp)
	if err != nil {
		return err
	}
	if has {
		// 如果存在，返回错误信息
		fmt.Printf("应用已存在，应用ID：%d，应用名称：%s", existingApp.AppId, existingApp.AppName)
		return fmt.Errorf("应用已存在，应用ID：%d，应用名称：%s", existingApp.AppId, existingApp.AppName)
	}
	// 如果不存在，进行创建操作
	_, err = datasource.Engine.Insert(app)
	if err != nil {
		return err
	}
	return nil
}

//根据应用id查询应用
func GetApplication(id int64) (*Application, error) {
	app := Application{AppId: id}
	_, err := datasource.Engine.Get(&app)
	if err != nil {
		fmt.Println(config.ColorRed, "根据应用id获取应用信息失败!", config.ColorReset)
		return nil, err
	}
	return &app, err
}

//更新应用
func UpdateApplication(app *Application) error {
	_, err := datasource.Engine.Id(app.AppId).Update(app)
	if err != nil {
		fmt.Println(config.ColorRed, "更新应用信息失败!", config.ColorReset)
		return err
	}
	return nil
}

//删除应用信息
func DeleteApplication(id int64) error {
	_, err := datasource.Engine.Id(id).Delete(&Application{})
	if err != nil {
		fmt.Println(config.ColorRed, "删除应用信息失败!", config.ColorReset)
		return err
	}
	return nil
}

// GetApplicationsByParticipatorId 使用JSON_CONTAINS函数从Application表中检索参与者ID。
func GetApplicationsByParticipatorId(participatorId int64) ([]Application, error) {
	var apps []Application
	participatorIdStr := strconv.FormatInt(participatorId, 10) // 将参与者ID转换为字符串
	// 构造一个JSON数组字符串，包含我们要查找的参与者ID
	jsonQuery := fmt.Sprintf("[%s]", participatorIdStr)

	// 使用JSON_CONTAINS函数构建查询条件
	// 注意：确保你的数据库列名和结构体字段名对应正确
	err := datasource.Engine.Where("JSON_CONTAINS(participator_id, ?)", jsonQuery).Find(&apps)
	if err != nil {
		return nil, fmt.Errorf("error querying applications: %v", err)
	}
	return apps, nil
}

// AddApplicationParticipant 根据手机号添加应用参与者
func AddApplicationParticipant(appID int64, phone string) error {
	// 根据手机号查询对应用户
	var user User
	if _, err := datasource.Engine.Where("phone = ?", phone).Get(&user); err != nil {
		return fmt.Errorf("查询用户失败: %v", err)
	}

	//根据应用id获取应用
	var app Application
	if _, err := datasource.Engine.ID(appID).Get(&app); err != nil {
		return fmt.Errorf("查询应用失败: %v", err)
	}

	//检查应用的参与者是否包括该用户
	for _, id := range app.ParticipatorId {
		if id == user.Id {
			return fmt.Errorf("用户已经是应用的参与者了")
		}
	}

	// 添加用户的ID到应用的参与者数组中
	app.ParticipatorId = append(app.ParticipatorId, user.Id)

	// 更新数据库中的应用信息
	if _, err := datasource.Engine.ID(appID).Cols("participator_id").Update(&app); err != nil {
		return fmt.Errorf("更新应用信息的参与者失败: %v", err)
	}
	return nil
}

// 根据应用ID查询参与者
func GetParticipantsByAppID(appID int64) ([]User, error) {
	var app Application
	var users []User

	has, err := datasource.Engine.ID(appID).Get(&app)
	if err != nil {
		return nil, fmt.Errorf("获取应用出错: %v", err)
	}
	if !has {
		return nil, fmt.Errorf("未发现该应用")
	}

	err = datasource.Engine.In("id", app.ParticipatorId).Find(&users)
	if err != nil {
		return nil, fmt.Errorf("查询用户出错: %v", err)
	}

	return users, nil
}

//根据应用名称模糊匹配
/*
  根据应用名称模糊匹配查询应用
  如果当前的用户的等级不为0，只能查询到应用名字模糊匹配到的，且用户id等于应用创作者id的。
*/
func QueryApplicationLikeAppName(userID int64, keyword string) ([]*Application, error) {
	apps := make([]*Application, 0)

	// 联表查询，连接用户表和数字人表，根据权限和关键词进行过滤
	err := datasource.Engine.Table("application").Alias("app").
		Join("INNER", "user", "user.id = ?", userID).
		Where("(user.level < 3 OR app.creator_id = ? ) AND app.app_name LIKE ?",
			userID, "%"+keyword+"%").
		Find(&apps)
	if err != nil {
		return nil, err
	}
	fmt.Println(config.ColorYellow, "digitalPersons 模糊查询获取应用个数：", len(apps), config.ColorReset)
	for _, app := range apps {
		fmt.Printf("\033[32m AppID: %d,AppName: %s, CreatorID: %d, Description: %s,ConfigData: %s \033[0m\n", app.AppId, app.AppName, app.CreatorId, app.Description, app.ConfigData)
	}

	return apps, nil
}

//根据应用id和应用名称获取应用的配置信息
// GetConfigDataByAppInfo fetches the config_data for a given app_id and app_name.
func GetConfigDataByAppInfo(appID int64, appName string) (map[string]interface{}, error) {
	var app Application

	// Perform the query to find the application.
	has, err := datasource.Engine.Where("app_id = ? AND app_name = ?", appID, appName).Get(&app)
	if err != nil {
		return nil, fmt.Errorf("error querying database: %w", err)
	}
	if !has {
		return nil, fmt.Errorf("application not found")
	}

	// Unmarshal the ConfigData JSON into a map.
	var configData map[string]interface{}
	err = json.Unmarshal([]byte(app.ConfigData), &configData)
	if err != nil {
		return nil, fmt.Errorf("error unmarshaling config data: %w", err)
	}

	return configData, nil
}

//添加用户到应用参与者
func AddParticipants(session *xorm.Session, appIDs []int64, userIDs ...int64) error {
	for _, appID := range appIDs {
		// 根据应用ID查询应用实例
		app := &Application{}
		has, err := session.ID(appID).Get(app)
		if err != nil {
			return err
		}
		if !has {
			return fmt.Errorf("application with ID %d not found", appID)
		}

		// 将用户ID追加到参与者列表中
		app.ParticipatorId = append(app.ParticipatorId, userIDs...)

		// 使用xorm更新应用记录
		_, err = session.Id(app.AppId).Cols("participator_id").Update(app)
		if err != nil {
			return err
		}
	}

	return nil
}
