package applogic

import (
	"fmt"
	"strings"

	"aijianzhan/platform/internal/agentstore"
	"aijianzhan/platform/internal/dbsync"
	"aijianzhan/platform/internal/schema"
	"aijianzhan/platform/internal/svc"
	"aijianzhan/platform/internal/types"
	"aijianzhan/platform/internal/userstore"
)

// fillAgentSyncOnToken Z12a：换票带回同步落点。
func fillAgentSyncOnToken(resp *types.TokenResp, acc *agentstore.Account) {
	if resp == nil || acc == nil {
		return
	}
	resp.ChannelID = strings.TrimSpace(acc.ChannelID)
	resp.OnlineDBID = strings.TrimSpace(acc.OnlineDBID)
	resp.DatabaseName = strings.TrimSpace(acc.DatabaseName)
	if resp.DatabaseName != "" && !schema.ValidDBName(resp.DatabaseName) {
		resp.DatabaseName = ""
	}
	resp.SyncBound = resp.ChannelID != "" && resp.OnlineDBID != ""
}

// fillUserSyncOnToken：人类登录优先从本人 Binding 带回落点。
func fillUserSyncOnToken(svcCtx *svc.ServiceContext, resp *types.TokenResp, u *userstore.User) {
	if resp == nil || u == nil || svcCtx == nil || svcCtx.DBSync == nil || u.TenantID <= 0 {
		return
	}
	list, err := svcCtx.DBSync.Store().ListBindingsFiltered(u.TenantID, u.UserID, "")
	if err != nil || len(list) == 0 {
		return
	}
	b := list[0]
	for i := range list {
		if list[i].ChannelID != "" && list[i].OnlineDBID != "" {
			b = list[i]
			break
		}
	}
	resp.ChannelID = strings.TrimSpace(b.ChannelID)
	resp.OnlineDBID = strings.TrimSpace(b.OnlineDBID)
	// Z35：database_name 仅物理库名；勿把中文 DisplayName 填进该字段
	resp.DatabaseName = strings.TrimSpace(b.DatabaseName)
	if resp.DatabaseName != "" && !schema.ValidDBName(resp.DatabaseName) {
		resp.DatabaseName = ""
	}
	resp.SyncBound = resp.ChannelID != "" && resp.OnlineDBID != ""
}

// ensureAgentSyncBind Z12c/Z12h：无通道或通道已删除时，创建/复用默认同步通道并写回智能体。
func (l *AgentAdminLogic) ensureAgentSyncBind(acc *agentstore.Account) (*agentstore.Account, error) {
	if acc == nil {
		return nil, fmt.Errorf("agent nil")
	}
	if l.svcCtx.DBSync == nil {
		return acc, nil
	}
	alive := channelAlive(l.svcCtx.DBSync.Store(), acc.TenantID, acc.ChannelID)
	if alive && strings.TrimSpace(acc.OnlineDBID) != "" {
		return acc, nil
	}
	if _, err := HealTenantSyncBind(l.ctx, l.svcCtx, acc.TenantID); err != nil {
		return nil, fmt.Errorf("heal sync bind: %w", err)
	}
	st, err := l.store()
	if err != nil {
		return nil, err
	}
	updated, err := st.Get(l.ctx, acc.TenantID, acc.AgentID)
	if err != nil {
		return nil, err
	}
	// 若 heal 未覆盖该智能体（例如无 Binding 仅 Agent），再显式挂一次
	if !channelAlive(l.svcCtx.DBSync.Store(), updated.TenantID, updated.ChannelID) || strings.TrimSpace(updated.OnlineDBID) == "" {
		cfg := l.svcCtx.Config.DBSync
		driver := dbsync.Driver(strings.TrimSpace(cfg.DefaultRemoteDriver))
		if driver == "" {
			driver = dbsync.DriverPostgres
		}
		ch, err := l.svcCtx.DBSync.EnsureAndStartSystemDefaultChannel(dbsync.DefaultChannelOpts{
			TenantID:     acc.TenantID,
			AgentID:      acc.AgentID,
			Name:         fmt.Sprintf("默认同步 · %s", acc.Name),
			RemoteDriver: driver,
			RemoteDSN:    strings.TrimSpace(cfg.DefaultRemoteDSN),
			DatabaseName: acc.DatabaseName,
		})
		if err != nil {
			return nil, fmt.Errorf("ensure default channel: %w", err)
		}
		online := strings.TrimSpace(updated.OnlineDBID)
		if online == "" {
			online = dbsync.ResolveOnlineDBID("", ch.ID)
		}
		dbName := schema.SafeSyncDatabaseName(updated.DatabaseName, updated.AgentID, 0)
		updated, err = st.AttachSyncBind(l.ctx, updated.AgentID, updated.TenantID, ch.ID, online, dbName, updated.Status == agentstore.StatusActive || updated.Status == "")
		if err != nil {
			return nil, err
		}
	}
	return updated, nil
}
