using Microsoft.VisualStudio.TestTools.UnitTesting;
using YMhut.Box.Core.App;
using YMhut.Box.Core.Api;
using YMhut.Box.Core.Data;
using YMhut.Box.Core.Logging;
using YMhut.Box.Core.Settings;

namespace YMhut.Box.Tests;

[TestClass]
public sealed class ServiceLayerTests
{
    [TestMethod]
    public async Task SettingsServiceBroadcastsAndPersistsChanges()
    {
        var root = Path.Combine(Path.GetTempPath(), "ymhut-box-tests", Guid.NewGuid().ToString("N"));
        var service = new AppSettingsService(new AppSettingsStore(root));
        var changed = false;
        service.PropertyChanged += (_, args) => changed |= args.PropertyName == nameof(ISettingsService.Current);

        await service.LoadAsync();
        await service.UpdateAsync(settings => settings.Theme = "Dark");

        var reloaded = await new AppSettingsStore(root).LoadAsync();
        Assert.IsTrue(changed);
        Assert.AreEqual("Dark", reloaded.Theme);
    }

    [TestMethod]
    public async Task SettingsStorePersistsAndNormalizesFeedbackDefaults()
    {
        var root = Path.Combine(Path.GetTempPath(), "ymhut-box-tests", Guid.NewGuid().ToString("N"));
        var store = new AppSettingsStore(root);
        await store.SaveAsync(new AppSettings
        {
            FeedbackDefaultContact = "dev@example.com",
            FeedbackDefaultType = "bad-type",
            FeedbackDefaultSeverity = "bad-severity",
            FeedbackIncludeTodayLogsByDefault = true,
            FeedbackIncludeToolStatusByDefault = true,
            FeedbackIncludeSystemSummaryByDefault = true,
            FeedbackRememberDefaults = false
        });

        var settings = await store.LoadAsync();

        Assert.AreEqual("dev@example.com", settings.FeedbackDefaultContact);
        Assert.AreEqual("issue", settings.FeedbackDefaultType);
        Assert.AreEqual("normal", settings.FeedbackDefaultSeverity);
        Assert.IsTrue(settings.FeedbackIncludeTodayLogsByDefault);
        Assert.IsTrue(settings.FeedbackIncludeToolStatusByDefault);
        Assert.IsTrue(settings.FeedbackIncludeSystemSummaryByDefault);
        Assert.IsFalse(settings.FeedbackRememberDefaults);
    }

    [TestMethod]
    public async Task SettingsStorePersistsToolboxAndRiskSettings()
    {
        var root = Path.Combine(Path.GetTempPath(), "ymhut-box-tests", Guid.NewGuid().ToString("N"));
        var store = new AppSettingsStore(root);
        await store.SaveAsync(new AppSettings
        {
            ToolDisplayMode = "compact",
            ToolboxDefaultScope = "plugins",
            ToolboxCompactCards = true,
            ToolboxShowRecentFirst = false,
            ShowHardwareBrandLogo = false,
            RequireRiskConfirmation = false,
            LogRetentionCount = 90,
            PluginsEnabled = true
        });

        var settings = await store.LoadAsync();

        Assert.AreEqual("list", settings.ToolDisplayMode);
        Assert.AreEqual("plugin", settings.ToolboxDefaultScope);
        Assert.IsTrue(settings.ToolboxCompactCards);
        Assert.IsFalse(settings.ToolboxShowRecentFirst);
        Assert.IsFalse(settings.ShowHardwareBrandLogo);
        Assert.IsFalse(settings.RequireRiskConfirmation);
        Assert.AreEqual(90, settings.LogRetentionCount);
        Assert.IsTrue(settings.PluginsEnabled);
    }

    [TestMethod]
    public async Task LogServiceWritesReadsAndCleansUp()
    {
        var root = Path.Combine(Path.GetTempPath(), "ymhut-box-tests", Guid.NewGuid().ToString("N"));
        var service = new JsonFileLogService(AppPaths.ForCurrentUser(root));

        await service.WriteAsync("Information", "test", "first");
        await service.WriteAsync("Error", "test", "second");
        var errors = await service.ReadAsync("Error");

        Assert.HasCount(1, errors);
        Assert.AreEqual("second", errors[0].Message);

        await service.CleanupAsync(1);
        var all = await service.ReadAsync();
        Assert.HasCount(1, all);
    }

    [TestMethod]
    public void ApiEndpointsResolveWeather()
    {
        var ok = ApiEndpoints.TryResolve("weather", "Shanghai", out var endpoint, out var uri);

        Assert.IsTrue(ok);
        Assert.AreEqual("weather", endpoint.Id);
        StringAssert.Contains(endpoint.SourceName, "Open-Meteo");
        StringAssert.Contains(uri.Host, "open-meteo.com");
    }

    [TestMethod]
    public void ReferenceDataServiceValidatesRequiredAssets()
    {
        var root = Path.Combine(Path.GetTempPath(), "ymhut-box-tests", Guid.NewGuid().ToString("N"));
        var assets = Path.Combine(root, "Assets");
        Directory.CreateDirectory(Path.Combine(assets, "data", "reference"));
        File.WriteAllText(Path.Combine(assets, "data", "reference", "ymhut_reference_data.json"), "{}");

        var service = new ReferenceDataService(AppPaths.ForCurrentUser(root, assets));
        var result = service.ValidateRequiredAssets("data/reference/ymhut_reference_data.json", "data/missing.json");

        Assert.IsFalse(result.IsHealthy);
        Assert.HasCount(1, result.PresentPaths);
        Assert.HasCount(1, result.MissingPaths);
    }
}
