using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace MarcusLaw.OutlookAddin.Core.Security
{
    public sealed class StoredCredentials
    {
        [JsonPropertyName("username")]
        public string Username { get; set; } = string.Empty;

        [JsonPropertyName("apiKey")]
        public string ApiKey { get; set; } = string.Empty;
    }

    public sealed class DpapiCredentialStore
    {
        private const string EntropySeed = "MarcusLaw.OutlookAddin.v1";
        private static readonly byte[] Entropy = SHA256.Create().ComputeHash(Encoding.UTF8.GetBytes(EntropySeed));

        private readonly string _filePath;

        public DpapiCredentialStore()
            : this(DefaultPath())
        {
        }

        public DpapiCredentialStore(string filePath)
        {
            if (string.IsNullOrWhiteSpace(filePath)) throw new ArgumentException("filePath required", nameof(filePath));
            _filePath = filePath;
        }

        public string FilePath => _filePath;

        public void Save(string? username, string apiKey)
        {
            if (string.IsNullOrWhiteSpace(apiKey)) throw new ArgumentException("apiKey required", nameof(apiKey));

            var payload = JsonSerializer.SerializeToUtf8Bytes(new StoredCredentials
            {
                Username = username ?? string.Empty,
                ApiKey = apiKey
            });

            var encrypted = ProtectedData.Protect(payload, Entropy, DataProtectionScope.CurrentUser);

            var dir = Path.GetDirectoryName(_filePath);
            if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }

            File.WriteAllBytes(_filePath, encrypted);
        }

        public StoredCredentials? Load()
        {
            if (!File.Exists(_filePath)) return null;

            var encrypted = File.ReadAllBytes(_filePath);
            byte[] decrypted;
            try
            {
                decrypted = ProtectedData.Unprotect(encrypted, Entropy, DataProtectionScope.CurrentUser);
            }
            catch (CryptographicException)
            {
                return null;
            }

            try
            {
                return JsonSerializer.Deserialize<StoredCredentials>(decrypted);
            }
            catch (JsonException)
            {
                return null;
            }
        }

        public void Delete()
        {
            if (File.Exists(_filePath))
            {
                File.Delete(_filePath);
            }
        }

        private static string DefaultPath()
        {
            return Path.Combine(
                Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
                "MarcusLaw",
                "OutlookAddin",
                "creds.dat");
        }
    }
}
