using DysonNetwork.Sphere.Permission;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting;
namespace DysonNetwork.Sphere.Connection.WebReader;
/// 
/// Controller for web scraping and link preview services
/// 
[ApiController]
[Route("/scrap")]
[EnableRateLimiting("fixed")]
public class WebReaderController(WebReaderService reader, ILogger logger)
    : ControllerBase
{
    /// 
    /// Retrieves a preview for the provided URL
    /// 
    /// URL-encoded link to generate preview for
    /// Link preview data including title, description, and image
    [HttpGet("link")]
    public async Task> ScrapLink([FromQuery] string url)
    {
        if (string.IsNullOrEmpty(url))
        {
            return BadRequest(new { error = "URL parameter is required" });
        }
        try
        {
            // Ensure URL is properly decoded
            var decodedUrl = UrlDecoder.Decode(url);
            // Validate URL format
            if (!Uri.TryCreate(decodedUrl, UriKind.Absolute, out _))
            {
                return BadRequest(new { error = "Invalid URL format" });
            }
            var linkEmbed = await reader.GetLinkPreviewAsync(decodedUrl);
            return Ok(linkEmbed);
        }
        catch (WebReaderException ex)
        {
            logger.LogWarning(ex, "Error scraping link: {Url}", url);
            return BadRequest(new { error = ex.Message });
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Unexpected error scraping link: {Url}", url);
            return StatusCode(StatusCodes.Status500InternalServerError, 
                new { error = "An unexpected error occurred while processing the link" });
        }
    }
    /// 
    /// Force invalidates the cache for a specific URL
    /// 
    [HttpDelete("link/cache")]
    [Authorize]
    [RequiredPermission("maintenance", "cache.scrap")]
    public async Task InvalidateCache([FromQuery] string url)
    {
        if (string.IsNullOrEmpty(url))
        {
            return BadRequest(new { error = "URL parameter is required" });
        }
        await reader.InvalidateCacheForUrlAsync(url);
        return Ok(new { message = "Cache invalidated for URL" });
    }
    /// 
    /// Force invalidates all cached link previews
    /// 
    [HttpDelete("cache/all")]
    [Authorize]
    [RequiredPermission("maintenance", "cache.scrap")]
    public async Task InvalidateAllCache()
    {
        await reader.InvalidateAllCachedPreviewsAsync();
        return Ok(new { message = "All link preview caches invalidated" });
    }
}
/// 
/// Helper class for URL decoding
/// 
public static class UrlDecoder
{
    public static string Decode(string url)
    {
        // First check if URL is already decoded
        if (!url.Contains('%') && !url.Contains('+'))
        {   
            return url;
        }
        try
        {
            return System.Net.WebUtility.UrlDecode(url);
        }
        catch
        {
            // If decoding fails, return the original string
            return url;
        }
    }
}