using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting;
using Meezi.Core.Interfaces;
using Meezi.Shared;

namespace Meezi.API.Controllers;

/// <summary>Public website endpoints — blog, comments, demo requests.</summary>
[AllowAnonymous]
[ApiController]
[Route("api/public/website")]
public class WebsiteContentController(IWebsiteService website) : ControllerBase
{
    // ── Blog posts ────────────────────────────────────────────────────────

    [HttpGet("posts")]
    public async Task<IActionResult> GetPosts(
        [FromQuery] string locale = "fa",
        [FromQuery] int page = 1,
        [FromQuery] int limit = 12,
        CancellationToken ct = default)
    {
        limit = Math.Clamp(limit, 1, 50);
        page  = Math.Max(page, 1);
        var (posts, total) = await website.GetPostsAsync(locale, page, limit, ct);
        return Ok(new ApiResponse<object>(true, new { Posts = posts, Total = total, Page = page, Limit = limit }));
    }

    [HttpGet("posts/{slug}")]
    public async Task<IActionResult> GetPost(string slug,
        [FromQuery] string locale = "fa",
        CancellationToken ct = default)
    {
        var post = await website.GetPostAsync(slug, locale, ct);
        if (post is null) return NotFound(new ApiResponse<object>(false, null,
            new ApiError("POST_NOT_FOUND", "Blog post not found.")));
        return Ok(new ApiResponse<object>(true, post));
    }

    // ── Comments ──────────────────────────────────────────────────────────

    [HttpGet("posts/{slug}/comments")]
    public async Task<IActionResult> GetComments(string slug, CancellationToken ct = default)
    {
        var comments = await website.GetCommentsAsync(slug, ct);
        return Ok(new ApiResponse<object>(true, comments));
    }

    [HttpPost("posts/{slug}/comments")]
    [EnableRateLimiting("public-read")]
    public async Task<IActionResult> PostComment(string slug,
        [FromBody] PostCommentRequest req,
        CancellationToken ct = default)
    {
        if (string.IsNullOrWhiteSpace(req.AuthorName) || string.IsNullOrWhiteSpace(req.Content))
            return BadRequest(new ApiResponse<object>(false, null,
                new ApiError("VALIDATION", "AuthorName and Content are required.")));

        if (req.Content.Length > 2000)
            return BadRequest(new ApiResponse<object>(false, null,
                new ApiError("VALIDATION", "Comment too long (max 2000 chars).")));

        var ip = HttpContext.Connection.RemoteIpAddress?.ToString();
        try
        {
            var comment = await website.AddCommentAsync(slug, req.AuthorName, req.Email, req.Content, ip, ct);
            return Ok(new ApiResponse<object>(true, comment));
        }
        catch (InvalidOperationException)
        {
            return NotFound(new ApiResponse<object>(false, null,
                new ApiError("POST_NOT_FOUND", "Blog post not found.")));
        }
    }

    // ── Demo requests ─────────────────────────────────────────────────────

    [HttpPost("demo-requests")]
    [EnableRateLimiting("public-write")]
    public async Task<IActionResult> CreateDemoRequest(
        [FromBody] CreateDemoRequestBody req,
        CancellationToken ct = default)
    {
        if (string.IsNullOrWhiteSpace(req.ContactName) ||
            string.IsNullOrWhiteSpace(req.BusinessName) ||
            string.IsNullOrWhiteSpace(req.Phone))
        {
            return BadRequest(new ApiResponse<object>(false, null,
                new ApiError("VALIDATION", "ContactName, BusinessName, and Phone are required.")));
        }

        var result = await website.CreateDemoRequestAsync(
            req.ContactName, req.BusinessName, req.Phone,
            req.Email, req.BranchCount ?? "1", req.Notes, req.Source ?? "website", ct);

        return Ok(new ApiResponse<object>(true, result));
    }
}

public record PostCommentRequest(string AuthorName, string? Email, string Content);
public record CreateDemoRequestBody(
    string ContactName, string BusinessName, string Phone,
    string? Email, string? BranchCount, string? Notes, string? Source);
