using System;
using System.IO;
using System.Text;
using FluentAssertions;
using MarcusLaw.OutlookAddin.Core.Configuration;
using MarcusLaw.OutlookAddin.Core.Models;
using Xunit;

namespace MarcusLaw.OutlookAddin.Tests.Configuration
{
    public class SettingsManagerTests : IDisposable
    {
        private readonly string _tempDir;

        public SettingsManagerTests()
        {
            _tempDir = Path.Combine(Path.GetTempPath(), "OutlookAddinSettingsTests-" + Guid.NewGuid().ToString("N"));
            Directory.CreateDirectory(_tempDir);
        }

        public void Dispose()
        {
            try { Directory.Delete(_tempDir, recursive: true); } catch { }
        }

        private SettingsManager NewManager() =>
            new SettingsManager(Path.Combine(_tempDir, "settings.json"));

        [Fact]
        public void Load_ReturnsDefaults_WhenFileMissing()
        {
            var mgr = NewManager();

            var settings = mgr.Load();

            settings.Should().NotBeNull();
            settings.Locale.Should().Be("he-IL");
            settings.RecentEntities.Should().BeEmpty();
            settings.WatchedFolders.Should().BeEmpty();
        }

        [Fact]
        public void SaveThenLoad_RoundTripsAllFields()
        {
            var mgr = NewManager();

            var settings = new AppSettings
            {
                EspoCrmUrl = "https://crm.test/",
                Locale = "en-US",
                RecentEntities =
                {
                    new EspoEntityRef { Id = "1", Name = "Smith Family", EntityType = "Account" }
                },
                WatchedFolders =
                {
                    new WatchedFolder
                    {
                        StoreId = "store-1",
                        FolderPath = @"\Inbox\Clients",
                        DefaultParentId = "p1",
                        DefaultParentType = "Case",
                        Mode = WatchMode.AutoFile,
                        ConfidenceThreshold = 0.9
                    }
                }
            };

            mgr.Save(settings);
            var loaded = mgr.Load();

            loaded.EspoCrmUrl.Should().Be("https://crm.test/");
            loaded.Locale.Should().Be("en-US");
            loaded.RecentEntities.Should().ContainSingle().Which.Name.Should().Be("Smith Family");
            loaded.WatchedFolders.Should().ContainSingle()
                .Which.Should().BeEquivalentTo(settings.WatchedFolders[0]);
        }

        [Fact]
        public void SaveThenLoad_PreservesHebrewStrings()
        {
            var mgr = NewManager();

            var settings = new AppSettings
            {
                Locale = "he-IL",
                RecentEntities =
                {
                    new EspoEntityRef { Id = "case-77", Name = "תיק משפחת כהן 2025-77", EntityType = "Case" }
                }
            };

            mgr.Save(settings);
            var loaded = mgr.Load();

            loaded.RecentEntities[0].Name.Should().Be("תיק משפחת כהן 2025-77");
        }

        [Fact]
        public void Save_WritesUtf8WithoutBom()
        {
            var mgr = NewManager();
            mgr.Save(new AppSettings { Locale = "he-IL" });

            var bytes = File.ReadAllBytes(mgr.FilePath);

            bytes.Length.Should().BeGreaterThan(3);
            (bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF).Should().BeFalse("settings.json should not have UTF-8 BOM");
            Encoding.UTF8.GetString(bytes).Should().Contain("\"he-IL\"");
        }

        [Fact]
        public void Load_ReturnsDefaults_WhenFileCorrupt()
        {
            var path = Path.Combine(_tempDir, "settings.json");
            File.WriteAllText(path, "{ this is not json");
            var mgr = new SettingsManager(path);

            var settings = mgr.Load();

            settings.Should().NotBeNull();
            settings.Locale.Should().Be("he-IL");
        }

        [Fact]
        public void Save_CreatesParentDirectory_WhenMissing()
        {
            var nested = Path.Combine(_tempDir, "a", "b", "settings.json");
            var mgr = new SettingsManager(nested);

            mgr.Save(new AppSettings());

            File.Exists(nested).Should().BeTrue();
        }
    }
}
