package repository

import (
	"errors"
	"strings"

	"hyapp-admin-server/internal/model"

	"gorm.io/gorm"
)

func (s *Store) ListTeams(keyword string) ([]model.Team, error) {
	query := s.db.Model(&model.Team{}).
		Select("admin_teams.*, parent_team.name AS parent_name, COUNT(DISTINCT admin_users.id) AS user_count").
		Joins("LEFT JOIN admin_teams parent_team ON parent_team.id = admin_teams.parent_id").
		Joins("LEFT JOIN admin_teams child_team ON child_team.parent_id = admin_teams.id").
		Joins("LEFT JOIN admin_users ON admin_users.team_id = admin_teams.id OR admin_users.team_id = child_team.id")
	if keyword := strings.TrimSpace(keyword); keyword != "" {
		like := "%" + keyword + "%"
		query = query.Where("admin_teams.name LIKE ? OR CAST(admin_teams.id AS CHAR) LIKE ? OR admin_teams.description LIKE ? OR parent_team.name LIKE ?", like, like, like, like)
	}

	var teams []model.Team
	err := query.
		Group("admin_teams.id, admin_teams.parent_id, admin_teams.name, admin_teams.description, admin_teams.sort, admin_teams.created_at_ms, admin_teams.updated_at_ms, parent_team.name").
		Order("CASE WHEN admin_teams.parent_id IS NULL THEN admin_teams.sort ELSE COALESCE(parent_team.sort, admin_teams.sort) END DESC").
		Order("COALESCE(admin_teams.parent_id, admin_teams.id) ASC").
		Order("CASE WHEN admin_teams.parent_id IS NULL THEN 0 ELSE 1 END ASC").
		Order("admin_teams.sort DESC, admin_teams.id ASC").
		Scan(&teams).Error
	return teams, err
}

func (s *Store) GetTeam(id uint) (*model.Team, error) {
	var team model.Team
	if err := s.db.First(&team, id).Error; err != nil {
		return nil, err
	}
	return &team, nil
}

func (s *Store) FindTeamByName(name string) (*model.Team, error) {
	var team model.Team
	if err := s.db.Where("name = ?", strings.TrimSpace(name)).First(&team).Error; err != nil {
		return nil, err
	}
	return &team, nil
}

func (s *Store) CreateTeam(team *model.Team) error {
	if err := normalizeTeam(team); err != nil {
		return err
	}
	if err := s.validateTeamParent(s.db, 0, team.ParentID); err != nil {
		return err
	}
	return s.db.Create(team).Error
}

func (s *Store) UpdateTeam(id uint, updates model.Team) (*model.Team, error) {
	if id == 0 {
		return nil, errors.New("team id is required")
	}
	if err := normalizeTeam(&updates); err != nil {
		return nil, err
	}

	err := s.db.Transaction(func(tx *gorm.DB) error {
		var team model.Team
		if err := tx.First(&team, id).Error; err != nil {
			return err
		}
		if err := s.validateTeamParent(tx, id, updates.ParentID); err != nil {
			return err
		}
		if err := tx.Model(&team).Updates(map[string]any{
			"parent_id":   updates.ParentID,
			"name":        updates.Name,
			"description": updates.Description,
			"sort":        updates.Sort,
		}).Error; err != nil {
			return err
		}
		// admin_users.team 是旧版字符串字段，仍被历史数据权限和导出兜底读取；团队重命名时同步维护，避免新旧字段长期分叉。
		return tx.Model(&model.User{}).Where("team_id = ?", id).Update("team", updates.Name).Error
	})
	if err != nil {
		return nil, err
	}
	return s.GetTeam(id)
}

func (s *Store) TeamAndChildIDs(id uint) ([]uint, error) {
	if id == 0 {
		return nil, errors.New("team id is required")
	}
	ids := []uint{id}
	var childIDs []uint
	if err := s.db.Model(&model.Team{}).Where("parent_id = ?", id).Order("sort DESC, id ASC").Pluck("id", &childIDs).Error; err != nil {
		return nil, err
	}
	ids = append(ids, childIDs...)
	return ids, nil
}

func (s *Store) NormalizeUserTeam(teamID *uint, legacyName string) (*uint, string, error) {
	name := strings.TrimSpace(legacyName)
	if teamID != nil {
		if *teamID == 0 {
			return nil, "", nil
		}
		team, err := s.GetTeam(*teamID)
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, "", errors.New("团队不存在")
		}
		if err != nil {
			return nil, "", err
		}
		id := team.ID
		return &id, team.Name, nil
	}
	if name == "" {
		return nil, "", nil
	}
	team, err := s.FindTeamByName(name)
	if err == nil {
		id := team.ID
		return &id, team.Name, nil
	}
	if errors.Is(err, gorm.ErrRecordNotFound) {
		// 老客户端可能仍提交自由文本团队；无法匹配到团队表时保留文本，不阻断兼容请求。
		return nil, name, nil
	}
	return nil, "", err
}

func normalizeTeam(team *model.Team) error {
	team.Name = strings.TrimSpace(team.Name)
	team.Description = strings.TrimSpace(team.Description)
	if team.ParentID != nil && *team.ParentID == 0 {
		team.ParentID = nil
	}
	if team.Name == "" {
		return errors.New("团队名称不能为空")
	}
	return nil
}

func (s *Store) validateTeamParent(tx *gorm.DB, currentID uint, parentID *uint) error {
	if parentID == nil {
		return nil
	}
	if currentID > 0 && *parentID == currentID {
		return errors.New("子部门不能挂到自己下面")
	}

	var parent model.Team
	if err := tx.First(&parent, *parentID).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return errors.New("父级团队不存在")
		}
		return err
	}
	if parent.ParentID != nil {
		return errors.New("暂不支持三级团队")
	}
	if currentID > 0 {
		var childCount int64
		if err := tx.Model(&model.Team{}).Where("parent_id = ?", currentID).Count(&childCount).Error; err != nil {
			return err
		}
		// 已有子部门的团队如果再被设为子部门，会形成三级结构；这里提前阻断，保证团队树始终只有团队和子部门两层。
		if childCount > 0 {
			return errors.New("已有子部门的团队不能设为子部门")
		}
	}
	return nil
}
