using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using OneForMe.Data;
using OneForMe.Models;
using System.IO;

namespace OneForMe.Controllers;

[Authorize]
public class OrderController : Controller
{
    private readonly ApplicationDbContext _context;

    public OrderController(ApplicationDbContext context)
    {
        _context = context;
    }

    // GET: Order/Create
    public IActionResult Create()
    {
        return View();
    }

    // POST: Order/Create
    [HttpPost]
    public async Task<IActionResult> Create(Order order, string[] itemNames, string[] itemPrices, IFormFile? ImageFile)
    {
        if (!ModelState.IsValid)
            return View();

        order.OrderCode = GenerateOrderCode();
        order.CreatorName = User.Identity?.Name ?? "Unknown";
        
        // Handle image upload
        if (ImageFile != null && ImageFile.Length > 0)
        {
            try
            {
                var uploadsFolder = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "uploads", "orders");
                if (!Directory.Exists(uploadsFolder))
                {
                    Directory.CreateDirectory(uploadsFolder);
                }

                var uniqueFileName = $"{order.OrderCode}_{Guid.NewGuid()}_{Path.GetFileName(ImageFile.FileName)}";
                var filePath = Path.Combine(uploadsFolder, uniqueFileName);

                using (var fileStream = new FileStream(filePath, FileMode.Create))
                {
                    await ImageFile.CopyToAsync(fileStream);
                }

                order.ImagePath = $"/uploads/orders/{uniqueFileName}";
            }
            catch (Exception ex)
            {
                ModelState.AddModelError("ImageFile", $"Error uploading file: {ex.Message}");
                return View();
            }
        }
        
        _context.Orders.Add(order);
        await _context.SaveChangesAsync();

        // Add menu items
        for (int i = 0; i < itemNames.Length; i++)
        {
            itemPrices[i] = itemPrices[i].Replace(".", ",");
            if (!string.IsNullOrEmpty(itemNames[i]) && decimal.TryParse(itemPrices[i], out var price) && price > 0)
            {
                _context.MenuItems.Add(new MenuItem
                {
                    OrderId = order.Id,
                    Name = itemNames[i],
                    Price = price
                });
            }
        }
        await _context.SaveChangesAsync();

        return RedirectToAction("Details", new { code = order.OrderCode });
    }

    // GET: Order/Join
    public async Task<IActionResult> Join(string code)
    {
        var order = await _context.Orders
            .Include(o => o.MenuItems)
            .Include(o => o.OrderItems)
            .FirstOrDefaultAsync(o => o.OrderCode == code);

        if (order == null)
            return NotFound("Order not found");

        if (order.IsClosed || order.IsCompleted)
            return BadRequest("This order cannot be joined");

        return View(order);
    }

    // POST: Order/AddItem
    [HttpPost]
    public async Task<IActionResult> AddItem(int orderId, int menuItemId, int quantity, string comments)
    {
        var order = await _context.Orders.FindAsync(orderId);
        if (order == null || order.IsClosed)
            return BadRequest("Order not found or is closed");

        var menuItem = await _context.MenuItems.FindAsync(menuItemId);
        if (menuItem == null)
            return BadRequest("Menu item not found");

        var orderItem = new OrderItem
        {
            OrderId = orderId,
            MenuItemId = menuItemId,
            Quantity = quantity,
            ParticipantName = User.Identity?.Name ?? "",
            ParticipantEmail = User.Identity?.Name,
            Comments = comments
        };

        _context.OrderItems.Add(orderItem);
        await _context.SaveChangesAsync();

        return RedirectToAction("Details" , new { code = order.OrderCode });
    }

    [HttpPost]
    public async Task<IActionResult> DeleteItem(int orderItemId)
    {
        var orderItem = await _context.OrderItems
            .Include(oi => oi.Order)
            .FirstOrDefaultAsync(oi => oi.Id == orderItemId);
        if (orderItem == null)
            return NotFound("Order item not found");

        if (orderItem.Order?.CreatorName != User.Identity?.Name && orderItem.ParticipantEmail != User.Identity?.Name)
            return Forbid("Only the order creator or the participant who added the item can delete it");

        _context.OrderItems.Remove(orderItem);
        await _context.SaveChangesAsync();

        return RedirectToAction("Details", new { code = orderItem.Order?.OrderCode });
    }

    // POST: Order/UpdateItem
    [HttpPost]
    public async Task<IActionResult> UpdateItem(int orderItemId, int quantity, string comments)
    {
        var orderItem = await _context.OrderItems
            .Include(oi => oi.Order)
            .Include(oi => oi.MenuItem)
            .FirstOrDefaultAsync(oi => oi.Id == orderItemId);
            
        if (orderItem == null)
            return NotFound("Order item not found");

        if (orderItem.Order?.IsClosed == true)
            return BadRequest("Cannot update items in a closed order");

        if (orderItem.ParticipantEmail != User.Identity?.Name)
            return Forbid("Only the participant who added this item can update it");

        orderItem.Quantity = quantity;
        orderItem.Comments = comments;
        
        _context.OrderItems.Update(orderItem);
        await _context.SaveChangesAsync();

        return RedirectToAction("Details", new { code = orderItem.Order?.OrderCode });
    }


    // GET: Order/Details/{code}
    public async Task<IActionResult> Details(string code)
    {
        var order = await _context.Orders
            .Include(o => o.MenuItems)
            .Include(o => o.OrderItems)
            .FirstOrDefaultAsync(o => o.OrderCode == code);

        if (order == null)
            return NotFound();

        return View(order);
    }

    // GET: Order/Close/{code}
    public async Task<IActionResult> Close(string code)
    {
        var order = await _context.Orders.FirstOrDefaultAsync(o => o.OrderCode == code);
        
        if (order == null)
            return NotFound("Order not found");

        if (order.IsClosed)
            return BadRequest("Order is already closed");

        if (order.CreatorName != User.Identity?.Name)
            return Forbid("Only the order creator can close this order");

        order.IsClosed = true;
        order.ClosedAt = DateTime.UtcNow;
        
        _context.Orders.Update(order);
        await _context.SaveChangesAsync();

        return RedirectToAction("Details", new { code = order.OrderCode });
    }

    // GET: Order/Complete/{code}
    public async Task<IActionResult> Complete(string code)
    {
        var order = await _context.Orders.FirstOrDefaultAsync(o => o.OrderCode == code);
        
        if (order == null)
            return NotFound("Order not found");

        // Only the creator can complete an order
        if (order.CreatorName != User.Identity?.Name)
            return Forbid("Only the order creator can mark this as completed");

        if (!order.IsClosed)
            return BadRequest("Order must be closed before marking as completed");

        if (order.IsCompleted)
            return BadRequest("Order is already marked as completed");

        order.IsCompleted = true;
        order.CompletedAt = DateTime.UtcNow;
        
        _context.Orders.Update(order);
        await _context.SaveChangesAsync();

        return RedirectToAction("Details", new { code = order.OrderCode });
    }

    private string GenerateOrderCode()
    {
        return Guid.NewGuid().ToString().Substring(0, 8).ToUpper();
    }
}