using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace GreenTree.Nachtragsmanagement.Web.Models.Appendix
{
    public class AppendixDataModel : IRequireStateDataModel
    {
        public int Id { get; set; }
        public string CustomNumber { get; set; }
        public string Description { get; set; }
        public decimal? Probability { get; set; }
        public int? OfferingNumber { get; set; }
        public DateTime? OfferingDate { get; set; }
        public decimal OfferingValue { get; set; }
        public decimal? RelationOfferingToDeviations { get; set; }
        public decimal Percentage { get; set; }
        public decimal PercentageValue { get; set; }
        public DateTime? NegotiationDate { get; set; }
        public decimal? NegotiationValue { get; set; }
        public decimal? RelationOfferingToNegotiation { get; set; }
        public bool ProtocolExists { get; set; }
        public string OrderNumber { get; set; }
        public DateTime? OrderDate { get; set; }
        public bool OrderInvoiceCreated { get; set; }
        public string OrderInvoiceCreatedDescription { get; set; }
        public string Comment { get; set; }
        public int? StateId { get; set; }
        public StateDataModel State { get; set; }
        public string StateDescription { 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 ICollection<int> DeviationValues { get; set; }
        public ICollection<string> DeviationDescriptions { get; set; }
        public string DeviationDescription { get; set; }
        public ICollection<string> CategoryEntities { get; set; }
        public ICollection<CategoryValueDataModel> CategoryValueEntities { get; set; }
        public string CategoryValuesDescription
        {
            get
            {
                if (CategoryValueEntities == null)
                    return String.Empty;
                else
                    return String.Join(", ", CategoryValueEntities.Select(d => d.Description));
            }
        }
        public string InvoiceDescription { get; set; }
        public ICollection<InvoiceDataModel> Invoices { get; set; }


        public AppendixDataModel()
        {
            DeviationValues = new List<int>();
            DeviationDescriptions = new List<string>();
            CategoryEntities = new List<string>();
            CategoryValueEntities = new List<CategoryValueDataModel>();
            Invoices = new List<InvoiceDataModel>();
        }

        public static AppendixDataModel FromAppendix(Core.Domain.Appendix.Appendix appendixEntity, bool newWhenIsNull)
        {
            if (appendixEntity == null && newWhenIsNull)
                return new AppendixDataModel
                {
                    Id = -1,
                    Percentage = (decimal)1.0
                };

            if (appendixEntity == null && !newWhenIsNull)
                throw new ArgumentNullException("appendixEntity", "Cannot create AppendixDataModel from NULL appendix entity.");

            var model = new AppendixDataModel
            {
                Id = appendixEntity.Id,
                CustomNumber = appendixEntity.CustomNumber,
                Description = appendixEntity.Description,
                Percentage = appendixEntity.Percentage.HasValue
                    ? appendixEntity.Percentage.Value
                    : (decimal)0.5,
                PercentageValue = appendixEntity.Value.HasValue && appendixEntity.Percentage.HasValue
                    ? appendixEntity.Value.Value * appendixEntity.Percentage.Value
                    : 0,
                OfferingNumber = appendixEntity.OfferingNumber,
                OfferingDate = appendixEntity.OfferingDate,
                OfferingValue = appendixEntity.Value.Value,
                RelationOfferingToDeviations =
                    appendixEntity.Value.HasValue && appendixEntity.Deviations.Any()
                        ? appendixEntity.Deviations
                            .Sum(r => r.Value.HasValue && r.Percentage.HasValue ? r.Value.Value * r.Percentage.Value : 0) != 0
                                ? (decimal?)Convert.ToDecimal(
                                    (appendixEntity.Value.Value * appendixEntity.Percentage.Value) / appendixEntity.Deviations
                                        .Sum(r => r.Value.HasValue && r.Percentage.HasValue 
                                            ? r.Value.Value * r.Percentage.Value 
                                            : 0))
                                : null
                        : null,
                NegotiationDate = appendixEntity.NegotiationDate,
                NegotiationValue = appendixEntity.NegotiationValue,
                RelationOfferingToNegotiation =
                    appendixEntity.Percentage.HasValue && appendixEntity.NegotiationValue.HasValue
                        ? appendixEntity.NegotiationValue / 
                            (appendixEntity.Value == 0 
                                ? 1 
                                : (appendixEntity.Value.Value * appendixEntity.Percentage.Value))
                        : null,
                ProtocolExists = appendixEntity.ProtocolExists,
                OrderNumber = appendixEntity.OrderNumber,
                OrderDate = appendixEntity.OrderDate,
                Comment = appendixEntity.Comment,
                OrderInvoiceCreated = appendixEntity.OrderInvoiceCreated,
                OrderInvoiceCreatedDescription =
                    appendixEntity.OrderInvoiceCreated
                        ? "Ja"
                        : "Nein",
                StateId = appendixEntity.StateId,
                State = appendixEntity.State == null
                    ? null
                    : StateDataModel.FromState(appendixEntity.State, false),
                StateDescription = appendixEntity.State == null
                    ? null
                    : appendixEntity.State.Description,
                SiteId = appendixEntity.SiteId,
                SiteDescription = appendixEntity.Site == null
                    ? null
                    : appendixEntity.Site.Description,
                SiteCustomNumber = appendixEntity.Site == null
                    ? null
                    : appendixEntity.Site.CustomNumber,
                UserDescriptions = appendixEntity.Site == null
                    ? null
                    : appendixEntity.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 = appendixEntity.Site == null
                    ? String.Empty
                    : String.Join(", ",
                          appendixEntity.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))),
                CategoryValueEntities =
                    appendixEntity.CategoryValues
                        .Select(r =>
                            new CategoryValueDataModel
                            {
                                CategoryId = r.CategoryId,
                                Description = String.Format("{0} - {1:c2}", r.Category.Description, r.Value),
                                Value = r.Value
                            })
                        .ToList(),
                DeviationValues =
                    appendixEntity.Deviations
                        .Select(r => r.Id)
                        .ToList(),
                DeviationDescriptions =
                    appendixEntity.Deviations
                        .Select(r => r.CustomNumber)
                        .ToList(),
                DeviationDescription =
                    String.Join(", ",
                        appendixEntity.Deviations
                            .Select(d => d.CustomNumber)),
                Invoices =
                    appendixEntity.Invoices
                        .Select(i => InvoiceDataModel.FromInvoice(i, false))
                        .ToList()
            };

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

                disturbance.Json = json;

                model.CategoryEntities.Add(json);
            }

            return model;
        }

        public Core.Domain.Appendix.Appendix ToAppendix()
        {
            return new Core.Domain.Appendix.Appendix
            {
                Id = this.Id,
                CustomNumber = this.CustomNumber,
                Description = this.Description,
                Percentage = this.Percentage,
                StateId = this.StateId,
                Value = this.OfferingValue,
                OfferingNumber = this.OfferingNumber,
                OfferingDate = this.OfferingDate,
                NegotiationDate = this.NegotiationDate,
                NegotiationValue = this.NegotiationValue,
                ProtocolExists = this.ProtocolExists,
                OrderNumber = this.OrderNumber,
                OrderDate = this.OrderDate,
                Comment = this.Comment,
                SiteId = this.SiteId
            };
        }
    }
}