using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using LittleShop.Services;
using LittleShop.DTOs;
using System.Text;

namespace LittleShop.Areas.Admin.Controllers;

[Area("Admin")]
[Authorize(Policy = "AdminOnly")]
public class ProductsController : Controller
{
    private readonly IProductService _productService;
    private readonly ICategoryService _categoryService;
    private readonly IProductImportService _importService;

    public ProductsController(IProductService productService, ICategoryService categoryService, IProductImportService importService)
    {
        _productService = productService;
        _categoryService = categoryService;
        _importService = importService;
    }

    public async Task<IActionResult> Index()
    {
        // Prevent caching of products list to show real-time data
        Response.Headers.Add("Cache-Control", "no-cache, no-store, must-revalidate");
        Response.Headers.Add("Pragma", "no-cache");
        Response.Headers.Add("Expires", "0");
        
        var products = await _productService.GetAllProductsAsync();
        return View(products);
    }

    public async Task<IActionResult> Create()
    {
        var categories = await _categoryService.GetAllCategoriesAsync();
        ViewData["Categories"] = categories.Where(c => c.IsActive);
        return View(new CreateProductDto());
    }

    [HttpPost]
    public async Task<IActionResult> Create(CreateProductDto model)
    {
        Console.WriteLine($"Received Product: Name='{model?.Name}', Description='{model?.Description}', Price={model?.Price}, Stock={model?.StockQuantity}");
        Console.WriteLine($"CategoryId: {model?.CategoryId}");
        Console.WriteLine($"Weight: {model?.Weight}, WeightUnit: {model?.WeightUnit}");
        Console.WriteLine($"ModelState.IsValid: {ModelState.IsValid}");
        
        // Remove Description validation errors since it's optional
        ModelState.Remove("Description");
        
        if (!ModelState.IsValid)
        {
            Console.WriteLine("Validation errors:");
            foreach (var error in ModelState)
            {
                if (error.Value?.Errors.Count > 0)
                {
                    Console.WriteLine($"  {error.Key}: {string.Join(", ", error.Value.Errors.Select(e => e.ErrorMessage))}");
                }
            }
            
            var categories = await _categoryService.GetAllCategoriesAsync();
            ViewData["Categories"] = categories.Where(c => c.IsActive);
            return View(model);
        }

        var createdProduct = await _productService.CreateProductAsync(model);
        return RedirectToAction(nameof(Index));
    }

    public async Task<IActionResult> Edit(Guid id)
    {
        var product = await _productService.GetProductByIdAsync(id);
        if (product == null)
        {
            return NotFound();
        }

        var categories = await _categoryService.GetAllCategoriesAsync();
        ViewData["Categories"] = categories.Where(c => c.IsActive);
        ViewData["ProductId"] = id;
        ViewData["ProductPhotos"] = product.Photos;

        var model = new UpdateProductDto
        {
            Name = product.Name,
            Description = product.Description,
            WeightUnit = product.WeightUnit,
            Weight = product.Weight,
            Price = product.Price,
            StockQuantity = product.StockQuantity,
            CategoryId = product.CategoryId,
            IsActive = product.IsActive
        };

        return View(model);
    }

    [HttpPost]
    public async Task<IActionResult> Edit(Guid id, UpdateProductDto model)
    {
        if (!ModelState.IsValid)
        {
            var categories = await _categoryService.GetAllCategoriesAsync();
            ViewData["Categories"] = categories.Where(c => c.IsActive);
            ViewData["ProductId"] = id;
            return View(model);
        }

        var success = await _productService.UpdateProductAsync(id, model);
        if (!success)
        {
            return NotFound();
        }

        return RedirectToAction(nameof(Index));
    }

    [HttpPost]
    public async Task<IActionResult> UploadPhoto(Guid id, IFormFile file, string? altText)
    {
        if (file != null && file.Length > 0)
        {
            await _productService.AddProductPhotoAsync(id, file, altText);
        }

        return RedirectToAction(nameof(Edit), new { id });
    }

    [HttpPost]
    public async Task<IActionResult> DeletePhoto(Guid id, Guid photoId)
    {
        await _productService.RemoveProductPhotoAsync(id, photoId);
        return RedirectToAction(nameof(Edit), new { id });
    }

    [HttpPost]
    public async Task<IActionResult> Delete(Guid id)
    {
        await _productService.DeleteProductAsync(id);
        return RedirectToAction(nameof(Index));
    }

    // Product Variations
    public async Task<IActionResult> Variations(Guid id)
    {
        var product = await _productService.GetProductByIdAsync(id);
        if (product == null)
            return NotFound();

        ViewData["Product"] = product;
        var variations = await _productService.GetProductVariationsAsync(id);
        return View(variations);
    }

    public async Task<IActionResult> CreateVariation(Guid productId)
    {
        var product = await _productService.GetProductByIdAsync(productId);
        if (product == null)
            return NotFound();

        // Force no-cache to ensure updated form loads
        Response.Headers.Add("Cache-Control", "no-cache, no-store, must-revalidate");
        Response.Headers.Add("Pragma", "no-cache");
        Response.Headers.Add("Expires", "0");

        ViewData["Product"] = product;

        // Get existing quantities to help user avoid duplicates
        var existingQuantities = await _productService.GetProductVariationsAsync(productId);
        ViewData["ExistingQuantities"] = existingQuantities.Select(v => v.Quantity).ToList();

        return View(new CreateProductVariationDto { ProductId = productId });
    }

    [HttpPost]
    public async Task<IActionResult> CreateVariation(CreateProductVariationDto model)
    {
        // Debug form data
        Console.WriteLine("=== FORM DEBUG ===");
        Console.WriteLine($"Received CreateVariation POST: ProductId={model?.ProductId}, Name='{model?.Name}', Quantity={model?.Quantity}, Price={model?.Price}");
        Console.WriteLine($"ModelState.IsValid: {ModelState.IsValid}");
        Console.WriteLine("Raw form data:");
        foreach (var key in Request.Form.Keys)
        {
            Console.WriteLine($"  {key} = '{Request.Form[key]}'");
        }
        Console.WriteLine("================");

        if (!ModelState.IsValid)
        {
            foreach (var key in ModelState.Keys)
            {
                var errors = ModelState[key]?.Errors;
                if (errors?.Any() == true)
                {
                    Console.WriteLine($"ModelState Error - {key}: {string.Join(", ", errors.Select(e => e.ErrorMessage))}");
                }
            }

            var product = await _productService.GetProductByIdAsync(model.ProductId);
            ViewData["Product"] = product;

            // Re-populate existing quantities for error display
            var existingQuantities = await _productService.GetProductVariationsAsync(model.ProductId);
            ViewData["ExistingQuantities"] = existingQuantities.Select(v => v.Quantity).ToList();

            return View(model);
        }

        try
        {
            await _productService.CreateProductVariationAsync(model);
            return RedirectToAction(nameof(Variations), new { id = model.ProductId });
        }
        catch (ArgumentException ex)
        {
            // Add the error to the appropriate field if it's a quantity conflict
            if (ex.Message.Contains("quantity") && ex.Message.Contains("already exists"))
            {
                ModelState.AddModelError("Quantity", ex.Message);
            }
            else
            {
                ModelState.AddModelError("", ex.Message);
            }

            var product = await _productService.GetProductByIdAsync(model.ProductId);
            ViewData["Product"] = product;

            // Re-populate existing quantities for error display
            var existingQuantities = await _productService.GetProductVariationsAsync(model.ProductId);
            ViewData["ExistingQuantities"] = existingQuantities.Select(v => v.Quantity).ToList();

            return View(model);
        }
    }

    public async Task<IActionResult> EditVariation(Guid id)
    {
        var variation = await _productService.GetProductVariationByIdAsync(id);
        if (variation == null)
            return NotFound();

        var product = await _productService.GetProductByIdAsync(variation.ProductId);
        ViewData["Product"] = product;

        var model = new UpdateProductVariationDto
        {
            Name = variation.Name,
            Description = variation.Description,
            Quantity = variation.Quantity,
            Price = variation.Price,
            SortOrder = variation.SortOrder,
            IsActive = variation.IsActive
        };

        return View(model);
    }

    [HttpPost]
    public async Task<IActionResult> EditVariation(Guid id, UpdateProductVariationDto model)
    {
        if (!ModelState.IsValid)
        {
            var variation = await _productService.GetProductVariationByIdAsync(id);
            var product = await _productService.GetProductByIdAsync(variation!.ProductId);
            ViewData["Product"] = product;
            return View(model);
        }

        var success = await _productService.UpdateProductVariationAsync(id, model);
        if (!success)
            return NotFound();

        var variationToRedirect = await _productService.GetProductVariationByIdAsync(id);
        return RedirectToAction(nameof(Variations), new { id = variationToRedirect!.ProductId });
    }

    [HttpPost]
    public async Task<IActionResult> DeleteVariation(Guid id)
    {
        var variation = await _productService.GetProductVariationByIdAsync(id);
        if (variation == null)
            return NotFound();

        await _productService.DeleteProductVariationAsync(id);
        return RedirectToAction(nameof(Variations), new { id = variation.ProductId });
    }

    // Product Import/Export
    public IActionResult Import()
    {
        return View();
    }

    [HttpPost]
    public async Task<IActionResult> Import(IFormFile file)
    {
        if (file == null || file.Length == 0)
        {
            ModelState.AddModelError("", "Please select a CSV file to import");
            return View();
        }

        if (!file.FileName.EndsWith(".csv", StringComparison.OrdinalIgnoreCase))
        {
            ModelState.AddModelError("", "Only CSV files are supported");
            return View();
        }

        try
        {
            using var stream = file.OpenReadStream();
            var result = await _importService.ImportFromCsvAsync(stream);

            ViewData["ImportResult"] = result;
            return View("ImportResult", result);
        }
        catch (Exception ex)
        {
            ModelState.AddModelError("", $"Import failed: {ex.Message}");
            return View();
        }
    }

    public async Task<IActionResult> Export()
    {
        var csvContent = await _importService.ExportProductsAsCsvAsync();
        var fileName = $"products_export_{DateTime.UtcNow:yyyyMMdd_HHmmss}.csv";

        return File(Encoding.UTF8.GetBytes(csvContent), "text/csv", fileName);
    }

    public IActionResult DownloadTemplate()
    {
        var templateContent = _importService.GenerateTemplateAsCsv();
        var fileName = "product_import_template.csv";

        return File(Encoding.UTF8.GetBytes(templateContent), "text/csv", fileName);
    }
}