using System.IO;
using System.Text;
using System.Text.Json;
using SharepointToolbox.Core.Models;

namespace SharepointToolbox.Infrastructure.Persistence;

public class TemplateRepository
{
    private readonly string _directoryPath;
    private readonly SemaphoreSlim _writeLock = new(1, 1);
    private static readonly JsonSerializerOptions JsonOptions = new()
    {
        WriteIndented = true,
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        PropertyNameCaseInsensitive = true,
    };

    public TemplateRepository(string directoryPath)
    {
        _directoryPath = directoryPath;
    }

    public async Task<List<SiteTemplate>> GetAllAsync()
    {
        if (!Directory.Exists(_directoryPath))
            return new List<SiteTemplate>();

        var templates = new List<SiteTemplate>();
        foreach (var file in Directory.GetFiles(_directoryPath, "*.json"))
        {
            try
            {
                var json = await File.ReadAllTextAsync(file, Encoding.UTF8);
                var template = JsonSerializer.Deserialize<SiteTemplate>(json, JsonOptions);
                if (template != null)
                    templates.Add(template);
            }
            catch (JsonException)
            {
                // Skip corrupted template files
            }
        }
        return templates.OrderByDescending(t => t.CapturedAt).ToList();
    }

    public async Task<SiteTemplate?> GetByIdAsync(string id)
    {
        var filePath = GetFilePath(id);
        if (!File.Exists(filePath))
            return null;

        var json = await File.ReadAllTextAsync(filePath, Encoding.UTF8);
        return JsonSerializer.Deserialize<SiteTemplate>(json, JsonOptions);
    }

    public async Task SaveAsync(SiteTemplate template)
    {
        await _writeLock.WaitAsync();
        try
        {
            if (!Directory.Exists(_directoryPath))
                Directory.CreateDirectory(_directoryPath);

            var json = JsonSerializer.Serialize(template, JsonOptions);
            var filePath = GetFilePath(template.Id);
            var tmpPath = filePath + ".tmp";

            await File.WriteAllTextAsync(tmpPath, json, Encoding.UTF8);

            // Validate round-trip before replacing
            JsonDocument.Parse(await File.ReadAllTextAsync(tmpPath, Encoding.UTF8)).Dispose();

            File.Move(tmpPath, filePath, overwrite: true);
        }
        finally
        {
            _writeLock.Release();
        }
    }

    public Task DeleteAsync(string id)
    {
        var filePath = GetFilePath(id);
        if (File.Exists(filePath))
            File.Delete(filePath);
        return Task.CompletedTask;
    }

    public async Task RenameAsync(string id, string newName)
    {
        var template = await GetByIdAsync(id);
        if (template == null)
            throw new InvalidOperationException($"Template not found: {id}");

        template.Name = newName;
        await SaveAsync(template);
    }

    private string GetFilePath(string id) => Path.Combine(_directoryPath, $"{id}.json");
}
