using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using System.Security.Claims;
using LittleShop.DTOs;
using LittleShop.Services;

namespace LittleShop.Controllers;

[ApiController]
[Route("api/push")]
public class PushNotificationController : ControllerBase
{
    private readonly IPushNotificationService _pushNotificationService;

    public PushNotificationController(IPushNotificationService pushNotificationService)
    {
        _pushNotificationService = pushNotificationService;
    }

    /// <summary>
    /// Get the VAPID public key for client-side push subscription
    /// </summary>
    [HttpGet("vapid-key")]
    public IActionResult GetVapidPublicKey()
    {
        try
        {
            var publicKey = _pushNotificationService.GetVapidPublicKey();
            return Ok(new { publicKey });
        }
        catch (Exception ex)
        {
            return StatusCode(500, new { error = ex.Message });
        }
    }

    /// <summary>
    /// Subscribe admin user to push notifications
    /// </summary>
    [HttpPost("subscribe")]
    [Authorize(AuthenticationSchemes = "Cookies", Roles = "Admin")]
    public async Task<IActionResult> Subscribe([FromBody] PushSubscriptionDto subscriptionDto)
    {
        try
        {
            var userIdClaim = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            var username = User.FindFirst(ClaimTypes.Name)?.Value ?? User.Identity?.Name;
            
            // Debug logging
            var logger = HttpContext.RequestServices.GetRequiredService<ILogger<PushNotificationController>>();
            logger.LogInformation("Push subscription attempt - UserIdClaim: {UserIdClaim}, Username: {Username}", userIdClaim, username);
            
            if (string.IsNullOrEmpty(userIdClaim) || !Guid.TryParse(userIdClaim, out Guid userId))
            {
                return Unauthorized(new { error = "Invalid user ID", userIdClaim, username });
            }

            var userAgent = Request.Headers.UserAgent.ToString();
            var ipAddress = HttpContext.Connection.RemoteIpAddress?.ToString();

            var success = await _pushNotificationService.SubscribeUserAsync(userId, subscriptionDto, userAgent, ipAddress);
            
            if (success)
            {
                return Ok(new { message = "Successfully subscribed to push notifications" });
            }
            else
            {
                return StatusCode(500, new { error = "Failed to subscribe to push notifications" });
            }
        }
        catch (Exception ex)
        {
            var logger = HttpContext.RequestServices.GetRequiredService<ILogger<PushNotificationController>>();
            logger.LogError(ex, "Push subscription error");
            return StatusCode(500, new { error = ex.Message });
        }
    }

    /// <summary>
    /// Subscribe customer to push notifications (for customer-facing apps)
    /// </summary>
    [HttpPost("subscribe/customer")]
    [AllowAnonymous]
    public async Task<IActionResult> SubscribeCustomer([FromBody] PushSubscriptionDto subscriptionDto, [FromQuery] Guid customerId)
    {
        try
        {
            if (customerId == Guid.Empty)
            {
                return BadRequest("Invalid customer ID");
            }

            var userAgent = Request.Headers.UserAgent.ToString();
            var ipAddress = HttpContext.Connection.RemoteIpAddress?.ToString();

            var success = await _pushNotificationService.SubscribeCustomerAsync(customerId, subscriptionDto, userAgent, ipAddress);
            
            if (success)
            {
                return Ok(new { message = "Successfully subscribed to push notifications" });
            }
            else
            {
                return StatusCode(500, new { error = "Failed to subscribe to push notifications" });
            }
        }
        catch (Exception ex)
        {
            return StatusCode(500, new { error = ex.Message });
        }
    }

    /// <summary>
    /// Unsubscribe from push notifications
    /// </summary>
    [HttpPost("unsubscribe")]
    public async Task<IActionResult> Unsubscribe([FromBody] UnsubscribeDto unsubscribeDto)
    {
        try
        {
            var success = await _pushNotificationService.UnsubscribeAsync(unsubscribeDto.Endpoint);
            
            if (success)
            {
                return Ok(new { message = "Successfully unsubscribed from push notifications" });
            }
            else
            {
                return NotFound(new { error = "Subscription not found" });
            }
        }
        catch (Exception ex)
        {
            return StatusCode(500, new { error = ex.Message });
        }
    }

    /// <summary>
    /// Send test notification to current admin user
    /// </summary>
    [HttpPost("test")]
    [Authorize(AuthenticationSchemes = "Cookies", Roles = "Admin")]
    public async Task<IActionResult> SendTestNotification([FromBody] TestPushNotificationDto testDto)
    {
        try
        {
            var userIdClaim = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            var success = await _pushNotificationService.SendTestNotificationAsync(userIdClaim, testDto.Title, testDto.Body);
            
            if (success)
            {
                return Ok(new { message = "Test notification sent successfully" });
            }
            else
            {
                return StatusCode(500, new { error = "Failed to send test notification. Make sure you are subscribed to push notifications." });
            }
        }
        catch (Exception ex)
        {
            return StatusCode(500, new { error = ex.Message });
        }
    }

    /// <summary>
    /// Send broadcast notification to all admin users
    /// </summary>
    [HttpPost("broadcast")]
    [Authorize(AuthenticationSchemes = "Cookies", Roles = "Admin")]
    public async Task<IActionResult> SendBroadcastNotification([FromBody] PushNotificationDto notificationDto)
    {
        try
        {
            var success = await _pushNotificationService.SendNotificationToAllUsersAsync(notificationDto);
            
            if (success)
            {
                return Ok(new { message = "Broadcast notification sent successfully" });
            }
            else
            {
                return StatusCode(500, new { error = "Failed to send broadcast notification" });
            }
        }
        catch (Exception ex)
        {
            return StatusCode(500, new { error = ex.Message });
        }
    }

    /// <summary>
    /// Get active push subscriptions (admin only)
    /// </summary>
    [HttpGet("subscriptions")]
    [Authorize(AuthenticationSchemes = "Cookies", Roles = "Admin")]
    public async Task<IActionResult> GetActiveSubscriptions()
    {
        try
        {
            var subscriptions = await _pushNotificationService.GetActiveSubscriptionsAsync();
            
            var result = subscriptions.Select(s => new
            {
                id = s.Id,
                userId = s.UserId,
                customerId = s.CustomerId,
                userName = s.User?.Username,
                customerName = s.Customer?.TelegramDisplayName ?? s.Customer?.TelegramUsername,
                subscribedAt = s.SubscribedAt,
                lastUsedAt = s.LastUsedAt,
                userAgent = s.UserAgent,
                endpoint = s.Endpoint[..Math.Min(50, s.Endpoint.Length)] + "..." // Truncate for security
            }).ToList();

            return Ok(result);
        }
        catch (Exception ex)
        {
            return StatusCode(500, new { error = ex.Message });
        }
    }

    /// <summary>
    /// Cleanup expired push subscriptions
    /// </summary>
    [HttpPost("cleanup")]
    [Authorize(AuthenticationSchemes = "Cookies", Roles = "Admin")]
    public async Task<IActionResult> CleanupExpiredSubscriptions()
    {
        try
        {
            var cleanedCount = await _pushNotificationService.CleanupExpiredSubscriptionsAsync();
            return Ok(new { message = $"Cleaned up {cleanedCount} expired subscriptions" });
        }
        catch (Exception ex)
        {
            return StatusCode(500, new { error = ex.Message });
        }
    }
}

public class UnsubscribeDto
{
    public string Endpoint { get; set; } = string.Empty;
}