using GreenTree.Nachtragsmanagement.Core.Domain.Deviation;
using GreenTree.Nachtragsmanagement.Services.Configuration;
using GreenTree.Nachtragsmanagement.Web.Models.Appendix;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace GreenTree.Nachtragsmanagement.Web.Models.Deviation
{
    public class DeviationDataModel 
        : IRequireStatusDataModel, IRequireKindDataModel
    {
        public int Id { get; set; }
        public string CustomNumber { get; set; }
        public string Description { get; set; }
        public DateTime? ReceiptDate { get; set; }
        public int? DaysReceiptDateToday { get; set; }
        public DateTime? AppendixDate { get; set; }
        public decimal Value { get; set; }
        public decimal Percentage { get; set; }
        public decimal PercentageValue { get; set; }
        public int? StatusId { get; set; }
        public bool IsZeroSummarize { get; set; }
        public string StatusDescription { get; set; }
        public int? KindId { get; set; }
        public string KindDescription { get; set; }
        public string Comment { get; set; }
        public string SiteDescription { get; set; }
        public string SiteCustomNumber { get; set; }
        public int? SiteId { get; set; }
        public ICollection<string> UserDescriptions { get; set; }
        public string UserDescription { get; set; }
        public string AppendixDescription { get; set; }
        public int? AppendixId { get; set; }
        public int? DaysReceiptToAppendixOffering { get; set; }
        public ICollection<string> DisturbanceEntities { get; set; }
        public ICollection<DisturbanceValueDataModel> DisturbanceValueEntities { get; set; }
        public string DisturbanceValuesDescription
        {
            get
            {
                if (DisturbanceValueEntities == null)
                    return String.Empty;
                else
                    return String.Join(", ", DisturbanceValueEntities.Select(d => d.Description));
            }
        }
        public decimal? DisturbanceValueSum
        {
            get
            {
                if (DisturbanceValueEntities == null)
                    return null;
                else
                    return DisturbanceValueEntities.Sum(d => d.Value);
            }
        }
        public string DisplayColor { get; set; }

        public DeviationDataModel()
        {
            DisturbanceEntities = new List<string>();
            DisturbanceValueEntities = new List<DisturbanceValueDataModel>();
        }

        public static DeviationDataModel FromDeviation(Core.Domain.Deviation.Deviation deviationEntity, bool newWhenIsNull, 
            IConfigurationService configurationService)
        {
            if (deviationEntity == null && newWhenIsNull)
                return new DeviationDataModel
                {
                    Id = -1,
                    Percentage = 100
                };

            if (deviationEntity == null && !newWhenIsNull)
                throw new ArgumentNullException("deviationEntity", "Cannot create DeviationDataModel from NULL deviation entity.");

            var model = new DeviationDataModel
            {
                Id = deviationEntity.Id,
                CustomNumber = deviationEntity.CustomNumber,
                Description = deviationEntity.Description,
                ReceiptDate = deviationEntity.ReceiptDate,
                DaysReceiptDateToday = deviationEntity.ReceiptDate == null
                    ? (int?)(DateTime.Now - deviationEntity.ReceiptDate).Value.Days
                    : null,
                AppendixDate = deviationEntity.AppendixDate,
                Value = deviationEntity.Value.Value,
                Percentage = deviationEntity.Status != null && deviationEntity.Status.IsZeroValue
                    ? (decimal)0.0
                    : deviationEntity.Percentage.HasValue
                        ? deviationEntity.Percentage.Value
                        : (decimal)1.0,
                PercentageValue = deviationEntity.Status != null && deviationEntity.Status.IsZeroValue
                    ? 0
                    : (deviationEntity.Value.HasValue && deviationEntity.Percentage.HasValue
                        ? deviationEntity.Value.Value * deviationEntity.Percentage.Value
                        : 0),
                SiteId = deviationEntity.SiteId,
                SiteDescription = deviationEntity.Site == null
                    ? deviationEntity.Appendix == null
                        ? String.Empty
                        : deviationEntity.Appendix.Site == null
                            ? String.Empty
                            : deviationEntity.Appendix.Site.Description
                    : deviationEntity.Site.Description,
                SiteCustomNumber = deviationEntity.Site == null
                    ? deviationEntity.Appendix == null
                        ? String.Empty
                        : deviationEntity.Appendix.Site == null
                            ? String.Empty
                            : deviationEntity.Appendix.Site.CustomNumber
                    : deviationEntity.Site.CustomNumber,
                UserDescriptions = deviationEntity.Site == null
                    ? deviationEntity.Appendix == null || (deviationEntity.Appendix != null && deviationEntity.Appendix.Site == null)
                        ? null
                        : deviationEntity.Appendix.Site.Users
                            .Select(r => new
                            {
                                LastName = r.Lastname,
                                Roles = String.Join(", ", r.Roles.Select(u => u.Description))
                            })
                            .OrderBy(r => r.Roles)
                            .Select(r => String.Format("{0}|({1})", r.LastName, r.Roles))
                            .ToList()
                    : deviationEntity.Site.Users
                        .Select(r => new
                        {
                            LastName = r.Lastname,
                            Roles = String.Join(", ", r.Roles.Select(u => u.Description))
                        })
                        .OrderBy(r => r.Roles)
                        .Select(r => String.Format("{0}|({1})", r.LastName, r.Roles))
                        .ToList(),
                UserDescription = deviationEntity.Site == null
                    ? deviationEntity.Appendix == null || (deviationEntity.Appendix != null && deviationEntity.Appendix.Site == null)
                        ? String.Empty
                        : String.Join(", ",
                              deviationEntity.Appendix.Site.Users
                                  .Select(r => new
                                  {
                                      LastName = r.Lastname,
                                      Roles = String.Join(", ", r.Roles.Select(u => u.Description))
                                  })
                                  .Select(u => String.Format("{0} ({1})", u.LastName, u.Roles)))
                    : String.Join(", ",
                        deviationEntity.Site.Users
                            .Select(r => new
                            {
                                LastName = r.Lastname,
                                Roles = String.Join(", ", r.Roles.Select(u => u.Description))
                            })
                            .Select(u => String.Format("{0} ({1})", u.LastName, u.Roles))),
                AppendixId = deviationEntity.AppendixId,
                AppendixDescription = deviationEntity.Appendix == null
                    ? "Offen"
                    : deviationEntity.Appendix.CustomNumber,
                StatusId = deviationEntity.StatusId.Value,
                StatusDescription = deviationEntity.Status == null
                    ? null
                    : deviationEntity.Status.Description,
                IsZeroSummarize = deviationEntity.Status != null && deviationEntity.Status.IsZeroSummarize,
                KindId = deviationEntity.KindId.Value,
                KindDescription = deviationEntity.Kind == null
                    ? null
                    : deviationEntity.Kind.Shortance,
                Comment = deviationEntity.Comment,
                DaysReceiptToAppendixOffering = deviationEntity.Appendix == null
                    ? null
                    : deviationEntity.Appendix.OfferingDate.HasValue && deviationEntity.ReceiptDate.HasValue
                        ? (int?)(deviationEntity.Appendix.OfferingDate.Value - deviationEntity.ReceiptDate.Value).Days
                        : null,
                DisturbanceValueEntities =
                    deviationEntity.DisturbanceValues
                        .Select(r =>
                            new DisturbanceValueDataModel
                            {
                                DisturbanceId = r.DisturbanceId,
                                Description = String.Format("{0} - {1:c2}", r.Disturbance.Description, r.Value),
                                Value = r.Value
                            })
                        .ToList()
            };

            var colorLevel1 = configurationService.TryGetConfigItemValue<string>(
                "GreenTree.Nachtragsmanagement.DeviationNotificationPlugin.ProcessDeviationReceipt.HexColorLevel1", "#FFD800");
            var ageDaysLevel1 = configurationService.TryGetConfigItemValue<int>(
                "GreenTree.Nachtragsmanagement.DeviationNotificationPlugin.ProcessDeviationReceipt.AgeDaysLevel1", 40);

            var colorLevel2 = configurationService.TryGetConfigItemValue<string>(
                "GreenTree.Nachtragsmanagement.DeviationNotificationPlugin.ProcessDeviationReceipt.HexColorLevel2", "#FF6A00");
            var ageDaysLevel2 = configurationService.TryGetConfigItemValue<int>(
                "GreenTree.Nachtragsmanagement.DeviationNotificationPlugin.ProcessDeviationReceipt.AgeDaysLevel2", 60);

            if (model.DaysReceiptDateToday >= ageDaysLevel1 && model.DaysReceiptDateToday < ageDaysLevel2 && !model.AppendixId.HasValue)
                model.DisplayColor = colorLevel1;
            else if (model.DaysReceiptDateToday >= ageDaysLevel2 && !model.AppendixId.HasValue)
                model.DisplayColor = colorLevel2;

            foreach (var disturbance in model.DisturbanceValueEntities)
            {
                var json = JsonConvert.SerializeObject(disturbance);

                disturbance.Json = json;

                model.DisturbanceEntities.Add(json);
            }

            return model;
        }

        public Core.Domain.Deviation.Deviation ToDeviation()
        {
            return new Core.Domain.Deviation.Deviation
            {
                Id = this.Id,
                CustomNumber = this.CustomNumber,
                Description = Description,
                ReceiptDate = this.ReceiptDate,
                AppendixDate = this.AppendixDate,
                Value = this.Value,
                Percentage = this.Percentage,
                SiteId = this.SiteId,
                AppendixId = this.AppendixId,
                StatusId = this.StatusId,
                KindId = this.KindId,
                Comment = this.Comment
            };
        }
    }
}