using System.IO;
using System.Text;

namespace AxCopilot.Services.Agent;

/// <summary>
/// Phase 17-D: SkillService에 경로 기반 활성화 및 fork 컨텍스트 지원 추가.
/// SkillService.LoadSkills() 호출 후 이 클래스로 확장 데이터를 보강합니다.
/// </summary>
public static class SkillServiceExtensions
{
    /// <summary>
    /// 로드된 스킬 목록에서 Phase 17-D 확장 프론트매터를 파싱하여 SkillExtensionStore에 저장.
    /// SkillService.LoadSkills() 직후 호출하세요.
    /// </summary>
    public static void LoadExtendedFrontmatter(IReadOnlyList<SkillDefinition> skills)
    {
        SkillExtensionStore.Clear();

        foreach (var skill in skills)
        {
            if (string.IsNullOrEmpty(skill.FilePath) || !File.Exists(skill.FilePath))
                continue;

            try
            {
                var ext = ParseExtendedFrontmatter(skill.FilePath);
                if (ext != null)
                    SkillExtensionStore.Set(skill.Id, ext);
            }
            catch (Exception) { }
        }
    }

    private static SkillExtData? ParseExtendedFrontmatter(string filePath)
    {
        var content = File.ReadAllText(filePath, Encoding.UTF8);
        if (!content.TrimStart().StartsWith("---")) return null;

        var firstSep = content.IndexOf("---", StringComparison.Ordinal);
        var secondSep = content.IndexOf("---", firstSep + 3, StringComparison.Ordinal);
        if (secondSep < 0) return null;

        var frontmatter = content[(firstSep + 3)..secondSep].Trim();

        var data = new SkillExtData();
        bool hasExtFields = false;

        foreach (var line in frontmatter.Split('\n'))
        {
            var ci = line.IndexOf(':');
            if (ci <= 0) continue;
            var key = line[..ci].Trim().ToLowerInvariant();
            var value = line[(ci + 1)..].Trim().Trim('"', '\'');

            switch (key)
            {
                case "context":
                    if (value.Equals("fork", StringComparison.OrdinalIgnoreCase))
                    {
                        data.ContextMode = SkillContextMode.Fork;
                        hasExtFields = true;
                    }
                    break;
                case "model":
                    if (!string.IsNullOrEmpty(value))
                    {
                        data.ModelOverride = value;
                        hasExtFields = true;
                    }
                    break;
                case "user-invocable":
                case "user_invocable":
                    data.UserInvocable = !value.Equals("false", StringComparison.OrdinalIgnoreCase);
                    hasExtFields = true;
                    break;
                case "paths":
                    // 단일 값 또는 YAML 리스트 첫 줄
                    if (!string.IsNullOrEmpty(value))
                    {
                        data.PathPatterns.Add(value);
                        hasExtFields = true;
                    }
                    break;
            }
        }

        // paths: 여러 줄 파싱 (YAML 리스트: "  - pattern" 형식)
        var inPaths = false;
        foreach (var line in frontmatter.Split('\n'))
        {
            var trimmed = line.Trim();
            if (trimmed.StartsWith("paths:"))
            {
                inPaths = true;
                continue;
            }
            if (inPaths)
            {
                if (trimmed.StartsWith("-"))
                {
                    var pat = trimmed.TrimStart('-').Trim().Trim('"', '\'');
                    if (!string.IsNullOrEmpty(pat) && !data.PathPatterns.Contains(pat))
                    {
                        data.PathPatterns.Add(pat);
                        hasExtFields = true;
                    }
                }
                else if (!string.IsNullOrWhiteSpace(trimmed) && trimmed.Contains(':'))
                {
                    inPaths = false;
                }
            }
        }

        return hasExtFields ? data : null;
    }

    /// <summary>사용자 호출 가능한 스킬만 필터링 (슬래시 메뉴용).</summary>
    public static IReadOnlyList<SkillDefinition> GetUserInvocable(IReadOnlyList<SkillDefinition> skills)
        => skills.Where(s =>
        {
            var ext = SkillExtensionStore.Get(s.Id);
            return ext == null || ext.UserInvocable;
        }).ToList();

    /// <summary>paths 패턴이 등록된 스킬 목록 반환.</summary>
    public static IReadOnlyList<SkillDefinition> GetPathScoped(IReadOnlyList<SkillDefinition> skills)
        => skills.Where(s =>
        {
            var ext = SkillExtensionStore.Get(s.Id);
            return ext != null && ext.PathPatterns.Count > 0;
        }).ToList();
}

/// <summary>PathPatterns 접근용 SkillDefinition 확장 메서드.</summary>
public static class SkillDefinitionExtensions
{
    public static IReadOnlyList<string> GetPathPatterns(this SkillDefinition skill)
    {
        // Phase 24: SkillDefinition.Paths 필드 우선, 없으면 ExtensionStore 폴백
        if (!string.IsNullOrEmpty(skill.Paths))
        {
            return skill.Paths.Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
                .ToList();
        }
        return SkillExtensionStore.Get(skill.Id)?.PathPatterns ?? new List<string>();
    }

    public static SkillContextMode GetContextMode(this SkillDefinition skill)
    {
        if (skill.IsForkContext) return SkillContextMode.Fork;
        return SkillExtensionStore.Get(skill.Id)?.ContextMode ?? SkillContextMode.Default;
    }

    public static string? GetModelOverride(this SkillDefinition skill)
    {
        if (!string.IsNullOrEmpty(skill.ModelOverride)) return skill.ModelOverride;
        return SkillExtensionStore.Get(skill.Id)?.ModelOverride;
    }

    public static bool IsUserInvocable(this SkillDefinition skill)
        => skill.UserInvocable && (SkillExtensionStore.Get(skill.Id)?.UserInvocable ?? true);
}
