using SharepointToolbox.Core.Models;

namespace SharepointToolbox.Core.Helpers;

/// <summary>
/// Maps SharePoint built-in permission level names to human-readable labels and risk levels.
/// Used by SimplifiedPermissionEntry and export services to translate raw role names
/// into plain-language descriptions that non-technical users can understand.
/// </summary>
public static class PermissionLevelMapping
{
    /// <summary>
    /// Result of looking up a SharePoint role name.
    /// </summary>
    public record MappingResult(string Label, RiskLevel RiskLevel);

    /// <summary>
    /// Known SharePoint built-in permission level mappings.
    /// Keys are case-insensitive via the dictionary comparer.
    /// </summary>
    private static readonly Dictionary<string, MappingResult> Mappings = new(StringComparer.OrdinalIgnoreCase)
    {
        // High risk — full administrative access
        ["Full Control"]                 = new("Full control (can manage everything)", RiskLevel.High),
        ["Site Collection Administrator"] = new("Site collection admin (full control)", RiskLevel.High),

        // Medium risk — can modify content
        ["Contribute"]       = new("Can edit files and list items", RiskLevel.Medium),
        ["Edit"]             = new("Can edit files, lists, and pages", RiskLevel.Medium),
        ["Design"]           = new("Can edit pages and use design tools", RiskLevel.Medium),
        ["Approve"]          = new("Can approve content and list items", RiskLevel.Medium),
        ["Manage Hierarchy"] = new("Can create sites and manage pages", RiskLevel.Medium),

        // Low risk — read access
        ["Read"]             = new("Can view files and pages", RiskLevel.Low),
        ["Restricted Read"]  = new("Can view pages only (no download)", RiskLevel.Low),

        // Read-only — most restricted
        ["View Only"]        = new("Can view files in browser only", RiskLevel.ReadOnly),
        ["Restricted View"]  = new("Restricted view access", RiskLevel.ReadOnly),
    };

    /// <summary>
    /// Gets the human-readable label and risk level for a SharePoint role name.
    /// Returns the mapped result for known roles; for unknown/custom roles,
    /// returns the raw name as-is with Medium risk level.
    /// </summary>
    public static MappingResult GetMapping(string roleName)
    {
        if (string.IsNullOrWhiteSpace(roleName))
            return new MappingResult(roleName, RiskLevel.Low);

        return Mappings.TryGetValue(roleName.Trim(), out var result)
            ? result
            : new MappingResult(roleName.Trim(), RiskLevel.Medium);
    }

    /// <summary>
    /// Resolves a semicolon-delimited PermissionLevels string into individual mapping results.
    /// This handles the PermissionEntry.PermissionLevels format (e.g. "Full Control; Contribute").
    /// </summary>
    public static IReadOnlyList<MappingResult> GetMappings(string permissionLevels)
    {
        if (string.IsNullOrWhiteSpace(permissionLevels))
            return Array.Empty<MappingResult>();

        return permissionLevels
            .Split(';', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
            .Select(GetMapping)
            .ToList();
    }

    /// <summary>
    /// Returns the highest (most dangerous) risk level from a semicolon-delimited permission levels string.
    /// Used for row-level color coding when an entry has multiple roles.
    /// </summary>
    public static RiskLevel GetHighestRisk(string permissionLevels)
    {
        var mappings = GetMappings(permissionLevels);
        if (mappings.Count == 0) return RiskLevel.Low;

        // High < Medium < Low < ReadOnly in enum order — Min gives highest risk
        return mappings.Min(m => m.RiskLevel);
    }

    /// <summary>
    /// Converts a semicolon-delimited PermissionLevels string into a simplified labels string.
    /// E.g. "Full Control; Contribute" becomes "Full control (can manage everything); Can edit files and list items"
    /// </summary>
    public static string GetSimplifiedLabels(string permissionLevels)
    {
        var mappings = GetMappings(permissionLevels);
        return string.Join("; ", mappings.Select(m => m.Label));
    }
}
