import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { inventoryApi, DEFAULT_SHOP_ID } from "../services/api-client.js";
import { errorResponse, textResponse } from "../services/error-handler.js";

interface InventoryItemDto {
  id: string;
  productId: string;
  shopId: string;
  name: string;
  itemType: string;
  unit: string;
  costPerUnit: number;
  supplierName?: string;
  quantity: number;
  reservedQuantity: number;
  availableQuantity: number;
  reorderLevel: number;
  updatedAt?: string;
}

export function registerInventoryTools(server: McpServer): void {
  // 1. check_inventory
  server.tool(
    "check_inventory",
    "Check current inventory/stock levels for a shop. Shows item name, quantity, unit, reorder level, and low stock warnings.",
    {
      shopId: z
        .string()
        .uuid()
        .optional()
        .describe("Shop ID (defaults to primary shop)"),
      skip: z.number().int().min(0).optional().default(0).describe("Records to skip"),
      take: z.number().int().min(1).max(200).optional().default(50).describe("Records to take"),
    },
    async ({ shopId, skip, take }) => {
      try {
        const resolvedShopId = shopId ?? DEFAULT_SHOP_ID;
        const response = await inventoryApi.get("/inventory", {
          params: { shopId: resolvedShopId, skip, take },
        });

        const payload = response.data?.data ?? response.data;
        const items: InventoryItemDto[] = payload?.items ?? [];
        const totalCount: number = payload?.totalCount ?? items.length;

        if (items.length === 0) {
          return textResponse(`No inventory items found for shop ${resolvedShopId}.`);
        }

        const header = `Inventory (${items.length} of ${totalCount} items)\n${"─".repeat(70)}`;
        const rows = items.map((item) => {
          const status = item.quantity <= item.reorderLevel ? "\u26a0\ufe0f Low" : "\u2705 OK";
          return `${item.name} | ${item.quantity} | ${item.unit} | ${item.reorderLevel} | ${status}`;
        });

        const table = [
          header,
          "Name | Qty | Unit | Reorder Level | Status",
          "─".repeat(70),
          ...rows,
          "─".repeat(70),
          `Page: skip=${skip}, take=${take} | Total: ${totalCount}`,
        ].join("\n");

        return textResponse(table);
      } catch (err) {
        return errorResponse(err);
      }
    }
  );

  // 2. record_intake (nhap kho)
  server.tool(
    "record_intake",
    "Record stock intake (nhap kho) — when goods are received from suppliers.",
    {
      shopId: z
        .string()
        .uuid()
        .optional()
        .describe("Shop ID (defaults to primary shop)"),
      productId: z.string().uuid().describe("Product ID to stock in"),
      amount: z.number().int().positive().describe("Quantity to add (whole number)"),
      notes: z.string().min(1).optional().describe("Optional notes for this intake"),
      unitCost: z.number().positive().optional().describe("Cost per unit (optional)"),
    },
    async ({ shopId, productId, amount, notes, unitCost }) => {
      try {
        const response = await inventoryApi.post("/inventory/stock-in", {
          productId,
          shopId: shopId ?? DEFAULT_SHOP_ID,
          amount,
          notes: notes ?? undefined,
          unitCost: unitCost ?? undefined,
        });

        const inventoryItemId = response.data?.data ?? response.data;

        const text = [
          `Stock intake recorded successfully.`,
          `  Product:          ${productId}`,
          `  Amount:           +${amount}`,
          unitCost != null ? `  Unit Cost:        ${unitCost}` : null,
          notes ? `  Notes:            ${notes}` : null,
          `  Inventory Item:   ${inventoryItemId}`,
        ]
          .filter(Boolean)
          .join("\n");

        return textResponse(text);
      } catch (err) {
        return errorResponse(err);
      }
    }
  );

  // 3. record_usage (xuat kho)
  server.tool(
    "record_usage",
    "Record stock usage/outflow (xuat kho) — when items are consumed, wasted, or adjusted.",
    {
      shopId: z
        .string()
        .uuid()
        .optional()
        .describe("Shop ID (defaults to primary shop)"),
      productId: z.string().uuid().describe("Product ID to stock out"),
      amount: z.number().int().positive().describe("Quantity to remove (whole number)"),
      notes: z.string().min(1).optional().describe("Optional notes (reason for usage)"),
    },
    async ({ shopId, productId, amount, notes }) => {
      try {
        await inventoryApi.post("/inventory/stock-out", {
          productId,
          shopId: shopId ?? DEFAULT_SHOP_ID,
          amount,
          notes: notes ?? undefined,
        });

        const text = [
          `Stock usage recorded successfully.`,
          `  Product:  ${productId}`,
          `  Amount:   -${amount}`,
          notes ? `  Notes:    ${notes}` : null,
        ]
          .filter(Boolean)
          .join("\n");

        return textResponse(text);
      } catch (err) {
        return errorResponse(err);
      }
    }
  );

  // 4. low_stock_alerts
  server.tool(
    "low_stock_alerts",
    "Get items that are at or below their reorder level. Critical for preventing stockouts.",
    {
      shopId: z
        .string()
        .uuid()
        .optional()
        .describe("Shop ID (defaults to primary shop)"),
      skip: z.number().int().min(0).optional().default(0).describe("Records to skip"),
      take: z.number().int().min(1).max(200).optional().default(50).describe("Records to take"),
    },
    async ({ shopId, skip, take }) => {
      try {
        const resolvedShopId = shopId ?? DEFAULT_SHOP_ID;
        const response = await inventoryApi.get("/inventory/low-stock", {
          params: { shopId: resolvedShopId, skip, take },
        });

        const payload = response.data?.data ?? response.data;
        const items: InventoryItemDto[] = payload?.items ?? [];
        const totalCount: number = payload?.totalCount ?? items.length;

        if (items.length === 0) {
          return textResponse(
            `No low-stock items found for shop ${resolvedShopId}. All stock levels are healthy.`,
          );
        }

        const header = `\u26a0\ufe0f Low Stock Alerts (${items.length} of ${totalCount} items)\n${"─".repeat(60)}`;
        const rows = items.map((item) => {
          const deficit = item.reorderLevel - item.quantity;
          return `\u26a0\ufe0f ${item.name}: ${item.quantity} ${item.unit} (reorder at ${item.reorderLevel}, need ${deficit > 0 ? deficit : 0} more)`;
        });

        const text = [header, ...rows, "─".repeat(60), `Total low-stock items: ${totalCount}`].join("\n");
        return textResponse(text);
      } catch (err) {
        return errorResponse(err);
      }
    }
  );
}
