using TraceCad.Core.Geometry;
using TraceCad.Core.Model;
using TraceCad.Core.Serialization;
using Xunit;

namespace TraceCad.Tests;

public sealed class SerializationTests
{
    [Fact]
    public void SketchDocumentRoundTripsEntitiesAndLayers()
    {
        var document = SketchDocument.CreateDefault();
        var lineId = Guid.NewGuid();
        var circleId = Guid.NewGuid();
        var arcId = Guid.NewGuid();

        document.AddEntity(new LineEntity(lineId, Layer.Cut.Name, new Point2(10, 20), new Point2(40, 50)));
        document.AddEntity(new CircleEntity(circleId, Layer.Cut.Name, new Point2(15, 15), 8));
        document.AddEntity(new ArcEntity(arcId, Layer.Cut.Name, new Point2(0, 0), 12, 0, 90, false));
        document.AddConstraint(new SketchConstraint(Guid.NewGuid(), ConstraintType.Tangent, new[] { lineId, arcId }));
        document.AddConstraint(new SketchConstraint(Guid.NewGuid(), ConstraintType.Radius, new[] { arcId }, 12.0));

        var json = SketchDocumentSerializer.Serialize(document);
        var reloaded = SketchDocumentSerializer.Deserialize(json);

        Assert.Equal("mm", reloaded.Units);
        Assert.Equal(document.Layers.Count, reloaded.Layers.Count);
        Assert.Contains(reloaded.Entities, entity => entity.Id == lineId);
        Assert.Contains(reloaded.Entities, entity => entity.Id == circleId);
        Assert.Contains(reloaded.Entities, entity => entity.Id == arcId);
        Assert.Contains(reloaded.Constraints, constraint =>
            constraint.Type == ConstraintType.Tangent &&
            constraint.EntityIds.Contains(lineId) &&
            constraint.EntityIds.Contains(arcId));
        Assert.Contains(reloaded.Constraints, constraint =>
            constraint.Type == ConstraintType.Radius &&
            constraint.EntityIds.Contains(arcId) &&
            constraint.ValueMm == 12.0);
    }

    [Fact]
    public void SketchDocumentRoundTripsReferenceImage()
    {
        var document = SketchDocument.CreateDefault();
        document.Reference = new ReferenceImage(
            "reference.png",
            0.42,
            Locked: false,
            new ReferenceTransform(12.5, 20.0, 0.25, 0.25, 8.0))
        {
            Calibration = new ReferenceCalibration(
                TargetLineLengthMm: 30.0,
                MeasuredLineLengthMm: 30.18,
                ErrorMm: 0.18,
                EstimatedAccuracyMm: 0.18,
                ScaleCorrectionFactor: 30.0 / 30.18,
                MeetsTargetAccuracy: false,
                ControlLineDetected: true)
        };

        var json = SketchDocumentSerializer.Serialize(document);
        var reloaded = SketchDocumentSerializer.Deserialize(json);

        Assert.NotNull(reloaded.Reference);
        Assert.Equal("reference.png", reloaded.Reference.ImagePath);
        Assert.Equal(0.42, reloaded.Reference.Opacity, 9);
        Assert.False(reloaded.Reference.Locked);
        Assert.Equal(12.5, reloaded.Reference.Transform.OriginX, 9);
        Assert.Equal(0.25, reloaded.Reference.Transform.ScaleX, 9);
        Assert.Equal(8.0, reloaded.Reference.Transform.RotationDeg, 9);
        Assert.NotNull(reloaded.Reference.Calibration);
        Assert.Equal(30.0, reloaded.Reference.Calibration.TargetLineLengthMm, 9);
        Assert.Equal(30.18, reloaded.Reference.Calibration.MeasuredLineLengthMm, 9);
        Assert.False(reloaded.Reference.Calibration.MeetsTargetAccuracy);
    }
}
