package com.easyagents.skill.repository.memory;

import com.easyagents.skill.model.Skill;
import com.easyagents.skill.model.SkillDescriptor;
import com.easyagents.skill.model.SkillReference;
import com.easyagents.skill.util.SkillResources;
import org.junit.Assert;
import org.junit.Test;

import java.util.Optional;

/**
 * InMemorySkillRepository 单元测试。
 */
public class InMemorySkillRepositoryTest {

    /**
     * 覆盖保存、读取、描述、列表、删除和存在性判断。
     */
    @Test
    public void crudSkill() {
        InMemorySkillRepository repository = new InMemorySkillRepository();
        Skill skill = skill();

        repository.save(skill);

        Assert.assertTrue(repository.exists("skill-a"));
        Assert.assertTrue(repository.get("skill-a").isPresent());
        Assert.assertTrue(repository.getDescriptor("skill-a").isPresent());
        Assert.assertEquals(1, repository.listDescriptors().size());

        repository.delete("skill-a");

        Assert.assertFalse(repository.exists("skill-a"));
        Assert.assertFalse(repository.get("skill-a").isPresent());
    }

    /**
     * descriptor 不携带 references/scripts/assets 内容。
     */
    @Test
    public void descriptorDoesNotExposeResourceContent() {
        InMemorySkillRepository repository = new InMemorySkillRepository();
        repository.save(skill());

        Optional<SkillDescriptor> descriptor = repository.getDescriptor("skill-a");

        Assert.assertTrue(descriptor.isPresent());
        Assert.assertEquals("skill-a", descriptor.get().getId());
        Assert.assertEquals("Skill A", descriptor.get().getName());
    }

    /**
     * 读取返回副本，避免外部修改仓储内部状态。
     */
    @Test
    public void getReturnsCopy() {
        InMemorySkillRepository repository = new InMemorySkillRepository();
        repository.save(skill());

        Skill loaded = repository.get("skill-a").get();
        loaded.setName("Changed");
        loaded.getReferences().get(0).setContent("changed");

        Skill reloaded = repository.get("skill-a").get();
        Assert.assertEquals("Skill A", reloaded.getName());
        Assert.assertEquals("# A", reloaded.getReferences().get(0).getContent());
    }

    /**
     * 仓储复制旧资源对象时应先迁移正式资源，不能因空 canonical 列表丢失 reference。
     */
    @Test
    public void repositoryCopyMigratesLegacyOnlyResources() {
        InMemorySkillRepository repository = new InMemorySkillRepository();
        Skill legacy = skill();
        Assert.assertFalse(legacy.isResourcesInitialized());

        repository.save(legacy);
        Skill loaded = repository.get("skill-a").orElseThrow();

        Assert.assertTrue(loaded.isResourcesInitialized());
        Assert.assertEquals(1, SkillResources.canonicalResources(loaded).size());
        Assert.assertEquals("references/a.md", loaded.getResources().get(0).getPath());
    }

    /**
     * 显式清空正式资源列表后，仓储往返不得从旧兼容视图恢复已删除资源。
     */
    @Test
    public void repositoryCopyPreservesExplicitlyEmptyCanonicalResources() {
        InMemorySkillRepository repository = new InMemorySkillRepository();
        Skill skill = skill();
        Assert.assertEquals(1, skill.getResources().size());
        skill.getResources().clear();

        repository.save(skill);
        Skill loaded = repository.get("skill-a").orElseThrow();

        Assert.assertTrue(loaded.isResourcesInitialized());
        Assert.assertTrue(SkillResources.canonicalResources(loaded).isEmpty());
    }

    private static Skill skill() {
        Skill skill = new Skill();
        skill.setId("skill-a");
        skill.setName("Skill A");
        skill.setDescription("Desc A");
        skill.setSkillContent("---\nname: Skill A\ndescription: Desc A\n---\n# Skill A\n");

        SkillReference reference = new SkillReference();
        reference.setPath("references/a.md");
        reference.setName("a.md");
        reference.setContent("# A");
        skill.getReferences().add(reference);
        return skill;
    }
}
