using System;
using System.IO;
using System.Security.Cryptography;

namespace PolyTrader.Core.Security
{
    /// <summary>
    /// Löst den AES-Master-Key auf, mit dem <see cref="SecretProtection"/> Secrets at-rest
    /// verschlüsselt (D-5/D-10 aus dem Deploymentcenter-Umsetzungsplan).
    ///
    /// Reihenfolge: Umgebungsvariable, dann eine vorhandene Schlüsseldatei, sonst wird ein neuer
    /// erzeugt und geschrieben — das ist der Regelfall direkt nach <c>update-agent --action install</c>
    /// auf einem frischen System, wo niemand von Hand einen Schlüssel eintippt.
    ///
    /// **Die eine Regel, die nie verletzt werden darf:** Erzeugt wird AUSSCHLIESSLICH, wenn weder
    /// Variable noch Datei existieren. Ein versehentliches Überschreiben würde jedes bereits
    /// verschlüsselte Secret in der Datenbank unwiederbringlich unlesbar machen — der einzige
    /// wirklich unumkehrbare Fehler in diesem gesamten Bereich. Ein zweiter Aufruf (jeder weitere
    /// Programmstart) liest deshalb ausnahmslos die vorhandene Datei, statt neu zu erzeugen.
    /// </summary>
    public static class MasterKeyResolver
    {
        /// <param name="keyFilePath">Pfad der Schlüsseldatei (z.B. neben der Anwendung).</param>
        /// <param name="readEnvironmentVariable">Liest z.B. POLYTRADER_MASTER_KEY. Injizierbar für Tests.</param>
        /// <param name="onGenerated">Aufgerufen, wenn ein neuer Schlüssel erzeugt wurde (Pfad als Parameter).</param>
        /// <param name="onWarning">Aufgerufen bei einem nicht fatalen Problem (z.B. Dateirechte, Erzeugung fehlgeschlagen).</param>
        public static string? Resolve(
            string keyFilePath,
            Func<string?> readEnvironmentVariable,
            Action<string>? onGenerated = null,
            Action<string>? onWarning = null)
        {
            string? masterKey = readEnvironmentVariable();
            if (!string.IsNullOrWhiteSpace(masterKey))
            {
                return masterKey;
            }

            if (File.Exists(keyFilePath))
            {
                return File.ReadAllText(keyFilePath).Trim();
            }

            try
            {
                byte[] keyBytes = RandomNumberGenerator.GetBytes(32);   // 256-Bit-Schlüssel
                string generated = Convert.ToBase64String(keyBytes);

                File.WriteAllText(keyFilePath, generated);
                FilePermissions.RestrictToOwner(keyFilePath, onWarning);

                onGenerated?.Invoke(keyFilePath);
                return generated;
            }
            catch (Exception ex)
            {
                // Erzeugung darf den Start nie verhindern - ohne Master-Key laufen Secrets eben
                // unverschlüsselt weiter (wie bisher ohne POLYTRADER_MASTER_KEY), statt abzustürzen.
                onWarning?.Invoke($"Master-Key konnte nicht automatisch erzeugt werden: {ex.Message}.");
                return null;
            }
        }
    }
}
