package db

import (
	"fmt"
	"net"
	"os"
	"strings"
	"sync"
)

/*
   // 获取数据库实例
   database, err := db.GetInstance()
   if err != nil {
       log.Fatal(err)
   }
   defer database.Close()

   // 创建Helper
   helper, _ := db.NewDBHelper()

   // 执行查询
   helper.Execute("SELECT * FROM nodes WHERE rack = ?", 1)

   // 获取一行
   row, _ := helper.FetchOne()
   if row != nil {
       log.Infof("节点: %v", row["name"])
   }

   // 获取所有行
   rows, _ := helper.FetchAll()
   log.Infof("共 %d 个节点", len(rows))

   // 使用Helper方法
   hostname, _ := helper.GetHostname("192.168.1.1")
   log.Infof("解析主机名: %s", hostname)

   // 设置属性
   helper.SetCategoryAttr("global", "global", "Kickstart_PrivateHostname", "sunhpc-master")

   // 获取属性
   val := helper.GetCategoryAttr("global", "global", "Kickstart_PrivateHostname")
   log.Infof("前端主机名: %s", val)
*/

const (
	attrPostfix = "_old"
)

// DBHelper DatabaseHelper类 - 继承DB，扩展业务方法
type DBHelper struct {
	*DB
	appliancesList []string
	frontendName   string
	cacheAttrs     sync.Map
}

func NewDBHelper() (*DBHelper, error) {
	db, err := GetInstance()
	if err != nil {
		return nil, err
	}
	return &DBHelper{
		DB:             db,
		appliancesList: nil,
		frontendName:   "",
	}, nil
}

// ==================== 节点查询 ====================

// GetListHostnames 获取所有主机名列表
func (h *DBHelper) GetListHostnames() ([]string, error) {
	_, err := h.Execute("SELECT name FROM nodes ORDER BY name")
	if err != nil {
		return nil, err
	}

	rows, err := h.FetchAll()
	if err != nil {
		return nil, err
	}

	var names []string
	for _, row := range rows {
		if name, ok := row["name"]; ok {
			names = append(names, name.(string))
		}
	}
	return names, nil
}

// GetNodesFromNames 从名称列表获取节点
func (h *DBHelper) GetNodesFromNames(names []string, managedOnly bool) ([]map[string]interface{}, error) {
	// 如果没有提供名称，返回所有节点
	if len(names) == 0 {
		query := "SELECT * FROM nodes"
		if managedOnly {
			query = `
                SELECT n.* FROM nodes n
                JOIN node_attrs a ON n.id = a.node_id
                WHERE a.attr = 'managed' AND a.value = 'true'
            `
		}

		_, err := h.Execute(query)
		if err != nil {
			return nil, err
		}
		return h.FetchAll()
	}

	// 构建查询条件
	conditions := []string{}
	args := []interface{}{}

	for _, name := range names {
		if strings.HasPrefix(name, "select ") {
			conditions = append(conditions, fmt.Sprintf("name IN (%s)", name[7:]))

		} else if strings.Contains(name, "%") {
			conditions = append(conditions, "name LIKE ?")
			args = append(args, name)

		} else if strings.HasPrefix(name, "rack") {
			rackNum := strings.TrimPrefix(name, "rack")
			conditions = append(conditions, "rack = ?")
			args = append(args, rackNum)

		} else if h.IsApplianceName(name) {
			conditions = append(conditions, `id IN (
                SELECT node_id FROM node_attrs 
                WHERE attr = 'appliance' AND value = ?
            )`)
			args = append(args, name)

		} else {
			hostname, err := h.GetHostname(name)
			if err == nil {
				conditions = append(conditions, "name = ?")
				args = append(args, hostname)
			}
		}
	}

	if len(conditions) == 0 {
		return []map[string]interface{}{}, nil
	}

	query := "SELECT * FROM nodes WHERE " + strings.Join(conditions, " OR ")
	_, err := h.Execute(query, args...)
	if err != nil {
		return nil, err
	}

	nodes, err := h.FetchAll()
	if err != nil {
		return nil, err
	}

	// 过滤受管节点
	if managedOnly {
		var managed []map[string]interface{}
		for _, node := range nodes {
			val := h.GetHostAttr(node["name"].(string), "managed")
			if val == "true" {
				managed = append(managed, node)
			}
		}
		return managed, nil
	}

	return nodes, nil
}

// ==================== 设备类型 ====================

// GetAppliancesListText 获取所有设备类型名称
func (h *DBHelper) GetAppliancesListText() []string {
	if h.appliancesList != nil {
		return h.appliancesList
	}

	_, err := h.Execute("SELECT DISTINCT value FROM node_attrs WHERE attr = 'appliance'")
	if err != nil {
		return []string{}
	}

	rows, _ := h.FetchAll()
	var apps []string
	for _, row := range rows {
		if val, ok := row["value"]; ok {
			apps = append(apps, val.(string))
		}
	}

	h.appliancesList = apps
	return apps
}

// IsApplianceName 检查是否为设备类型名称
func (h *DBHelper) IsApplianceName(name string) bool {
	for _, app := range h.GetAppliancesListText() {
		if app == name {
			return true
		}
	}
	return false
}

// ==================== 主机名解析 ====================

// GetHostname 规范化主机名 - 完全参考Rocks实现
func (h *DBHelper) GetHostname(hostname string) (string, error) {
	// 如果hostname为空，使用系统主机名
	if hostname == "" {
		hostname, _ = os.Hostname()
		hostname = strings.Split(hostname, ".")[0]
		return h.GetHostname(hostname)
	}

	// 1. 直接在nodes表中查找
	_, err := h.Execute("SELECT * FROM nodes WHERE name = ?", hostname)
	if err == nil {
		row, _ := h.FetchOne()
		if row != nil {
			return hostname, nil
		}
	}

	// 2. 尝试IP地址反向解析
	addr := net.ParseIP(hostname)
	if addr != nil {
		names, err := net.LookupAddr(hostname)
		if err == nil && len(names) > 0 {
			return h.GetHostname(strings.Split(names[0], ".")[0])
		}
	}

	// 3. 在networks表中查找IP
	if addr != nil {
		_, err := h.Execute(`
            SELECT n.name FROM nodes n
            JOIN networks net ON n.id = net.node_id
            WHERE net.ip = ?
        `, addr.String())
		if err == nil {
			row, _ := h.FetchOne()
			if row != nil {
				return row["name"].(string), nil
			}
		}
	}

	// 4. 尝试MAC地址
	mac := strings.ReplaceAll(hostname, "-", ":")
	_, err = h.Execute(`
        SELECT n.name FROM nodes n
        JOIN networks net ON n.id = net.node_id
        WHERE net.mac = ?
    `, mac)
	if err == nil {
		row, _ := h.FetchOne()
		if row != nil {
			return row["name"].(string), nil
		}
	}

	// 5. 检查别名
	_, err = h.Execute(`
        SELECT n.name FROM nodes n
        JOIN aliases a ON n.id = a.node_id
        WHERE a.name = ?
    `, hostname)
	if err == nil {
		row, _ := h.FetchOne()
		if row != nil {
			return row["name"].(string), nil
		}
	}

	// 6. 尝试FQDN
	if strings.Contains(hostname, ".") {
		parts := strings.Split(hostname, ".")
		name := parts[0]
		domain := strings.Join(parts[1:], ".")

		_, err := h.Execute(`
            SELECT n.name FROM nodes n
            JOIN networks net ON n.id = net.node_id
            JOIN subnets s ON net.subnet_id = s.id
            WHERE s.dns_zone = ? AND (net.name = ? OR n.name = ?)
        `, domain, name, name)
		if err == nil {
			row, _ := h.FetchOne()
			if row != nil {
				return row["name"].(string), nil
			}
		}
	}

	// 7. 如果以上都失败，抛出异常
	return "", fmt.Errorf("无法解析主机名: %s", hostname)
}

// CheckHostnameValidity 检查主机名有效性
func (h *DBHelper) CheckHostnameValidity(hostname string) error {
	// 不能包含点
	if strings.Contains(hostname, ".") {
		return fmt.Errorf("主机名 %s 不能包含点号", hostname)
	}

	// 不能是rack<数字>格式
	if strings.HasPrefix(hostname, "rack") {
		num := strings.TrimPrefix(hostname, "rack")
		if _, err := fmt.Sscanf(num, "%d", new(int)); err == nil {
			return fmt.Errorf("主机名 %s 不能是rack<数字>格式", hostname)
		}
	}

	// 不能是设备类型名称
	if h.IsApplianceName(hostname) {
		return fmt.Errorf("主机名 %s 不能与设备类型名称相同", hostname)
	}

	// 检查是否已存在
	_, err := h.GetHostname(hostname)
	if err == nil {
		return fmt.Errorf("节点 %s 已存在", hostname)
	}

	return nil
}

// ==================== 前端节点 ====================

// GetFrontendName 获取前端节点名称
func (h *DBHelper) GetFrontendName() string {
	if h.frontendName != "" {
		return h.frontendName
	}

	name := h.GetCategoryAttr("global", "global", "Kickstart_PrivateHostname")
	if name != "" {
		h.frontendName = name
	}
	return h.frontendName
}

// ==================== 属性管理 ====================

// GetCategoryIndex 获取类别索引
func (h *DBHelper) GetCategoryIndex(categoryName, categoryIndex string) (map[string]interface{}, map[string]interface{}, error) {
	// 查询类别和索引
	_, err := h.Execute(`
        SELECT c.id as cid, c.name as cname, i.id as iid, i.name as iname
        FROM categories c
        JOIN catindexes i ON c.id = i.category_id
        WHERE c.name = ? AND i.name = ?
    `, categoryName, categoryIndex)

	if err == nil {
		row, _ := h.FetchOne()
		if row != nil {
			category := map[string]interface{}{
				"id":   row["cid"],
				"name": row["cname"],
			}
			catindex := map[string]interface{}{
				"id":          row["iid"],
				"name":        row["iname"],
				"category_id": row["cid"],
			}
			return category, catindex, nil
		}
	}

	// 不存在则创建
	// 创建类别
	_, err = h.Execute("INSERT INTO categories (name) VALUES (?)", categoryName)
	if err != nil {
		return nil, nil, err
	}

	var catID int64
	h.Execute("SELECT last_insert_rowid()")
	row, _ := h.FetchOne()
	if row != nil {
		catID = row["last_insert_rowid()"].(int64)
	}

	// 创建索引
	_, err = h.Execute(
		"INSERT INTO catindexes (name, category_id) VALUES (?, ?)",
		categoryIndex, catID,
	)
	if err != nil {
		return nil, nil, err
	}

	h.Execute("SELECT last_insert_rowid()")
	row, _ = h.FetchOne()
	var idxID int64
	if row != nil {
		idxID = row["last_insert_rowid()"].(int64)
	}

	category := map[string]interface{}{
		"id":   catID,
		"name": categoryName,
	}
	catindex := map[string]interface{}{
		"id":          idxID,
		"name":        categoryIndex,
		"category_id": catID,
	}

	return category, catindex, nil
}

// SetCategoryAttr 设置类别属性
func (h *DBHelper) SetCategoryAttr(categoryName, catindexName, attr, value string) error {
	cat, catindex, err := h.GetCategoryIndex(categoryName, catindexName)
	if err != nil {
		return err
	}

	// 查询现有属性
	_, err = h.Execute(`
        SELECT id, value FROM attributes
        WHERE attr = ? AND category_id = ? AND catindex_id = ?
    `, attr, cat["id"], catindex["id"])

	if err == nil {
		row, _ := h.FetchOne()
		if row != nil {
			// 更新现有属性
			oldValue := row["value"]
			attrID := row["id"]

			_, err = h.Execute(
				"UPDATE attributes SET value = ? WHERE id = ?",
				value, attrID,
			)
			if err != nil {
				return err
			}

			// 保存旧值
			if !strings.HasSuffix(attr, attrPostfix) {
				h.SetCategoryAttr(categoryName, catindexName, attr+attrPostfix, oldValue.(string))
			}
			return nil
		}
	}

	// 创建新属性
	_, err = h.Execute(`
        INSERT INTO attributes (attr, value, category_id, catindex_id)
        VALUES (?, ?, ?, ?)
    `, attr, value, cat["id"], catindex["id"])

	return err
}

// GetCategoryAttr 获取类别属性
func (h *DBHelper) GetCategoryAttr(categoryName, catindexName, attrName string) string {
	cat, catindex, err := h.GetCategoryIndex(categoryName, catindexName)
	if err != nil {
		return ""
	}

	_, err = h.Execute(`
        SELECT value FROM attributes
        WHERE attr = ? AND category_id = ? AND catindex_id = ?
    `, attrName, cat["id"], catindex["id"])

	if err != nil {
		return ""
	}

	row, _ := h.FetchOne()
	if row == nil {
		return ""
	}

	return row["value"].(string)
}

// RemoveCategoryAttr 移除类别属性
func (h *DBHelper) RemoveCategoryAttr(categoryName, catindexName, attrName string) error {
	cat, catindex, err := h.GetCategoryIndex(categoryName, catindexName)
	if err != nil {
		return err
	}

	_, err = h.Execute(`
        DELETE FROM attributes
        WHERE attr = ? AND category_id = ? AND catindex_id = ?
    `, attrName, cat["id"], catindex["id"])

	if err != nil {
		return err
	}

	// 同时删除对应的_old属性
	_, _ = h.Execute(`
        DELETE FROM attributes
        WHERE attr = ? AND category_id = ? AND catindex_id = ?
    `, attrName+attrPostfix, cat["id"], catindex["id"])

	return nil
}

// ==================== 主机属性 ====================

// GetHostAttr 获取主机属性
func (h *DBHelper) GetHostAttr(hostname, attr string) string {
	// 先从节点直接属性查询
	_, err := h.Execute(`
        SELECT value FROM node_attrs
        WHERE node_id = (SELECT id FROM nodes WHERE name = ?)
        AND attr = ?
    `, hostname, attr)

	if err == nil {
		row, _ := h.FetchOne()
		if row != nil {
			return row["value"].(string)
		}
	}

	// 使用Rocks的属性解析链查询
	query := `
        SELECT a.value FROM attributes a
        JOIN resolvechain r ON a.category_id = r.category_id
        JOIN hostselections h ON a.category_id = h.category_id 
            AND a.catindex_id = h.selection
        WHERE h.host_id = (SELECT id FROM nodes WHERE name = ?)
        AND a.attr = ?
        ORDER BY r.precedence DESC
        LIMIT 1
    `

	_, err = h.Execute(query, hostname, attr)
	if err != nil {
		return ""
	}

	row, _ := h.FetchOne()
	if row == nil {
		return ""
	}

	return row["value"].(string)
}

// GetHostAttrs 获取主机所有属性
func (h *DBHelper) GetHostAttrs(hostname string, showSource bool) map[string]interface{} {
	attrs := make(map[string]interface{})

	// 获取节点基本信息
	_, err := h.Execute(`
        SELECT n.id, n.name, n.rack, n.rank, m.name as membership, a.name as appliance
        FROM nodes n
        LEFT JOIN memberships m ON n.membership_id = m.id
        LEFT JOIN appliances a ON m.appliance_id = a.id
        WHERE n.name = ?
    `, hostname)

	if err == nil {
		row, _ := h.FetchOne()
		if row != nil {
			if showSource {
				attrs["hostname"] = []interface{}{row["name"], "I"}
				attrs["rack"] = []interface{}{row["rack"], "I"}
				attrs["rank"] = []interface{}{row["rank"], "I"}
				attrs["appliance"] = []interface{}{row["appliance"], "I"}
				attrs["membership"] = []interface{}{row["membership"], "I"}
			} else {
				attrs["hostname"] = row["name"]
				attrs["rack"] = row["rack"]
				attrs["rank"] = row["rank"]
				attrs["appliance"] = row["appliance"]
				attrs["membership"] = row["membership"]
			}
		}
	}

	// 获取所有属性
	query := `
        SELECT a.attr, a.value, 
               CASE 
                   WHEN h.host_id IS NOT NULL THEN 'H'
                   ELSE UPPER(SUBSTR(c.name, 1, 1))
               END as source
        FROM attributes a
        JOIN categories c ON a.category_id = c.id
        LEFT JOIN hostselections h ON a.category_id = h.category_id 
            AND a.catindex_id = h.selection
            AND h.host_id = (SELECT id FROM nodes WHERE name = ?)
        UNION
        SELECT attr, value, 'N' as source
        FROM node_attrs
        WHERE node_id = (SELECT id FROM nodes WHERE name = ?)
    `

	_, err = h.Execute(query, hostname, hostname)
	if err == nil {
		rows, _ := h.FetchAll()
		for _, row := range rows {
			attr := row["attr"].(string)
			value := row["value"]
			if showSource {
				attrs[attr] = []interface{}{value, row["source"]}
			} else {
				attrs[attr] = value
			}
		}
	}

	return attrs
}
