package service

import (
	"log"
	"os"
	"path/filepath"
	"strings"

	"x-agents/server/internal/model"
	"x-agents/server/internal/repository"

	"gopkg.in/yaml.v3"
)

type SkillService struct {
	skillRepo *repository.SkillRepository
}

func NewSkillService(skillRepo *repository.SkillRepository) *SkillService {
	return &SkillService{skillRepo: skillRepo}
}

func (s *SkillService) GetAllSkills() ([]model.Skill, error) {
	return s.skillRepo.FindAll()
}

func (s *SkillService) GetSkillByID(id string) (*model.Skill, error) {
	return s.skillRepo.FindByID(id)
}

func (s *SkillService) GetSkillsByType(skillType string) ([]model.Skill, error) {
	return s.skillRepo.FindByType(skillType)
}

func (s *SkillService) CreateSkill(skill *model.Skill) error {
	return s.skillRepo.Create(skill)
}

func (s *SkillService) UpdateSkill(skill *model.Skill) error {
	return s.skillRepo.Update(skill)
}

func (s *SkillService) DeleteSkill(id string) error {
	// 先获取 skill 信息，以便删除本地文件
	skill, err := s.skillRepo.FindByID(id)
	if err != nil {
		return err
	}

	// 删除数据库记录
	if err := s.skillRepo.Delete(id); err != nil {
		return err
	}

	// 删除本地文件（skill 目录）
	if skill.Path != "" {
		// 获取 skill 所在目录（SKILL.md 的父目录）
		skillDir := filepath.Dir(skill.Path)
		if err := os.RemoveAll(skillDir); err != nil {
			log.Printf("[SkillService] Warning: failed to delete skill directory %s: %v", skillDir, err)
			// 数据库记录已删除，不返回错误
		} else {
			log.Printf("[SkillService] Deleted skill directory: %s", skillDir)
		}
	}

	return nil
}

// InitSkills 初始化扫描所有 skills 目录
func (s *SkillService) InitSkills() error {
	// 获取项目根目录
	projectRoot := s.getProjectRoot()
	if projectRoot == "" {
		return nil
	}

	var totalCount int

	// 扫描 system skills: account/admin/skills
	systemSkillsPath := filepath.Join(projectRoot, "account", "admin", "skills")
	if _, err := os.Stat(systemSkillsPath); err == nil {
		systemSkills, err := s.scanSkillsDirectory(systemSkillsPath, "system")
		if err == nil && len(systemSkills) > 0 {
			s.skillRepo.DeleteByType("system")
			s.skillRepo.UpsertBatch(systemSkills)
			totalCount += len(systemSkills)
		}
	}

	// 扫描 user skills: account/{username}/skills (除了 admin)
	accountPath := filepath.Join(projectRoot, "account")
	entries, err := os.ReadDir(accountPath)
	if err == nil {
		for _, entry := range entries {
			if !entry.IsDir() || entry.Name() == "admin" {
				continue
			}
			userSkillsPath := filepath.Join(accountPath, entry.Name(), "skills")
			if _, err := os.Stat(userSkillsPath); err == nil {
				userSkills, err := s.scanSkillsDirectory(userSkillsPath, "user")
				if err == nil && len(userSkills) > 0 {
					s.skillRepo.UpsertBatch(userSkills)
					totalCount += len(userSkills)
				}
			}
		}
	}

	if totalCount > 0 {
		log.Printf("[SkillService] Loaded %d skills", totalCount)
	}
	return nil
}

// scanSkillsDirectory 扫描指定目录下的所有 skill
func (s *SkillService) scanSkillsDirectory(basePath string, skillType string) ([]model.Skill, error) {
	var skills []model.Skill

	entries, err := os.ReadDir(basePath)
	if err != nil {
		return nil, err
	}

	for _, entry := range entries {
		if !entry.IsDir() {
			continue
		}

		skillDir := filepath.Join(basePath, entry.Name())
		skillPath := filepath.Join(skillDir, "SKILL.md")

		// 尝试 skill.md（大小写不敏感）
		if _, err := os.Stat(skillPath); os.IsNotExist(err) {
			skillPath = filepath.Join(skillDir, "skill.md")
		}

		skillInfo, err := s.parseSkillFile(skillPath)
		if err != nil {
			log.Printf("[SkillService] Error parsing skill file %s: %v", skillPath, err)
			continue
		}

		// 如果没有从文件解析到名称，使用目录名
		if skillInfo.SkillName == "" {
			skillInfo.SkillName = entry.Name()
		}

		skill := model.Skill{
			SkillName: skillInfo.SkillName,
			SkillType: skillType,
			SkillDesc: skillInfo.SkillDesc,
			Path:      skillPath,
			Status:    "active",
		}

		skills = append(skills, skill)
	}

	return skills, nil
}

// parseSkillFile 解析 SKILL.md 文件，提取 YAML front matter
func (s *SkillService) parseSkillFile(skillPath string) (*model.Skill, error) {
	content, err := os.ReadFile(skillPath)
	if err != nil {
		return nil, err
	}

	// 检查是否有 YAML front matter
	contentStr := string(content)
	if !strings.HasPrefix(contentStr, "---") {
		// 没有 front matter，返回空
		return &model.Skill{}, nil
	}

	// 找到结束标记
	lines := strings.Split(contentStr, "\n")
	var endIdx int
	for i := 1; i < len(lines); i++ {
		if strings.TrimSpace(lines[i]) == "---" {
			endIdx = i
			break
		}
	}

	if endIdx == 0 {
		return &model.Skill{}, nil
	}

	// 提取 YAML 内容
	yamlContent := strings.Join(lines[1:endIdx], "\n")

	// 解析 YAML
	var frontMatter map[string]string
	if err := yaml.Unmarshal([]byte(yamlContent), &frontMatter); err != nil {
		return nil, err
	}

	skill := &model.Skill{
		SkillName: frontMatter["name"],
		SkillDesc: frontMatter["description"],
	}

	return skill, nil
}

// getProjectRoot 获取项目根目录
func (s *SkillService) getProjectRoot() string {
	execPath, _ := os.Getwd()
	projectRoot := execPath

	// 如果当前目录名为 server，向上找一级
	baseName := filepath.Base(execPath)
	if baseName == "server" {
		projectRoot = filepath.Dir(execPath)
	}

	// 尝试向上查找包含 .git 的目录
	if _, err := os.Stat(filepath.Join(projectRoot, ".git")); os.IsNotExist(err) {
		for i := 0; i < 3; i++ {
			parent := filepath.Dir(projectRoot)
			if parent == projectRoot {
				break
			}
			if _, err := os.Stat(filepath.Join(parent, ".git")); err == nil {
				projectRoot = parent
				break
			}
			projectRoot = parent
		}
	}

	return projectRoot
}
