using System.Text.Json;
using Microsoft.AspNetCore.Mvc;
using WebClientTpos.Server.Infrastructure;

namespace WebClientTpos.Server.Controllers;

/// <summary>
/// EN: Inventory controller — proxies to InventoryService for inventory items and transactions.
/// VI: Controller tồn kho — proxy đến InventoryService cho mặt hàng và giao dịch tồn kho.
/// </summary>
[ApiController]
[Route("api/bff")]
public class InventoryController : ControllerBase
{
    private readonly HttpClient _inventory;
    private readonly HttpClient _catalog;

    public InventoryController(IHttpClientFactory httpClientFactory)
    {
        _inventory = httpClientFactory.CreateClient("InventoryService");
        _catalog = httpClientFactory.CreateClient("CatalogService");
    }

    /// <summary>
    /// EN: Get inventory items enriched with product names from CatalogService.
    /// VI: Lấy danh sách tồn kho kèm tên sản phẩm từ CatalogService.
    /// </summary>
    [HttpGet("inventory")]
    public async Task<IActionResult> GetInventory([FromQuery] Guid? shopId = null)
    {
        var qs = shopId.HasValue ? $"?shopId={shopId}" : "";
        var invResponse = await _inventory.GetAsync($"/api/v1/inventory{qs}");
        if (!invResponse.IsSuccessStatusCode)
            return StatusCode((int)invResponse.StatusCode, await invResponse.Content.ReadAsStringAsync());

        var invJson = await invResponse.Content.ReadAsStringAsync();
        using var invDoc = JsonDocument.Parse(invJson);

        // EN: Extract items array from response envelope
        // VI: Trích mảng items từ response envelope
        JsonElement itemsArray;
        if (invDoc.RootElement.TryGetProperty("data", out var dataEl) && dataEl.TryGetProperty("items", out var di))
            itemsArray = di;
        else if (invDoc.RootElement.TryGetProperty("items", out var ri))
            itemsArray = ri;
        else
            return Content(invJson, "application/json");

        // EN: Build product name lookup from CatalogService
        // VI: Tạo bảng tra tên sản phẩm từ CatalogService
        var productNames = new Dictionary<string, string>();
        try
        {
            var prodQs = shopId.HasValue ? $"?shopId={shopId}&pageSize=200" : "?pageSize=200";
            var prodResp = await _catalog.GetAsync($"/api/v1/products{prodQs}");
            if (prodResp.IsSuccessStatusCode)
            {
                var prodJson = await prodResp.Content.ReadAsStringAsync();
                using var prodDoc = JsonDocument.Parse(prodJson);
                JsonElement prodItems;
                if (prodDoc.RootElement.TryGetProperty("items", out var pi))
                    prodItems = pi;
                else if (prodDoc.RootElement.TryGetProperty("data", out var pd) && pd.TryGetProperty("items", out var pdi))
                    prodItems = pdi;
                else
                    prodItems = default;

                if (prodItems.ValueKind == JsonValueKind.Array)
                {
                    foreach (var p in prodItems.EnumerateArray())
                    {
                        if (p.TryGetProperty("id", out var pid) && p.TryGetProperty("name", out var pname))
                            productNames[pid.GetString()!] = pname.GetString()!;
                    }
                }
            }
        }
        catch { /* non-fatal: names will be missing */ }

        // EN: Enrich inventory items with productName
        // VI: Bổ sung productName vào từng inventory item
        var enriched = new List<object>();
        foreach (var item in itemsArray.EnumerateArray())
        {
            var dict = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(item.GetRawText())!;
            var productId = item.TryGetProperty("productId", out var pidEl) ? pidEl.GetString() : null;
            var productName = productId != null && productNames.TryGetValue(productId, out var name) ? name : null;

            var obj = new Dictionary<string, object?>();
            foreach (var kv in dict)
                obj[kv.Key] = kv.Value;
            // EN: Use item name (raw material) if available, fallback to catalog productName
            // VI: Dùng tên item (nguyên liệu) nếu có, fallback sang productName từ catalog
            var itemName = item.TryGetProperty("name", out var nameEl) && nameEl.ValueKind == JsonValueKind.String ? nameEl.GetString() : null;
            obj["productName"] = itemName ?? productName;
            enriched.Add(obj);
        }

        return Ok(new { success = true, data = new { items = enriched } });
    }

    /// <summary>
    /// EN: Create a new inventory item (raw material, finished product, or supply).
    /// VI: Tạo mặt hàng tồn kho mới (nguyên liệu, thành phẩm, hoặc vật tư).
    /// </summary>
    [HttpPost("inventory/items")]
    public Task<IActionResult> CreateInventoryItem([FromBody] JsonElement body) =>
        _inventory.PostAsJsonAsync("/api/v1/inventory/items", body).ProxyAsync();

    /// <summary>
    /// EN: Update inventory quantity for a specific item.
    /// VI: Cập nhật số lượng tồn kho cho mặt hàng.
    /// </summary>
    [HttpPut("inventory/{inventoryId:guid}")]
    public Task<IActionResult> UpdateInventory(Guid inventoryId, [FromBody] JsonElement body) =>
        _inventory.PutAsJsonAsync($"/api/v1/inventory/{inventoryId}", body).ProxyAsync();

    /// <summary>
    /// EN: Get inventory transactions scoped to current merchant's shops.
    /// VI: Lấy giao dịch tồn kho lọc theo shops của merchant hiện tại.
    /// </summary>
    [HttpGet("inventory/transactions")]
    public Task<IActionResult> GetInventoryTransactions([FromQuery] Guid? shopId = null)
    {
        var qs = shopId.HasValue ? $"?shopId={shopId}" : "";
        return _inventory.GetAsync($"/api/v1/inventory/transactions{qs}").ProxyAsync();
    }

    /// <summary>
    /// EN: Stock in — add quantity to inventory.
    /// VI: Nhập kho — thêm số lượng vào tồn kho.
    /// </summary>
    [HttpPost("inventory/stock-in")]
    public Task<IActionResult> StockIn([FromBody] JsonElement body) =>
        _inventory.PostAsJsonAsync("/api/v1/inventory/stock-in", body).ProxyAsync();

    /// <summary>
    /// EN: Stock out — remove quantity from inventory.
    /// VI: Xuất kho — trừ số lượng khỏi tồn kho.
    /// </summary>
    [HttpPost("inventory/stock-out")]
    public Task<IActionResult> StockOut([FromBody] JsonElement body) =>
        _inventory.PostAsJsonAsync("/api/v1/inventory/stock-out", body).ProxyAsync();

    /// <summary>
    /// EN: Adjust stock — set exact quantity.
    /// VI: Điều chỉnh kho — đặt số lượng chính xác.
    /// </summary>
    [HttpPost("inventory/adjust")]
    public Task<IActionResult> AdjustStock([FromBody] JsonElement body) =>
        _inventory.PostAsJsonAsync("/api/v1/inventory/adjust", body).ProxyAsync();

    /// <summary>
    /// EN: Record wastage/shrinkage.
    /// VI: Ghi nhận hao hụt.
    /// </summary>
    [HttpPost("inventory/wastage")]
    public Task<IActionResult> RecordWastage([FromBody] JsonElement body) =>
        _inventory.PostAsJsonAsync("/api/v1/inventory/wastage", body).ProxyAsync();

    /// <summary>
    /// EN: Perform stocktake (inventory count).
    /// VI: Thực hiện kiểm kê (đếm tồn kho).
    /// </summary>
    [HttpPost("inventory/stocktake")]
    public Task<IActionResult> Stocktake([FromBody] JsonElement body) =>
        _inventory.PostAsJsonAsync("/api/v1/inventory/stocktake", body).ProxyAsync();

    /// <summary>
    /// EN: Get low stock alerts.
    /// VI: Lấy cảnh báo hàng tồn kho thấp.
    /// </summary>
    [HttpGet("inventory/low-stock")]
    public Task<IActionResult> GetLowStock([FromQuery] Guid? shopId = null)
    {
        var qs = shopId.HasValue ? $"?shopId={shopId}" : "";
        return _inventory.GetAsync($"/api/v1/inventory/low-stock{qs}").ProxyAsync();
    }

    /// <summary>
    /// EN: Delete an inventory item.
    /// VI: Xóa nguyên liệu khỏi tồn kho.
    /// </summary>
    [HttpDelete("inventory/items/{id:guid}")]
    public Task<IActionResult> DeleteInventoryItem(Guid id) =>
        _inventory.DeleteAsync($"/api/v1/inventory/items/{id}").ProxyAsync();
}
