namespace PlotLine.Models;

public static class FeatureRequestStatuses
{
    public const string New = "New";
    public const string NeedsDetail = "Needs Detail";
    public const string UnderReview = "Under Review";
    public const string Candidate = "Candidate";
    public const string Planned = "Planned";
    public const string InProgress = "In Progress";
    public const string Shipped = "Shipped";
    public const string NotPlanned = "Not Planned";

    public static IReadOnlyList<string> All { get; } =
    [
        New,
        NeedsDetail,
        UnderReview,
        Candidate,
        Planned,
        InProgress,
        Shipped,
        NotPlanned
    ];

    public static bool IsValid(string? status) => All.Contains(status ?? string.Empty, StringComparer.OrdinalIgnoreCase);

    public static bool IsOpen(string? status) => !string.Equals(status, Shipped, StringComparison.OrdinalIgnoreCase)
        && !string.Equals(status, NotPlanned, StringComparison.OrdinalIgnoreCase);

    public static string Explanation(string? status) => status switch
    {
        New => "Your suggestion has been received and is waiting for review.",
        NeedsDetail => "We need a little more information before we can evaluate this suggestion.",
        UnderReview => "We are currently evaluating this idea.",
        Candidate => "This suggestion is being considered for a future release.",
        Planned => "This suggestion has been accepted and is planned for development.",
        InProgress => "Work has started on this feature.",
        Shipped => "This feature has been completed and released.",
        NotPlanned => "This suggestion does not currently fit PlotDirector's roadmap.",
        _ => "This suggestion is being reviewed."
    };
}

public static class FeatureRequestSortOptions
{
    public const string LatestActivity = "LatestActivity";
    public const string NewestFirst = "NewestFirst";
    public const string OldestFirst = "OldestFirst";

    public static IReadOnlyList<(string Value, string Label)> All { get; } =
    [
        (LatestActivity, "Latest activity"),
        (NewestFirst, "Newest first"),
        (OldestFirst, "Oldest first")
    ];

    public static bool IsValid(string? sort) => All.Any(option => string.Equals(option.Value, sort, StringComparison.OrdinalIgnoreCase));
}

public static class FeatureRequestOptions
{
    public static IReadOnlyList<string> AppAreas { get; } =
    [
        "Timeline",
        "Characters",
        "Locations",
        "Assets",
        "Plot Lines",
        "Continuity",
        "Writing Schedule",
        "Word Companion",
        "Import / Export",
        "Billing / Account",
        "Other"
    ];

    public static IReadOnlyList<string> ImportanceOptions { get; } =
    [
        "Nice to have",
        "Would save me time",
        "Blocking my workflow"
    ];
}

public sealed class FeatureRequest
{
    public int FeatureRequestID { get; set; }
    public int UserID { get; set; }
    public string? UserEmail { get; set; }
    public string? UserDisplayName { get; set; }
    public string Title { get; set; } = string.Empty;
    public string Description { get; set; } = string.Empty;
    public string? AppArea { get; set; }
    public string? Importance { get; set; }
    public string Status { get; set; } = FeatureRequestStatuses.New;
    public bool IsPublicCandidate { get; set; }
    public string? AdminNotes { get; set; }
    public DateTime CreatedUtc { get; set; }
    public DateTime UpdatedUtc { get; set; }
    public DateTime? ClosedUtc { get; set; }
    public DateTime? ShippedUtc { get; set; }
    public DateTime? LatestActivityUtc { get; set; }
    public bool? LatestMessageIsAdmin { get; set; }
    public string? LatestMessagePreview { get; set; }
    public int MessageCount { get; set; }
    public DateTime? UserLastViewedUtc { get; set; }
    public DateTime? UserAttentionUtc { get; set; }
    public bool UserNeedsAttention { get; set; }

    public bool IsOpen => FeatureRequestStatuses.IsOpen(Status);
    public string StatusExplanation => FeatureRequestStatuses.Explanation(Status);
    public string ConversationState
    {
        get
        {
            if ((LatestMessageIsAdmin is null || LatestMessageIsAdmin == false) && IsOpen)
            {
                return FeatureRequestConversationStates.WaitingForAdminReply;
            }

            if (LatestMessageIsAdmin == true && string.Equals(Status, FeatureRequestStatuses.NeedsDetail, StringComparison.OrdinalIgnoreCase))
            {
                return FeatureRequestConversationStates.WaitingForUserReply;
            }

            return FeatureRequestConversationStates.NoActionNeeded;
        }
    }
}

public sealed class FeatureRequestRoadmapSection
{
    public string Heading { get; set; } = string.Empty;
    public string Status { get; set; } = string.Empty;
    public IReadOnlyList<FeatureRequest> Requests { get; set; } = [];
}

public static class FeatureRequestConversationStates
{
    public const string WaitingForAdminReply = "Waiting for Admin Reply";
    public const string WaitingForUserReply = "Waiting for User Reply";
    public const string NoActionNeeded = "Up to date";
}

public sealed class FeatureRequestAdminSummary
{
    public IReadOnlyList<FeatureRequestStatusSummary> Statuses { get; set; } = [];
    public int TotalOpenRequests { get; set; }
    public int AwaitingAdminReply { get; set; }
    public int AwaitingUserReply { get; set; }
}

public sealed class FeatureRequestStatusSummary
{
    public string Status { get; set; } = string.Empty;
    public int Count { get; set; }
}

public sealed class FeatureRequestMessage
{
    public int FeatureRequestMessageID { get; set; }
    public int FeatureRequestID { get; set; }
    public int? UserID { get; set; }
    public string? UserEmail { get; set; }
    public string? UserDisplayName { get; set; }
    public bool IsAdmin { get; set; }
    public string MessageBody { get; set; } = string.Empty;
    public DateTime CreatedUtc { get; set; }
}
