using System.ComponentModel;
using Evos.Api.Common.Families;
using Evos.Api.Model;
using Evos.Api.Model.PredefinedFamilies;
using Evos.Api.Model.Serialization;
using Evos.Api.Samples.Infrastructure;

namespace Evos.Api.Samples
{
    /// Сохранение обменной модели и чтение обратно.
    /// Формат бинарный (protobuf), поэтому обмен идёт либо файлом, либо потоком.
    [Localizable(false)]
    public static class SerializeExchangeModelSample
    {
        public static void Run()
        {
            var projectId = SampleIdentifiers.ProjectId;
            var model = BuildExchangeModelSample.CreateCatalogModel(projectId);

            ExchangeThroughFile(model, projectId);
            ExchangeThroughStream(model, projectId);
        }

        /// Обмен файлом: сериализатору отдают путь, он сам открывает и закрывает файл.
        private static void ExchangeThroughFile(IReadOnlyExchangeModel model, Guid projectId)
        {
            var filePath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid():N}.evosexchange");
            try
            {
                ExchangeModelSerializerFactory.CreateSerializer().Serialize(model, filePath);
                Console.WriteLine($"Модель записана в {filePath} ({new FileInfo(filePath).Length} байт)");

                var restored = ExchangeModelSerializerFactory.CreateDeserializer().Deserialize(filePath);
                CheckRestoredMatchesOriginal(restored, model, projectId);

                foreach (var product in restored.Products)
                {
                    var manufacturer = product.KeyProperties.GetValue(CommonFamilies.КаталогПроизводитель.Производитель);
                    var name = product.Properties.GetValue(EvosFamilies.ProductName.Name);
                    Console.WriteLine($"  прочитан продукт: {name} ({manufacturer})");
                }
            }
            finally
            {
                File.Delete(filePath);
            }
        }

        /// Тот же обмен, но без файла на диске — так модель отдают в память или в сеть.
        /// Поток перед чтением надо перемотать на начало: сериализатор оставляет его в конце.
        private static void ExchangeThroughStream(IReadOnlyExchangeModel model, Guid projectId)
        {
            using var stream = new MemoryStream();

            ExchangeModelSerializerFactory.CreateSerializer().Serialize(model, stream);
            stream.Position = 0;

            var restored = ExchangeModelSerializerFactory.CreateDeserializer().Deserialize(stream);
            CheckRestoredMatchesOriginal(restored, model, projectId);

            Console.WriteLine($"Модель прочитана из потока ({stream.Length} байт), продуктов — {restored.Products.Count}");
        }

        private static void CheckRestoredMatchesOriginal(IReadOnlyExchangeModel restored, IReadOnlyExchangeModel model, Guid projectId)
        {
            SampleCheck.That(restored.ProjectId == projectId, "идентификатор проекта должен сохраниться");
            SampleCheck.That(restored.Products.Count == model.Products.Count, "число продуктов должно сохраниться");
        }
    }
}
