package inventory

import (
	"context"
	"errors"

	"git.huangwc.com/pig/pig-farm-controller/internal/app/controller"
	"git.huangwc.com/pig/pig-farm-controller/internal/app/dto"
	"git.huangwc.com/pig/pig-farm-controller/internal/app/service"
	"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"

	"github.com/labstack/echo/v4"
)

// InventoryController 定义了库存相关的控制器
type InventoryController struct {
	ctx              context.Context
	inventoryService service.InventoryService
}

// NewInventoryController 创建一个新的 InventoryController 实例
func NewInventoryController(ctx context.Context, inventoryService service.InventoryService) *InventoryController {
	return &InventoryController{
		ctx:              ctx,
		inventoryService: inventoryService,
	}
}

// AdjustStock godoc
// @Summary      调整原料库存
// @Description  手动调整指定原料的库存量。
// @Tags         库存管理
// @Security     BearerAuth
// @Accept       json
// @Produce      json
// @Param        request body dto.StockAdjustmentRequest true "库存调整请求"
// @Success      200 {object} controller.Response{data=dto.StockLogResponse} "业务码为200代表调整成功"
// @Router       /api/v1/inventory/stock/adjust [post]
func (c *InventoryController) AdjustStock(ctx echo.Context) error {
	reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "AdjustStock")
	var req dto.StockAdjustmentRequest
	const actionType = "调整原料库存"

	if err := ctx.Bind(&req); err != nil {
		logger.Errorf("%s: 参数绑定失败: %v", actionType, err)
		return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体: "+err.Error(), actionType, "请求体绑定失败", req)
	}

	resp, err := c.inventoryService.AdjustStock(reqCtx, &req)
	if err != nil {
		logger.Errorf("%s: 服务层调整库存失败: %v", actionType, err)
		if errors.Is(err, service.ErrInventoryRawMaterialNotFound) {
			return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), actionType, "原料不存在", req)
		}
		if errors.Is(err, service.ErrInventoryInsufficientStock) {
			return controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), actionType, "原料库存不足", req)
		}
		return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "调整库存失败: "+err.Error(), actionType, "服务层调整库存失败", req)
	}

	logger.Infof("%s: 库存调整成功, 原料ID: %d", actionType, resp.RawMaterialID)
	return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "库存调整成功", resp, actionType, "库存调整成功", resp)
}

// ListCurrentStock godoc
// @Summary      获取当前库存列表
// @Description  获取所有原料的当前库存列表，支持分页和过滤。
// @Tags         库存管理
// @Security     BearerAuth
// @Produce      json
// @Param        query query dto.ListCurrentStockRequest false "查询参数"
// @Success      200 {object} controller.Response{data=dto.ListCurrentStockResponse} "业务码为200代表成功获取列表"
// @Router       /api/v1/inventory/stock/current [get]
func (c *InventoryController) ListCurrentStock(ctx echo.Context) error {
	reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "ListCurrentStock")
	const actionType = "获取当前库存列表"
	var req dto.ListCurrentStockRequest

	if err := ctx.Bind(&req); err != nil {
		logger.Errorf("%s: 查询参数绑定失败: %v", actionType, err)
		return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的查询参数: "+err.Error(), actionType, "查询参数绑定失败", req)
	}

	resp, err := c.inventoryService.ListCurrentStock(reqCtx, &req)
	if err != nil {
		logger.Errorf("%s: 服务层获取当前库存列表失败: %v", actionType, err)
		return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取当前库存列表失败: "+err.Error(), actionType, "服务层获取当前库存列表失败", nil)
	}

	logger.Infof("%s: 获取当前库存列表成功, 数量: %d", actionType, len(resp.List))
	return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取当前库存列表成功", resp, actionType, "获取当前库存列表成功", resp)
}

// ListStockLogs godoc
// @Summary      获取库存变动日志
// @Description  获取原料库存变动历史记录，支持分页、过滤和时间范围查询。
// @Tags         库存管理
// @Security     BearerAuth
// @Produce      json
// @Param        query query dto.ListStockLogRequest false "查询参数"
// @Success      200 {object} controller.Response{data=dto.ListStockLogResponse} "业务码为200代表成功获取列表"
// @Router       /api/v1/inventory/stock/logs [get]
func (c *InventoryController) ListStockLogs(ctx echo.Context) error {
	reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "ListStockLogs")
	const actionType = "获取库存变动日志"
	var req dto.ListStockLogRequest

	if err := ctx.Bind(&req); err != nil {
		logger.Errorf("%s: 查询参数绑定失败: %v", actionType, err)
		return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的查询参数: "+err.Error(), actionType, "查询参数绑定失败", req)
	}

	resp, err := c.inventoryService.ListStockLogs(reqCtx, &req)
	if err != nil {
		logger.Errorf("%s: 服务层获取库存变动日志失败: %v", actionType, err)
		return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取库存变动日志失败: "+err.Error(), actionType, "服务层获取库存变动日志失败", nil)
	}

	logger.Infof("%s: 获取库存变动日志成功, 数量: %d", actionType, len(resp.List))
	return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取库存变动日志成功", resp, actionType, "获取库存变动日志成功", resp)
}
