using System.Collections.Concurrent;

namespace Inspectron.Epson.Templates.Storage;

public class FileTemplateStorage : ITemplateStorage
{
    private readonly string _basePath;
    private readonly string _templateExtension;
    private readonly ConcurrentDictionary<string, string> _cache = new();

    public FileTemplateStorage(string basePath, string templateExtension = ".template")
    {
        _basePath = Path.GetFullPath(basePath);
        _templateExtension = templateExtension;

        if (!Directory.Exists(_basePath))
        {
            Directory.CreateDirectory(_basePath);
        }
    }

    public string? Load(string templatePath)
    {
        var normalizedPath = NormalizePath(templatePath);

        if (_cache.TryGetValue(normalizedPath, out var cached))
        {
            return cached;
        }

        var fullPath = GetFullPath(normalizedPath);
        if (!File.Exists(fullPath))
        {
            return null;
        }

        var content = File.ReadAllText(fullPath);
        _cache[normalizedPath] = content;
        return content;
    }

    public bool Exists(string templatePath)
    {
        var normalizedPath = NormalizePath(templatePath);
        var fullPath = GetFullPath(normalizedPath);
        return File.Exists(fullPath);
    }

    public void Reload()
    {
        _cache.Clear();
    }

    public IEnumerable<string> ListTemplates()
    {
        if (!Directory.Exists(_basePath))
        {
            yield break;
        }

        var files = Directory.GetFiles(_basePath, $"*{_templateExtension}", SearchOption.AllDirectories);
        foreach (var file in files)
        {
            var relativePath = Path.GetRelativePath(_basePath, file);
            yield return relativePath.Replace('\\', '/');
        }
    }

    private string NormalizePath(string path)
    {
        // Ensure the path has the correct extension
        if (!path.EndsWith(_templateExtension, StringComparison.OrdinalIgnoreCase))
        {
            path += _templateExtension;
        }

        // Normalize path separators
        return path.Replace('\\', '/');
    }

    private string GetFullPath(string normalizedPath)
    {
        // Security: prevent directory traversal
        var fullPath = Path.GetFullPath(Path.Combine(_basePath, normalizedPath));
        if (!fullPath.StartsWith(_basePath, StringComparison.OrdinalIgnoreCase))
        {
            throw new InvalidOperationException($"Invalid template path: {normalizedPath}");
        }
        return fullPath;
    }
}
