using Api.Services.Contracts.Models;
using Api.Services.Contracts;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting;
using Microsoft.Extensions.Options;
using Models.Settings;
using Models.Requests;
using Swashbuckle.AspNetCore.Annotations;
using Common.Responses;

namespace Api.Controllers
{
    /// <summary>
    /// Exposes endpoints used by the frontend to send contact messages and to
    /// subscribe to newsletters. All endpoints are protected by reCAPTCHA
    /// verification and rate limiting.
    /// </summary>
    [ApiController]
    [Route("api/[controller]")]
    [EnableCors("FrontendOnly")]
    public sealed class ContactController : ControllerBase
    {
        private readonly ICaptchaVerifier _captcha;
        private readonly IEmailSender _email;
        private readonly ILogger<ContactController> _log;

        public ContactController(ICaptchaVerifier captcha, IEmailSender email, ILogger<ContactController> log)
        {
            _captcha = captcha;
            _email = email;
            _log = log;
        }
        /// <summary>
        /// Validates the provided reCAPTCHA token and sends a contact message
        /// via the configured email sender.
        /// </summary>
        /// <param name="req">Contact request containing name, email, subject,
        /// and message. The <c>CaptchaToken</c> field is required for verification.</param>
        /// <param name="ct">Cancellation token.</param>
        /// <returns>
        /// 200 OK when the message was queued/sent; 400 Bad Request when
        /// captcha verification fails; 500 on internal errors.
        /// </returns>
        [HttpPost]
        [EnableRateLimiting("contact")]
        [SwaggerOperation(Summary = "Send contact message", Description = "Validates captcha and sends a contact message using the configured email sender.")]
        [SwaggerResponse(StatusCodes.Status200OK, "Contact message sent")]
        [SwaggerResponse(StatusCodes.Status400BadRequest, "Invalid request or captcha verification failed")]
        [SwaggerResponse(StatusCodes.Status500InternalServerError, "Contact message could not be sent due to server error")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)]
        [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status500InternalServerError)]
        public async Task<IActionResult> Send([FromBody] ContactRequest req, CancellationToken ct)
        {
            if (!ModelState.IsValid)
                return ValidationProblem(ModelState);

            var userIp = HttpContext.Connection.RemoteIpAddress?.ToString();
            var verdict = await _captcha.VerifyAsync(req.CaptchaToken, userIp, "contact", ct);
            if (!verdict.Success)
            {
                return BadRequest(new ErrorResponse { Error = "Captcha verification failed.", Code = "captcha_verification_failed" });
            }

            try
            {
                await _email.SendContactAsync(req, ct);
                return Ok(new { ok = true });
            }
            catch (Exception ex)
            {
                _log.LogError(ex, "Contact send failed. ip={Ip} from={From}", userIp, req.Email);
                return StatusCode(StatusCodes.Status500InternalServerError, new ErrorResponse { Error = "Could not send message.", Code = "contact_send_failed" });
            }
        }

        /// <summary>
        /// Validates the provided reCAPTCHA token and subscribes the given
        /// email address to the newsletter or mailing list.
        /// </summary>
        /// <param name="req">Subscription request containing the email and
        /// the <c>CaptchaToken</c>.</param>
        /// <param name="ct">Cancellation token.</param>
        /// <returns>
        /// 200 OK when subscription succeeded; 400 when captcha verification
        /// fails; 500 on internal errors.
        /// </returns>
        [HttpPost("subscribe")]
        [EnableRateLimiting("contact")]
        [SwaggerOperation(Summary = "Subscribe email", Description = "Validates captcha and subscribes an email address to the mailing list.")]
        [SwaggerResponse(StatusCodes.Status200OK, "Subscription succeeded")]
        [SwaggerResponse(StatusCodes.Status400BadRequest, "Invalid request or captcha verification failed")]
        [SwaggerResponse(StatusCodes.Status500InternalServerError, "Subscription failed due to server error")]
        [ProducesResponseType(StatusCodes.Status200OK)]
        [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status400BadRequest)]
        [ProducesResponseType(typeof(ErrorResponse), StatusCodes.Status500InternalServerError)]
        public async Task<IActionResult> Subscribe([FromBody] SubscribeRequest req, CancellationToken ct)
        {
            if (!ModelState.IsValid)
                return ValidationProblem(ModelState);

            var userIp = HttpContext.Connection.RemoteIpAddress?.ToString();
            var verdict = await _captcha.VerifyAsync(req.CaptchaToken, userIp, "subscribe", ct);
            if (!verdict.Success)
            {
                return BadRequest(new ErrorResponse { Error = "Captcha verification failed.", Code = "captcha_verification_failed" });
            }

            try
            {
                await _email.SendSubscribeAsync(req, ct);
                return Ok(new { ok = true });
            }
            catch (Exception ex)
            {
                _log.LogError(ex, "Subscription failed. ip={Ip} eMail={eMail}", userIp, req.Email);
                return StatusCode(StatusCodes.Status500InternalServerError, new ErrorResponse { Error = "Could not process subscription.", Code = "subscription_failed" });
            }

        }
    }
}
