using ROCrates.Models;
using Xunit.Abstractions;
using File = ROCrates.Models.File;

namespace ROCrates.Tests;

public class TestRoCrate
{
  private readonly ITestOutputHelper _testOutputHelper;

  public TestRoCrate(ITestOutputHelper testOutputHelper)
  {
    _testOutputHelper = testOutputHelper;
  }

  [Fact]
  public void TestResolveId_CombinesGoodAndBad_Uris()
  {
    string validUrl = "https://doi.org/10.4225/59/59672c09f4a4b";
    string invalidUrl = "https://do i.org/10.4225/59/59672c09f4a4b";
    var crate = new ROCrate("my-test.zip");

    string resultValidUrl = crate.ResolveId(validUrl);
    Assert.Equal(validUrl, resultValidUrl);

    string resultInvalidUrl = crate.ResolveId(invalidUrl);
    Assert.StartsWith("arcp://", resultInvalidUrl);
    Assert.EndsWith(invalidUrl, resultInvalidUrl);
  }

  [Fact]
  public void TestAdd_AddsRootDataset()
  {
    var roCrate = new ROCrate();
    var rootDataset = new RootDataset(roCrate);

    roCrate.Add(rootDataset);
    Assert.Equal(roCrate.RootDataset.Id, rootDataset.Id);
    Assert.Equal(roCrate.RootDataset.Properties, rootDataset.Properties);

    Assert.True(roCrate.Entities.ContainsKey(rootDataset.GetCanonicalId()));
    Assert.True(roCrate.Entities.TryGetValue(rootDataset.GetCanonicalId(), out var recoveredRootDataset));
    Assert.IsType<RootDataset>(recoveredRootDataset);
  }

  [Fact]
  public void TestAdd_AddsMetadata()
  {
    var roCrate = new ROCrate();
    var metadata = new Metadata(roCrate);

    roCrate.Add(metadata);
    Assert.Equal(roCrate.Metadata.Id, metadata.Id);
    Assert.Equal(roCrate.Metadata.Properties, metadata.Properties);

    Assert.True(roCrate.Entities.ContainsKey(metadata.GetCanonicalId()));
    Assert.True(roCrate.Entities.TryGetValue(metadata.GetCanonicalId(), out var recoveredMetadata));
    Assert.IsType<Metadata>(recoveredMetadata);
  }

  [Fact]
  public void TestAdd_AddsObjetsOfDifferentTypes()
  {
    var roCrate = new ROCrate();
    var person = new Person(roCrate);
    var file = new File(roCrate, source: "my-test-file.txt");
    var dataset = new Dataset(roCrate, source: "my-data-dir/");

    roCrate.Add(person, file, dataset);

    Assert.True(roCrate.Entities.ContainsKey(person.GetCanonicalId()));
    Assert.True(roCrate.Entities.TryGetValue(person.GetCanonicalId(), out var recoveredPerson));
    Assert.IsType<Person>(recoveredPerson);

    Assert.True(roCrate.Entities.ContainsKey(file.GetCanonicalId()));
    Assert.True(roCrate.Entities.TryGetValue(file.GetCanonicalId(), out var recoveredFile));
    Assert.IsType<File>(recoveredFile);

    Assert.True(roCrate.Entities.ContainsKey(dataset.GetCanonicalId()));
    Assert.True(roCrate.Entities.TryGetValue(dataset.GetCanonicalId(), out var recoveredDataset));
    Assert.IsType<Dataset>(recoveredDataset);
  }
}
