using PowderCoating.Core.Entities;
using PowderCoating.Shared.Constants;

namespace PowderCoating.Web.Controllers;

/// <summary>Risk bucket for a tenant company, derived from its health score.</summary>
public enum ChurnRisk { Healthy, AtRisk, Critical, NeverActivated }

/// <summary>
/// Shared health-score logic used by both <see cref="CompanyHealthController"/> (dashboard)
/// and <see cref="CompaniesController"/> (list + detail badges).
/// </summary>
public static class CompanyHealthHelper
{
    /// <summary>
    /// Computes a 0–100 health score and a list of human-readable risk signals for a single
    /// company based on its subscription status, login recency, and job activity.
    /// See <see cref="CompanyHealthController"/> XML doc for scoring rules.
    /// </summary>
    public static (int Score, List<string> Signals) ComputeHealth(
        Company c, int daysSinceLogin, int j30, int j90, int totalJobs, DateTime now)
    {
        var score = 100;
        var signals = new List<string>();

        if (!c.IsActive)
        {
            signals.Add("Account disabled");
            return (0, signals);
        }

        if (!c.IsComped && c.SubscriptionEndDate.HasValue)
        {
            var daysUntil = (int)(c.SubscriptionEndDate.Value.Date - now.Date).TotalDays;
            if (daysUntil < -AppConstants.SubscriptionConstants.GracePeriodDays)
            {
                score -= 50;
                signals.Add("Subscription expired");
            }
            else if (daysUntil < 0)
            {
                score -= 30;
                signals.Add("In grace period");
            }
            else if (daysUntil <= 7)
            {
                score -= 20;
                signals.Add($"Expires in {daysUntil}d");
            }
            else if (daysUntil <= 14)
            {
                score -= 10;
                signals.Add($"Expires in {daysUntil}d");
            }
        }

        if (daysSinceLogin == -1)
        {
            score -= 30;
            signals.Add("Never logged in");
        }
        else if (daysSinceLogin >= 90)
        {
            score -= 30;
            signals.Add($"No login {daysSinceLogin}d");
        }
        else if (daysSinceLogin >= 60)
        {
            score -= 20;
            signals.Add($"No login {daysSinceLogin}d");
        }
        else if (daysSinceLogin >= 30)
        {
            score -= 10;
            signals.Add($"No login {daysSinceLogin}d");
        }

        if (totalJobs == 0)
        {
            score -= 20;
            signals.Add("No jobs ever");
        }
        else if (j90 == 0)
        {
            score -= 10;
            signals.Add("No jobs in 90d");
        }
        else if (j30 == 0)
        {
            score -= 5;
            signals.Add("No jobs in 30d");
        }

        return (Math.Max(0, score), signals);
    }

    /// <summary>
    /// Derives a <see cref="ChurnRisk"/> bucket from a pre-computed score and activity flags.
    /// </summary>
    public static ChurnRisk ToRiskLevel(int score, bool neverActivated) =>
        neverActivated            ? ChurnRisk.NeverActivated
        : score >= 75             ? ChurnRisk.Healthy
        : score >= 45             ? ChurnRisk.AtRisk
        :                           ChurnRisk.Critical;
}
