using System.IO;
using System.Text;
using SharepointToolbox.Core.Models;
using SharepointToolbox.Services;

namespace SharepointToolbox.Tests.Services;

public class CsvValidationServiceTests
{
    private readonly CsvValidationService _service = new();

    private static Stream ToStream(string content)
    {
        return new MemoryStream(Encoding.UTF8.GetBytes(content));
    }

    private static Stream ToStreamWithBom(string content)
    {
        var preamble = Encoding.UTF8.GetPreamble();
        var bytes = Encoding.UTF8.GetBytes(content);
        var combined = new byte[preamble.Length + bytes.Length];
        preamble.CopyTo(combined, 0);
        bytes.CopyTo(combined, preamble.Length);
        return new MemoryStream(combined);
    }

    [Fact]
    public void ParseAndValidateMembers_ValidCsv_ReturnsValidRows()
    {
        var csv = "GroupName,GroupUrl,Email,Role\nTeam A,https://site,user@test.com,Member\n";
        var rows = _service.ParseAndValidateMembers(ToStream(csv));

        Assert.Single(rows);
        Assert.True(rows[0].IsValid);
        Assert.Equal("user@test.com", rows[0].Record!.Email);
    }

    [Fact]
    public void ParseAndValidateMembers_InvalidEmail_ReturnsErrors()
    {
        var csv = "GroupName,GroupUrl,Email,Role\nTeam A,https://site,not-an-email,Member\n";
        var rows = _service.ParseAndValidateMembers(ToStream(csv));

        Assert.Single(rows);
        Assert.False(rows[0].IsValid);
        Assert.Contains(rows[0].Errors, e => e.Contains("Invalid email"));
    }

    [Fact]
    public void ParseAndValidateMembers_MissingGroup_ReturnsError()
    {
        var csv = "GroupName,GroupUrl,Email,Role\n,,user@test.com,Member\n";
        var rows = _service.ParseAndValidateMembers(ToStream(csv));

        Assert.Single(rows);
        Assert.False(rows[0].IsValid);
        Assert.Contains(rows[0].Errors, e => e.Contains("GroupName or GroupUrl"));
    }

    [Fact]
    public void ParseAndValidateSites_TeamWithoutOwner_ReturnsError()
    {
        var csv = "Name;Alias;Type;Template;Owners;Members\nSite A;site-a;Team;;;\n";
        var rows = _service.ParseAndValidateSites(ToStream(csv));

        Assert.Single(rows);
        Assert.False(rows[0].IsValid);
        Assert.Contains(rows[0].Errors, e => e.Contains("owner"));
    }

    [Fact]
    public void ParseAndValidateSites_ValidTeam_ReturnsValid()
    {
        var csv = "Name;Alias;Type;Template;Owners;Members\nSite A;site-a;Team;;admin@test.com;user@test.com\n";
        var rows = _service.ParseAndValidateSites(ToStream(csv));

        Assert.Single(rows);
        Assert.True(rows[0].IsValid);
        Assert.Equal("Site A", rows[0].Record!.Name);
    }

    [Fact]
    public void ParseAndValidateFolders_ValidCsv_ReturnsValidRows()
    {
        var csv = "Level1;Level2;Level3;Level4\nAdmin;HR;;\n";
        var rows = _service.ParseAndValidateFolders(ToStream(csv));

        Assert.Single(rows);
        Assert.True(rows[0].IsValid);
        Assert.Equal("Admin", rows[0].Record!.Level1);
        Assert.Equal("HR", rows[0].Record!.Level2);
    }

    [Fact]
    public void ParseAndValidateFolders_MissingLevel1_ReturnsError()
    {
        var csv = "Level1;Level2;Level3;Level4\n;SubFolder;;\n";
        var rows = _service.ParseAndValidateFolders(ToStream(csv));

        Assert.Single(rows);
        Assert.False(rows[0].IsValid);
        Assert.Contains(rows[0].Errors, e => e.Contains("Level1"));
    }

    [Fact]
    public void ParseAndValidate_BomDetection_WorksWithAndWithoutBom()
    {
        var csv = "GroupName,GroupUrl,Email,Role\nTeam A,https://site,user@test.com,Member\n";
        var rowsNoBom = _service.ParseAndValidateMembers(ToStream(csv));
        var rowsWithBom = _service.ParseAndValidateMembers(ToStreamWithBom(csv));

        Assert.Single(rowsNoBom);
        Assert.Single(rowsWithBom);
        Assert.True(rowsNoBom[0].IsValid);
        Assert.True(rowsWithBom[0].IsValid);
    }

    [Fact]
    public void ParseAndValidate_SemicolonDelimiter_DetectedAutomatically()
    {
        var csv = "Name;Alias;Type;Template;Owners;Members\nSite A;site-a;Communication;;;;\n";
        var rows = _service.ParseAndValidateSites(ToStream(csv));

        Assert.Single(rows);
        Assert.Equal("Site A", rows[0].Record!.Name);
        Assert.Equal("Communication", rows[0].Record!.Type);
    }
}
