using System.IO;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Moq;
using SharepointToolbox.Core.Models;
using SharepointToolbox.Infrastructure.Auth;
using SharepointToolbox.Infrastructure.Persistence;
using SharepointToolbox.Services;
using SharepointToolbox.ViewModels;

namespace SharepointToolbox.Tests.ViewModels;

[Trait("Category", "Unit")]
public class ProfileManagementViewModelLogoTests : IDisposable
{
    private readonly string _tempFile;
    private readonly Mock<IBrandingService> _mockBranding;
    private readonly Mock<IAppRegistrationService> _mockAppReg;
    private readonly GraphClientFactory _graphClientFactory;
    private readonly ILogger<ProfileManagementViewModel> _logger;

    public ProfileManagementViewModelLogoTests()
    {
        _tempFile = Path.GetTempFileName();
        File.Delete(_tempFile);
        _mockBranding = new Mock<IBrandingService>();
        _mockAppReg = new Mock<IAppRegistrationService>();
        _graphClientFactory = new GraphClientFactory(new MsalClientFactory());
        _logger = NullLogger<ProfileManagementViewModel>.Instance;
    }

    public void Dispose()
    {
        if (File.Exists(_tempFile)) File.Delete(_tempFile);
        if (File.Exists(_tempFile + ".tmp")) File.Delete(_tempFile + ".tmp");
    }

    private ProfileManagementViewModel CreateViewModel()
    {
        var profileService = new ProfileService(new ProfileRepository(_tempFile));
        return new ProfileManagementViewModel(
            profileService,
            _mockBranding.Object,
            _graphClientFactory,
            _logger,
            _mockAppReg.Object);
    }

    [Fact]
    public void Constructor_BrowseClientLogoCommand_IsNotNull()
    {
        var vm = CreateViewModel();
        Assert.NotNull(vm.BrowseClientLogoCommand);
    }

    [Fact]
    public void Constructor_ClearClientLogoCommand_IsNotNull()
    {
        var vm = CreateViewModel();
        Assert.NotNull(vm.ClearClientLogoCommand);
    }

    [Fact]
    public void Constructor_AutoPullClientLogoCommand_IsNotNull()
    {
        var vm = CreateViewModel();
        Assert.NotNull(vm.AutoPullClientLogoCommand);
    }

    [Fact]
    public void BrowseClientLogoCommand_CannotExecute_WhenNoProfileSelected()
    {
        var vm = CreateViewModel();
        Assert.False(vm.BrowseClientLogoCommand.CanExecute(null));
    }

    [Fact]
    public void ClearClientLogoCommand_CannotExecute_WhenNoProfileSelected()
    {
        var vm = CreateViewModel();
        Assert.False(vm.ClearClientLogoCommand.CanExecute(null));
    }

    [Fact]
    public void AutoPullClientLogoCommand_CannotExecute_WhenNoProfileSelected()
    {
        var vm = CreateViewModel();
        Assert.False(vm.AutoPullClientLogoCommand.CanExecute(null));
    }

    [Fact]
    public async Task ClearClientLogoCommand_ClearsClientLogo_AndPersists()
    {
        var profileService = new ProfileService(new ProfileRepository(_tempFile));
        var profile = new TenantProfile
        {
            Name = "TestTenant",
            TenantUrl = "https://test.sharepoint.com",
            ClientId = "00000000-0000-0000-0000-000000000001",
            ClientLogo = new LogoData { Base64 = "dGVzdA==", MimeType = "image/png" }
        };
        await profileService.AddProfileAsync(profile);

        var vm = new ProfileManagementViewModel(
            profileService,
            _mockBranding.Object,
            _graphClientFactory,
            _logger,
            _mockAppReg.Object);

        vm.SelectedProfile = profile;

        await vm.ClearClientLogoCommand.ExecuteAsync(null);

        Assert.Null(profile.ClientLogo);

        // Verify persisted
        var profiles = await profileService.GetProfilesAsync();
        var persisted = profiles.First(p => p.Name == "TestTenant");
        Assert.Null(persisted.ClientLogo);
    }

    [Fact]
    public void ClientLogoPreview_IsNull_WhenNoProfileSelected()
    {
        var vm = CreateViewModel();
        Assert.Null(vm.ClientLogoPreview);
    }

    [Fact]
    public void ClientLogoPreview_UpdatesToDataUri_WhenProfileWithLogoSelected()
    {
        var vm = CreateViewModel();
        var profile = new TenantProfile
        {
            Name = "WithLogo",
            TenantUrl = "https://test.sharepoint.com",
            ClientId = "00000000-0000-0000-0000-000000000002",
            ClientLogo = new LogoData { Base64 = "dGVzdA==", MimeType = "image/png" }
        };

        vm.SelectedProfile = profile;

        Assert.Equal("data:image/png;base64,dGVzdA==", vm.ClientLogoPreview);
    }

    [Fact]
    public void ClientLogoPreview_IsNull_WhenProfileWithoutLogoSelected()
    {
        var vm = CreateViewModel();
        var profile = new TenantProfile
        {
            Name = "NoLogo",
            TenantUrl = "https://test.sharepoint.com",
            ClientId = "00000000-0000-0000-0000-000000000003"
        };

        vm.SelectedProfile = profile;

        Assert.Null(vm.ClientLogoPreview);
    }

    [Fact]
    public async Task ClearClientLogoCommand_SetsClientLogoPreviewToNull()
    {
        var profileService = new ProfileService(new ProfileRepository(_tempFile));
        var profile = new TenantProfile
        {
            Name = "ClearTest",
            TenantUrl = "https://test.sharepoint.com",
            ClientId = "00000000-0000-0000-0000-000000000004",
            ClientLogo = new LogoData { Base64 = "dGVzdA==", MimeType = "image/png" }
        };
        await profileService.AddProfileAsync(profile);

        var vm = new ProfileManagementViewModel(
            profileService,
            _mockBranding.Object,
            _graphClientFactory,
            _logger,
            _mockAppReg.Object);

        vm.SelectedProfile = profile;
        Assert.NotNull(vm.ClientLogoPreview);

        await vm.ClearClientLogoCommand.ExecuteAsync(null);

        Assert.Null(vm.ClientLogoPreview);
    }
}
