using System.Text.Json.Serialization;

namespace ClawdDotNet.Core.Backup;

/// <summary>Wie mit Zugangsdaten in der Sicherung verfahren wird.</summary>
public enum SecretMode
{
    /// <summary>
    /// Zugangsdaten werden entfernt. Die Sicherung ist gefahrlos ablegbar, die
    /// Wiederherstellung aber unvollständig — Schlüssel und Passwörter müssen
    /// danach neu eingetragen werden.
    /// </summary>
    Exclude,

    /// <summary>
    /// Zugangsdaten werden mit einer Passphrase geschützt. Nur so überstehen sie
    /// einen Rechner- oder Benutzerwechsel.
    /// </summary>
    Passphrase
}

public sealed record BackupOptions
{
    public SecretMode Secrets { get; init; } = SecretMode.Exclude;

    /// <summary>Erforderlich bei <see cref="SecretMode.Passphrase"/>.</summary>
    public string? Passphrase { get; init; }

    /// <summary>Protokolle sind groß und selten nötig.</summary>
    public bool IncludeLogs { get; init; }

    /// <summary>Chatverläufe gehören zum Arbeitsstand, können aber umfangreich sein.</summary>
    public bool IncludeChatHistory { get; init; } = true;
}

public sealed record RestoreOptions
{
    public string? Passphrase { get; init; }

    /// <summary>Nur prüfen und berichten, nichts schreiben.</summary>
    public bool DryRun { get; init; }

    /// <summary>Vorhandene Dateien im Ziel überschreiben.</summary>
    public bool Overwrite { get; init; }
}

public sealed record BackupEntry(
    [property: JsonPropertyName("path")] string Path,
    [property: JsonPropertyName("size")] long Size,
    [property: JsonPropertyName("sha256")] string Sha256);

public sealed record BackupManifest
{
    /// <summary>Erlaubt es späteren Fassungen, ältere Sicherungen zu erkennen.</summary>
    [JsonPropertyName("formatVersion")]
    public int FormatVersion { get; init; } = 1;

    [JsonPropertyName("createdAt")]
    public DateTime CreatedAt { get; init; }

    [JsonPropertyName("instanceId")]
    public string InstanceId { get; init; } = "";

    [JsonPropertyName("instanceName")]
    public string InstanceName { get; init; } = "";

    [JsonPropertyName("secrets")]
    public string Secrets { get; init; } = nameof(SecretMode.Exclude);

    /// <summary>Wie viele Zugangsdaten enthalten bzw. entfernt wurden.</summary>
    [JsonPropertyName("secretCount")]
    public int SecretCount { get; init; }

    [JsonPropertyName("files")]
    public List<BackupEntry> Files { get; init; } = new();

    [JsonIgnore]
    public bool HasSecrets => Secrets == nameof(SecretMode.Passphrase);
}

public sealed record BackupResult(string ZipPath, BackupManifest Manifest, long SizeBytes);

public sealed record RestoreResult(
    IReadOnlyList<string> Written,
    IReadOnlyList<string> Skipped,
    IReadOnlyList<string> WouldOverwrite)
{
    public bool HasConflicts => WouldOverwrite.Count > 0;
}

public sealed class BackupException(string message, Exception? inner = null)
    : Exception(message, inner);
