using System.Collections.Concurrent;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using Dalamud.Plugin.Services;
using HellionChat.Branding;
using Microsoft.Extensions.Logging;

namespace HellionChat.Infrastructure.Logging;

[ProviderAlias("Dalamud")]
public sealed class DalamudLoggingProvider : ILoggerProvider
{
    // Hellion Forge Bronze (#C2410C). Mixed into the bootstrap fingerprint.
    private const string HellionMarker = "HellionForgeBronzeC2410C";

    private readonly ConcurrentDictionary<string, DalamudLogger> _loggers = new(
        StringComparer.OrdinalIgnoreCase
    );

    private readonly IPluginLog _pluginLog;

    public DalamudLoggingProvider(IPluginLog pluginLog)
    {
        _pluginLog = pluginLog;
        EmitBootstrapBanner();
    }

    // One-shot per plugin load. Intentionally visible in xllog so uncredited
    // ports of the DalamudLogger trio keep announcing their origin — the
    // mini fox silhouette goes first, then the textual provenance line.
    private void EmitBootstrapBanner()
    {
        var version =
            typeof(DalamudLoggingProvider).Assembly.GetName().Version?.ToString() ?? "0.0.0";
        var fingerprint = ComputeFingerprint(version);

        foreach (var line in HellionForgeAscii.FoxMini.Split('\n'))
        {
            var trimmed = line.TrimEnd('\r');
            if (trimmed.Length > 0)
                _pluginLog.Information(trimmed);
        }

        _pluginLog.Information("by Julia Moon - Hellion Forge");
        _pluginLog.Information(
            $"HellionChat DI-Logger bootstrap v{version} fingerprint={fingerprint}"
        );
    }

    private static string ComputeFingerprint(string version)
    {
        var seed = Encoding.UTF8.GetBytes($"{HellionMarker}-{version}");
        var hash = SHA256.HashData(seed);
        var sb = new StringBuilder(8);
        for (var i = 0; i < 4; i++)
            sb.Append(hash[i].ToString("x2"));
        return sb.ToString();
    }

    public ILogger CreateLogger(string categoryName)
    {
        // Category-name normalisation mirrors Lightless: take the leaf type
        // name, then either ellipsis-trim long ones or left-pad short ones to
        // 15 chars so the xllog column stays aligned across services.
        var catName = categoryName.Split(".", StringSplitOptions.RemoveEmptyEntries).Last();
        if (catName.Length > 15)
            catName = string.Concat(
                catName.AsSpan(0, 6),
                "...",
                catName.AsSpan(catName.Length - 6, 6)
            );
        else
            catName = catName.PadLeft(15);

        return _loggers.GetOrAdd(catName, name => new DalamudLogger(name, _pluginLog));
    }

    public void Dispose()
    {
        _loggers.Clear();
        GC.SuppressFinalize(this);
    }
}
