using System;

namespace XLAB
{
    public sealed class GroupOption
    {
        public string Key { get; set; }

        public string Title { get; set; }

        public override string ToString()
        {
            return Title ?? string.Empty;
        }
    }

    public sealed class CustomerReference
    {
        public int CustomerId { get; set; }

        public string CustomerName { get; set; }

        public override string ToString()
        {
            return CustomerName ?? string.Empty;
        }
    }

    public sealed class PsvDocumentSummary : ObservableObject
    {
        private DateTime? _acceptedOn;
        private string _customerName;
        private int? _customerId;
        private string _departmentName;
        private string _documentKey;
        private string _documentNumber;
        private int _failedCount;
        private bool _isDraft;
        private int _issuedCount;
        private DateTime? _issuedOn;
        private int _itemCount;
        private int _passedCount;
        private string _serialNumbersText;

        public DateTime? AcceptedOn
        {
            get { return _acceptedOn; }
            set
            {
                if (SetProperty(ref _acceptedOn, value))
                {
                    OnPropertyChanged("AcceptedMonthGroup");
                    RaiseOpenDocumentTimelinePropertiesChanged();
                }
            }
        }

        public string AcceptedMonthGroup
        {
            get { return AcceptedOn.HasValue ? AcceptedOn.Value.ToString("yyyy-MM") : "Без даты"; }
        }

        public string CustomerName
        {
            get { return _customerName; }
            set { SetProperty(ref _customerName, value); }
        }

        public int? CustomerId
        {
            get { return _customerId; }
            set { SetProperty(ref _customerId, value); }
        }

        public string DepartmentName
        {
            get { return _departmentName; }
            set { SetProperty(ref _departmentName, value); }
        }

        public string DocumentKey
        {
            get { return _documentKey; }
            set { SetProperty(ref _documentKey, value); }
        }

        public string DocumentNumber
        {
            get { return _documentNumber; }
            set { SetProperty(ref _documentNumber, value); }
        }

        public string SerialNumbersText
        {
            get { return _serialNumbersText; }
            set { SetProperty(ref _serialNumbersText, value); }
        }

        public int FailedCount
        {
            get { return _failedCount; }
            set { SetProperty(ref _failedCount, value); }
        }

        public bool IsDraft
        {
            get { return _isDraft; }
            set { SetProperty(ref _isDraft, value); }
        }

        public int IssuedCount
        {
            get { return _issuedCount; }
            set { SetProperty(ref _issuedCount, value); }
        }

        public DateTime? IssuedOn
        {
            get { return _issuedOn; }
            set
            {
                if (SetProperty(ref _issuedOn, value))
                {
                    RaiseOpenDocumentTimelinePropertiesChanged();
                }
            }
        }

        public int ItemCount
        {
            get { return _itemCount; }
            set { SetProperty(ref _itemCount, value); }
        }

        public int PassedCount
        {
            get { return _passedCount; }
            set { SetProperty(ref _passedCount, value); }
        }

        public DateTime? DueOn
        {
            get { return AcceptedOn.HasValue ? AcceptedOn.Value.Date.AddDays(30) : (DateTime?)null; }
        }

        public string TimelineDisplay
        {
            get
            {
                if (IssuedOn.HasValue)
                {
                    return string.Format("Выдача: {0:d}", IssuedOn.Value);
                }

                return DueOn.HasValue
                    ? string.Format("Срок: {0:d}", DueOn.Value)
                    : string.Empty;
            }
        }

        public bool IsOpenDocumentOverdue
        {
            get
            {
                return !IssuedOn.HasValue
                       && DueOn.HasValue
                       && DateTime.Today.Date >= DueOn.Value.Date;
            }
        }

        public bool IsOpenDocumentAtTwentyDays
        {
            get
            {
                return !IssuedOn.HasValue
                       && AcceptedOn.HasValue
                       && !IsOpenDocumentOverdue
                       && (DateTime.Today.Date - AcceptedOn.Value.Date).TotalDays >= 20;
            }
        }

        public bool IsOpenDocumentAtTenDays
        {
            get
            {
                return !IssuedOn.HasValue
                       && AcceptedOn.HasValue
                       && !IsOpenDocumentOverdue
                       && !IsOpenDocumentAtTwentyDays
                       && (DateTime.Today.Date - AcceptedOn.Value.Date).TotalDays >= 10;
            }
        }

        private void RaiseOpenDocumentTimelinePropertiesChanged()
        {
            OnPropertyChanged("DueOn");
            OnPropertyChanged("TimelineDisplay");
            OnPropertyChanged("IsOpenDocumentOverdue");
            OnPropertyChanged("IsOpenDocumentAtTwentyDays");
            OnPropertyChanged("IsOpenDocumentAtTenDays");
        }
    }

    public sealed class PsvDocumentLine : ObservableObject
    {
        private bool _isBatchSelected;

        public int CardId { get; set; }

        public int InstrumentId { get; set; }

        public int TypeSizeId { get; set; }

        public string SerialNumber { get; set; }

        public string InventoryNumber { get; set; }

        public string CustomerName { get; set; }

        public string InstrumentType { get; set; }

        public string InstrumentName { get; set; }

        public string MeasurementArea { get; set; }

        public string RangeText { get; set; }

        public string RegistryNumber { get; set; }

        public string AccuracyText { get; set; }

        public string VerificationType { get; set; }

        public int PeriodMonths { get; set; }

        public DateTime? AcceptedOn { get; set; }

        public DateTime? IssuedOn { get; set; }

        public bool? IsPassed { get; set; }

        public DateTime? VerificationPerformedOn { get; set; }

        public int? VerifierId { get; set; }

        public string VerifierName { get; set; }

        public string StickerNumber { get; set; }

        public int? VerificationDocumentFormId { get; set; }

        public int? VerificationDocumentLinkTypeId { get; set; }

        public string VerificationDocumentNumber { get; set; }

        public DateTime? VerificationDocumentDate { get; set; }

        public string RejectionReason { get; set; }

        public string Notes { get; set; }

        public bool IsPendingInsert { get; set; }

        public bool IsBatchSelected
        {
            get { return _isBatchSelected; }
            set { SetProperty(ref _isBatchSelected, value); }
        }

        public string DuplicateKey
        {
            get
            {
                return BuildDuplicateKey(InstrumentType, RangeText, RegistryNumber, SerialNumber);
            }
        }

        public string OpenDocumentConflictKey
        {
            get
            {
                return BuildOpenDocumentConflictKey(TypeSizeId, SerialNumber);
            }
        }

        public string ResultText
        {
            get
            {
                if (!IsPassed.HasValue)
                {
                    return string.Empty;
                }

                return IsPassed.Value ? "Годен" : "Не годен";
            }
        }

        public string VerificationDateDisplay
        {
            get
            {
                var verificationDate = VerificationPerformedOn ?? VerificationDocumentDate;
                return verificationDate.HasValue ? verificationDate.Value.ToString("d") : string.Empty;
            }
        }

        public string VerificationDocumentDisplay
        {
            get
            {
                if (string.IsNullOrWhiteSpace(VerificationDocumentNumber))
                {
                    return VerificationDocumentDate.HasValue ? VerificationDocumentDate.Value.ToString("d") : string.Empty;
                }

                if (!VerificationDocumentDate.HasValue)
                {
                    return VerificationDocumentNumber;
                }

                return string.Format("{0} от {1:d}", VerificationDocumentNumber, VerificationDocumentDate.Value);
            }
        }

        public static string BuildDuplicateKey(string instrumentType, string rangeText, string registryNumber, string serialNumber)
        {
            return string.Join("|",
                NormalizeKeyPart(instrumentType),
                NormalizeKeyPart(rangeText),
                NormalizeKeyPart(registryNumber),
                NormalizeKeyPart(serialNumber));
        }

        public static string BuildOpenDocumentConflictKey(int typeSizeId, string serialNumber)
        {
            return string.Format("{0}|{1}", typeSizeId, NormalizeKeyPart(serialNumber));
        }

        private static string NormalizeKeyPart(string value)
        {
            return string.IsNullOrWhiteSpace(value) ? string.Empty : value.Trim().ToUpperInvariant();
        }
    }

    public sealed class PsvDocumentGroupSummary : ObservableObject
    {
        private bool _isBatchSelected;

        public string InstrumentType { get; set; }

        public string RangeText { get; set; }

        public string RegistryNumber { get; set; }

        public string SerialNumbersText { get; set; }

        public int InVerificationCount { get; set; }

        public int VerifiedCount { get; set; }

        public int GoodCount { get; set; }

        public int RejectedCount { get; set; }

        public bool IsBatchSelected
        {
            get { return _isBatchSelected; }
            set { SetProperty(ref _isBatchSelected, value); }
        }

        public bool Matches(PsvDocumentLine line)
        {
            return line != null
                   && string.Equals(InstrumentType ?? string.Empty, line.InstrumentType ?? string.Empty, StringComparison.OrdinalIgnoreCase)
                   && string.Equals(RangeText ?? string.Empty, line.RangeText ?? string.Empty, StringComparison.OrdinalIgnoreCase)
                   && string.Equals(RegistryNumber ?? string.Empty, line.RegistryNumber ?? string.Empty, StringComparison.OrdinalIgnoreCase);
        }
    }

    public sealed class AvailableInstrumentItem : ObservableObject
    {
        private bool _isSelected;

        public string AccuracyText { get; set; }

        public string CustomerName { get; set; }

        public bool HasTemplate { get; set; }

        public int InstrumentId { get; set; }

        public string InstrumentName { get; set; }

        public string InstrumentType { get; set; }

        public string InventoryNumber { get; set; }

        public bool IsSelected
        {
            get { return _isSelected; }
            set { SetProperty(ref _isSelected, value); }
        }

        public DateTime? LastAcceptedOn { get; set; }

        public string LastDocumentNumber { get; set; }

        public string MeasurementArea { get; set; }

        public string RangeText { get; set; }

        public string RegistryNumber { get; set; }

        public string SerialNumber { get; set; }

        public string TemplateSource { get; set; }

        public int TypeSizeId { get; set; }
    }

    public sealed class PersonReference
    {
        public int PersonId { get; set; }

        public string FullName { get; set; }

        public override string ToString()
        {
            return FullName ?? string.Empty;
        }
    }

    public sealed class SpnmtpDirectoryItem
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public string SpecialName { get; set; }
    }

    internal sealed class SpnmtpDeleteResult
    {
        public bool IsDeleted { get; set; }

        public string WarningMessage { get; set; }
    }

    public sealed class SpoiDirectoryItem
    {
        public int Id { get; set; }

        public string Code { get; set; }

        public string Name { get; set; }
    }

    internal sealed class SpoiDeleteResult
    {
        public bool IsDeleted { get; set; }

        public string WarningMessage { get; set; }
    }

    internal static class SpoiDirectoryRules
    {
        public const int CodeMaxLength = 3;

        public const int NameMaxLength = 80;
    }

    internal static class SpnmtpDirectoryRules
    {
        public const int NameMaxLength = 150;

        public const int SpecialNameMaxLength = 150;
    }

    public sealed class DocumentFormReference
    {
        public int DocumentFormId { get; set; }

        public int LinkTypeId { get; set; }

        public string DocumentKindName { get; set; }

        public string DocumentFormName { get; set; }

        public override string ToString()
        {
            return DocumentFormName ?? string.Empty;
        }
    }

    public sealed class DocumentEditorResult
    {
        public string DocumentNumber { get; set; }

        public DateTime AcceptedOn { get; set; }

        public DateTime? IssuedOn { get; set; }

        public int? CustomerId { get; set; }
    }

    public sealed class InstrumentTypeSelectionResult
    {
        public AvailableInstrumentItem TypeItem { get; set; }

        public string SerialNumber { get; set; }
    }

    public sealed class VerificationEditSeed
    {
        public DocumentFormReference DocumentForm { get; set; }

        public bool IsPassed { get; set; }

        public string RejectionReason { get; set; }

        public string StickerNumber { get; set; }

        public DateTime? VerificationDate { get; set; }

        public string VerificationDocumentNumber { get; set; }

        public int? VerifierId { get; set; }
    }

    public sealed class CloneVerificationSeed
    {
        public string SourceSerialNumber { get; set; }

        public string VerificationSummary { get; set; }
    }

    public sealed class VerificationEditResult
    {
        public int DocumentFormId { get; set; }

        public int DocumentLinkTypeId { get; set; }

        public bool IsPassed { get; set; }

        public string RejectionReason { get; set; }

        public string StickerNumber { get; set; }

        public DateTime VerificationDate { get; set; }

        public string VerificationDocumentNumber { get; set; }

        public int VerifierId { get; set; }

        public string VerifierName { get; set; }
    }

    internal sealed class OpenDocumentConflictInfo
    {
        public string DocumentNumber { get; set; }

        public int TypeSizeId { get; set; }

        public string SerialNumber { get; set; }

        public string OpenDocumentConflictKey
        {
            get
            {
                return PsvDocumentLine.BuildOpenDocumentConflictKey(TypeSizeId, SerialNumber);
            }
        }
    }

    internal sealed class DocumentDeleteResult
    {
        public int DeletedEkzMkFctvlCount { get; set; }

        public int DeletedEkzMkCount { get; set; }

        public int DeletedDmsCount { get; set; }
    }

    internal sealed class DocumentGroupDeleteResult
    {
        public int DeletedEkzMkFctvlCount { get; set; }

        public int DeletedEkzMkCount { get; set; }

        public int DeletedDmsCount { get; set; }
    }

    internal sealed class DocumentSaveResult
    {
        public string DocumentNumber { get; set; }

        public int InsertedEkzMkCount { get; set; }

        public int SkippedDuplicateCount { get; set; }

        public int SkippedWithoutTemplateCount { get; set; }

        public int UpdatedEkzMkCount { get; set; }
    }

    internal sealed class EkzMkTemplate
    {
        public string Dpznmp { get; set; }

        public string Hrtcmp { get; set; }

        public int? IdEkzetl { get; set; }

        public int IdFrpd { get; set; }

        public int? IdGrsi { get; set; }

        public int? IdKsp { get; set; }

        public int? IdKsprl { get; set; }

        public int? IdPrsn { get; set; }

        public int? IdPrsnpr { get; set; }

        public int? IdPrsnsd { get; set; }

        public int? IdPrsnvd { get; set; }

        public int? IdPrsnvy { get; set; }

        public int? IdSpkmmk { get; set; }

        public int? IdSpmpob { get; set; }

        public int? IdSpmu { get; set; }

        public int? IdSpssmp { get; set; }

        public int? IdSptsmp { get; set; }

        public int? IdSpvdkl { get; set; }

        public int? IdSpvdsbmk { get; set; }

        public int? IdSpvdmc { get; set; }

        public decimal? NcSrmk { get; set; }

        public decimal? Nrvrmmp { get; set; }

        public decimal? Nrvrmndmp { get; set; }

        public int Prmk { get; set; }

        public string SourceDescription { get; set; }

        public decimal? Stmk { get; set; }

        public decimal? Stmkdp { get; set; }

        public decimal? Vrmkfk { get; set; }
    }
}
