using DysonNetwork.Shared.Proto;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace DysonNetwork.Sphere.WebReader;
[ApiController]
[Route("/api/feeds")]
public class WebFeedPublicController(
    AppDatabase db,
    WebFeedService webFeed
) : ControllerBase
{
    /// 
    /// Subscribe to a web feed
    /// 
    /// The ID of the feed to subscribe to
    /// Subscription details
    [HttpPost("{feedId:guid}/subscribe")]
    [Authorize]
    public async Task Subscribe(Guid feedId)
    {
        if (HttpContext.Items["CurrentUser"] is not Account currentUser)
            return Unauthorized();
        var accountId = Guid.Parse(currentUser.Id);
        // Check if feed exists
        var feed = await db.WebFeeds.FindAsync(feedId);
        if (feed == null)
            return NotFound("Feed not found");
        // Check if already subscribed
        var existingSubscription = await db.WebFeedSubscriptions
            .FirstOrDefaultAsync(s => s.FeedId == feedId && s.AccountId == accountId);
        if (existingSubscription != null)
            return Ok(existingSubscription);
        // Create new subscription
        var subscription = new WebFeedSubscription
        {
            FeedId = feedId,
            AccountId = accountId
        };
        db.WebFeedSubscriptions.Add(subscription);
        await db.SaveChangesAsync();
        return CreatedAtAction(nameof(GetSubscriptionStatus), new { feedId }, subscription);
    }
    /// 
    /// Unsubscribe from a web feed
    /// 
    /// The ID of the feed to unsubscribe from
    [HttpDelete("{feedId:guid}/subscribe")]
    [Authorize]
    public async Task Unsubscribe(Guid feedId)
    {
        if (HttpContext.Items["CurrentUser"] is not Account currentUser)
            return Unauthorized();
        var accountId = Guid.Parse(currentUser.Id);
        var subscription = await db.WebFeedSubscriptions
            .FirstOrDefaultAsync(s => s.FeedId == feedId && s.AccountId == accountId);
        if (subscription == null)
            return NoContent();
        db.WebFeedSubscriptions.Remove(subscription);
        await db.SaveChangesAsync();
        return NoContent();
    }
    /// 
    /// Get subscription status for the current user and a specific feed
    /// 
    /// The ID of the feed to check
    /// Subscription status
    [HttpGet("{feedId:guid}/subscription")]
    [Authorize]
    public async Task> GetSubscriptionStatus(Guid feedId)
    {
        if (HttpContext.Items["CurrentUser"] is not Account currentUser)
            return Unauthorized();
        var accountId = Guid.Parse(currentUser.Id);
        var subscription = await db.WebFeedSubscriptions
            .Where(s => s.FeedId == feedId && s.AccountId == accountId)
            .FirstOrDefaultAsync();
        if (subscription is null)
            return NotFound();
        return Ok(subscription);
    }
    /// 
    /// List all feeds the current user is subscribed to
    /// 
    /// List of subscribed feeds
    [HttpGet("subscribed")]
    [Authorize]
    public async Task> GetSubscribedFeeds(
        [FromQuery] int offset = 0,
        [FromQuery] int take = 20
    )
    {
        if (HttpContext.Items["CurrentUser"] is not Account currentUser)
            return Unauthorized();
        var accountId = Guid.Parse(currentUser.Id);
        var query = db.WebFeedSubscriptions
            .Where(s => s.AccountId == accountId)
            .Include(s => s.Feed)
            .ThenInclude(f => f.Publisher)
            .OrderByDescending(s => s.CreatedAt);
        var totalCount = await query.CountAsync();
        var subscriptions = await query
            .Select(q => q.Feed)
            .Skip(offset)
            .Take(take)
            .ToListAsync();
        Response.Headers["X-Total"] = totalCount.ToString();
        return Ok(subscriptions);
    }
    /// 
    /// Get articles from subscribed feeds
    /// 
    [HttpGet]
    [Authorize]
    public async Task> GetWebFeedArticles(
        [FromQuery] int offset = 0,
        [FromQuery] int take = 20
    )
    {
        if (HttpContext.Items["CurrentUser"] is not Account currentUser)
            return Unauthorized();
        var accountId = Guid.Parse(currentUser.Id);
        var subscribedFeedIds = await db.WebFeedSubscriptions
            .Where(s => s.AccountId == accountId)
            .Select(s => s.FeedId)
            .ToListAsync();
        var query = db.WebFeeds
            .Where(f => subscribedFeedIds.Contains(f.Id))
            .Include(f => f.Publisher)
            .OrderByDescending(f => f.CreatedAt);
        var totalCount = await query.CountAsync();
        var feeds = await query
            .Skip(offset)
            .Take(take)
            .ToListAsync();
        Response.Headers["X-Total"] = totalCount.ToString();
        return Ok(feeds);
    }
    /// 
    /// Get feed metadata by ID (public endpoint)
    /// 
    /// The ID of the feed
    /// Feed metadata
    [AllowAnonymous]
    [HttpGet("{feedId:guid}")]
    public async Task> GetFeedById(Guid feedId)
    {
        var feed = await webFeed.GetFeedAsync(feedId);
        if (feed == null)
            return NotFound();
        return Ok(feed);
    }
    /// 
    /// Get articles from a specific feed (public endpoint)
    /// 
    /// The ID of the feed
    /// Number of articles to skip
    /// Maximum number of articles to return
    /// List of articles from the feed
    [AllowAnonymous]
    [HttpGet("{feedId:guid}/articles")]
    public async Task> GetFeedArticles(
        [FromRoute] Guid feedId,
        [FromQuery] int offset = 0,
        [FromQuery] int take = 20
    )
    {
        // Check if feed exists
        var feedExists = await db.WebFeeds.AnyAsync(f => f.Id == feedId);
        if (!feedExists)
            return NotFound("Feed not found");
        var query = db.WebArticles
            .Where(a => a.FeedId == feedId)
            .OrderByDescending(a => a.CreatedAt)
            .Include(a => a.Feed)
            .ThenInclude(f => f.Publisher);
        var totalCount = await query.CountAsync();
        var articles = await query
            .Skip(offset)
            .Take(take)
            .ToListAsync();
        Response.Headers["X-Total"] = totalCount.ToString();
        return Ok(articles);
    }
    /// 
    /// Explore available web feeds
    /// 
    [HttpGet("explore")]
    [Authorize]
    public async Task> ExploreFeeds(
        [FromQuery] int offset = 0,
        [FromQuery] int take = 20,
        [FromQuery] string? query = null
    )
    {
        if (HttpContext.Items["CurrentUser"] is not Account currentUser)
            return Unauthorized();
        var accountId = Guid.Parse(currentUser.Id);
        var feedsQuery = db.WebFeeds
            .Include(f => f.Publisher)
            .OrderByDescending(f => f.CreatedAt)
            .AsQueryable();
        // Apply search filter if query is provided
        if (!string.IsNullOrWhiteSpace(query))
        {
            var searchTerm = $"%{query}%";
            feedsQuery = feedsQuery.Where(f =>
                EF.Functions.ILike(f.Title, searchTerm) ||
                (f.Description != null && EF.Functions.ILike(f.Description, searchTerm))
            );
        }
        var totalCount = await feedsQuery.CountAsync();
        var feeds = await feedsQuery
            .Skip(offset)
            .Take(take)
            .ToListAsync();
        Response.Headers["X-Total"] = totalCount.ToString();
        return Ok(feeds);
    }
}