using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using eSuite.Core.Sequences;

namespace e_suite.API.Common.models.@base;

public abstract class SequenceBase : IValidatableObject
{
    private static readonly Regex YearPlaceholderExpression =
        new(@"\{(YY|YYYY)\}", RegexOptions.Compiled | RegexOptions.CultureInvariant);

    private static readonly Regex MonthPlaceholderExpression =
        new(@"\{MM\}", RegexOptions.Compiled | RegexOptions.CultureInvariant);

    private static readonly Regex DayPlaceholderExpression =
        new(@"\{DD\}", RegexOptions.Compiled | RegexOptions.CultureInvariant);

    private static readonly Regex NumericPlaceholderExpression =
        new(@"\[0+\]", RegexOptions.Compiled | RegexOptions.CultureInvariant);

    [JsonPropertyName("name")]
    [Required]
    [DefaultValue("Sequence name")]
    public string Name { get; set; } = string.Empty;

    [JsonPropertyName("seed")]
    [Required]
    [DefaultValue(1)]
    public long Seed { get; set; }

    [JsonPropertyName("increment")]
    [Required]
    [DefaultValue(1)]
    public long Increment { get; set; }

    [JsonPropertyName("pattern")]
    [Required]
    [DefaultValue("[0]")]
    public string Pattern { get; set; } = "[0]";

    [JsonPropertyName("rolloverType")]
    [Required]
    [DefaultValue(Rollover.Continuous)]
    public Rollover RolloverType { get; set; }

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (RolloverType == Rollover.Day && !DayPlaceholderExpression.IsMatch(Pattern))
        {
            yield return new ValidationResult("When the rollover type is set to 'Daily', then the pattern must include either a {DD} placeholder", new string[] { nameof(Pattern) });
        }

        if (RolloverType == Rollover.Month && !MonthPlaceholderExpression.IsMatch(Pattern))
        {
            yield return new ValidationResult("When the rollover type is set to 'Monthly', then the pattern must include either a {MM} placeholder", new string[] { nameof(Pattern) });
        }

        if (RolloverType == Rollover.Year && !YearPlaceholderExpression.IsMatch(Pattern))
        {
            yield return new ValidationResult("When the rollover type is set to 'Annual', then the pattern must include either a {YY} or {YYYY} placeholder", new string[] { nameof(Pattern) });
        }

        if (!NumericPlaceholderExpression.IsMatch(Pattern))
        {
            yield return new ValidationResult("At minimum all patterns must contain one numeric value (i.e. [0])", new string[] { nameof(Pattern) });
        }

        if (Increment == 0)
        {
            yield return new ValidationResult("Increment can not be 0", new string[] { nameof(Increment) });
        }
    }
}