package management

import (
	"context"
	"errors"
	"strconv"

	"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"
)

// --- 控制器定义 ---

// PigFarmController 负责处理猪舍和猪栏相关的API请求
type PigFarmController struct {
	ctx     context.Context
	service service.PigFarmService
}

// NewPigFarmController 创建一个新的 PigFarmController 实例
func NewPigFarmController(ctx context.Context, service service.PigFarmService) *PigFarmController {
	return &PigFarmController{
		ctx:     ctx,
		service: service,
	}
}

// --- 猪舍 (PigHouse) API 实现 ---

// CreatePigHouse godoc
// @Summary      创建猪舍
// @Description  根据提供的信息创建一个新猪舍
// @Tags         猪场管理
// @Security     BearerAuth
// @Accept       json
// @Produce      json
// @Param        body body dto.CreatePigHouseRequest true "猪舍信息"
// @Success      201 {object} controller.Response{data=dto.PigHouseResponse} "创建成功"
// @Router       /api/v1/pig-houses [post]
func (c *PigFarmController) CreatePigHouse(ctx echo.Context) error {
	reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "CreatePigHouse")
	const action = "创建猪舍"
	var req dto.CreatePigHouseRequest
	if err := ctx.Bind(&req); err != nil {
		logger.Errorf("%s: 参数绑定失败: %v", action, err)
		return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req)
	}

	house, err := c.service.CreatePigHouse(reqCtx, req.Name, req.Description)
	if err != nil {
		logger.Errorf("%s: 业务逻辑失败: %v", action, err)
		return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "创建猪舍失败", action, "业务逻辑失败", req)
	}

	return controller.SendSuccessWithAudit(ctx, controller.CodeCreated, "创建成功", house, action, "创建成功", house)
}

// GetPigHouse godoc
// @Summary      获取单个猪舍
// @Description  根据ID获取单个猪舍信息
// @Tags         猪场管理
// @Security     BearerAuth
// @Produce      json
// @Param        id path int true "猪舍ID"
// @Success      200 {object} controller.Response{data=dto.PigHouseResponse} "获取成功"
// @Router       /api/v1/pig-houses/{id} [get]
func (c *PigFarmController) GetPigHouse(ctx echo.Context) error {
	reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "GetPigHouse")
	const action = "获取猪舍"
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
	}

	house, err := c.service.GetPigHouseByID(reqCtx, uint32(id))
	if err != nil {
		if errors.Is(err, service.ErrHouseNotFound) {
			return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪舍不存在", action, "猪舍不存在", id)
		}
		logger.Errorf("%s: 业务逻辑失败: %v", action, err)
		return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取猪舍失败", action, "业务逻辑失败", id)
	}

	return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取成功", house, action, "获取成功", house)
}

// ListPigHouses godoc
// @Summary      获取猪舍列表
// @Description  获取所有猪舍的列表
// @Tags         猪场管理
// @Security     BearerAuth
// @Produce      json
// @Success      200 {object} controller.Response{data=[]dto.PigHouseResponse} "获取成功"
// @Router       /api/v1/pig-houses [get]
func (c *PigFarmController) ListPigHouses(ctx echo.Context) error {
	reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "ListPigHouses")
	const action = "获取猪舍列表"
	houses, err := c.service.ListPigHouses(reqCtx)
	if err != nil {
		logger.Errorf("%s: 业务逻辑失败: %v", action, err)
		return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取列表失败", action, "业务逻辑失败", nil)
	}

	return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取成功", houses, action, "获取成功", houses)
}

// UpdatePigHouse godoc
// @Summary      更新猪舍
// @Description  更新一个已存在的猪舍信息
// @Tags         猪场管理
// @Security     BearerAuth
// @Accept       json
// @Produce      json
// @Param        id path int true "猪舍ID"
// @Param        body body dto.UpdatePigHouseRequest true "猪舍信息"
// @Success      200 {object} controller.Response{data=dto.PigHouseResponse} "更新成功"
// @Router       /api/v1/pig-houses/{id} [put]
func (c *PigFarmController) UpdatePigHouse(ctx echo.Context) error {
	reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "UpdatePigHouse")
	const action = "更新猪舍"
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
	}

	var req dto.UpdatePigHouseRequest
	if err := ctx.Bind(&req); err != nil {
		return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req)
	}

	house, err := c.service.UpdatePigHouse(reqCtx, uint32(id), req.Name, req.Description)
	if err != nil {
		if errors.Is(err, service.ErrHouseNotFound) {
			return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪舍不存在", action, "猪舍不存在", id)
		}
		logger.Errorf("%s: 业务逻辑失败: %v", action, err)
		return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新失败", action, "业务逻辑失败", req)
	}

	return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "更新成功", house, action, "更新成功", house)
}

// DeletePigHouse godoc
// @Summary      删除猪舍
// @Description  根据ID删除一个猪舍
// @Tags         猪场管理
// @Security     BearerAuth
// @Produce      json
// @Param        id path int true "猪舍ID"
// @Success      200 {object} controller.Response "删除成功"
// @Router       /api/v1/pig-houses/{id} [delete]
func (c *PigFarmController) DeletePigHouse(ctx echo.Context) error {
	reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "DeletePigHouse")
	const action = "删除猪舍"
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
	}

	if err := c.service.DeletePigHouse(reqCtx, uint32(id)); err != nil {
		if errors.Is(err, service.ErrHouseNotFound) {
			return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪舍不存在", action, "猪舍不存在", id)
		}
		// 检查是否是业务逻辑错误
		if errors.Is(err, service.ErrHouseContainsPens) {
			return controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), action, err.Error(), id)
		}
		logger.Errorf("%s: 业务逻辑失败: %v", action, err)
		return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "删除失败", action, "业务逻辑失败", id)
	}

	return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "删除成功", nil, action, "删除成功", id)
}

// --- 猪栏 (Pen) API 实现 ---

// CreatePen godoc
// @Summary      创建猪栏
// @Description  创建一个新的猪栏
// @Tags         猪场管理
// @Security     BearerAuth
// @Accept       json
// @Produce      json
// @Param        body body dto.CreatePenRequest true "猪栏信息"
// @Success      201 {object} controller.Response{data=dto.PenResponse} "创建成功"
// @Router       /api/v1/pens [post]
func (c *PigFarmController) CreatePen(ctx echo.Context) error {
	reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "CreatePen")
	const action = "创建猪栏"
	var req dto.CreatePenRequest
	if err := ctx.Bind(&req); err != nil {
		return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req)
	}

	pen, err := c.service.CreatePen(reqCtx, req.PenNumber, req.HouseID, req.Capacity)
	if err != nil {
		// 检查是否是业务逻辑错误
		if errors.Is(err, service.ErrHouseNotFound) {
			return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), action, err.Error(), req)
		}
		logger.Errorf("%s: 业务逻辑失败: %v", action, err)
		return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "创建猪栏失败", action, "业务逻辑失败", req)
	}

	return controller.SendSuccessWithAudit(ctx, controller.CodeCreated, "创建成功", pen, action, "创建成功", pen)
}

// GetPen godoc
// @Summary      获取单个猪栏
// @Description  根据ID获取单个猪栏信息
// @Tags         猪场管理
// @Security     BearerAuth
// @Produce      json
// @Param        id path int true "猪栏ID"
// @Success      200 {object} controller.Response{data=dto.PenResponse} "获取成功"
// @Router       /api/v1/pens/{id} [get]
func (c *PigFarmController) GetPen(ctx echo.Context) error {
	reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "GetPen")
	const action = "获取猪栏"
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
	}

	pen, err := c.service.GetPenByID(reqCtx, uint32(id))
	if err != nil {
		if errors.Is(err, service.ErrPenNotFound) {
			return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪栏不存在", action, "猪栏不存在", id)
		}
		logger.Errorf("%s: 业务逻辑失败: %v", action, err)
		return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取猪栏失败", action, "业务逻辑失败", id)
	}

	return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取成功", pen, action, "获取成功", pen)
}

// ListPens godoc
// @Summary      获取猪栏列表
// @Description  获取所有猪栏的列表
// @Tags         猪场管理
// @Security     BearerAuth
// @Produce      json
// @Success      200 {object} controller.Response{data=[]dto.PenResponse} "获取成功"
// @Router       /api/v1/pens [get]
func (c *PigFarmController) ListPens(ctx echo.Context) error {
	reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "ListPens")
	const action = "获取猪栏列表"
	pens, err := c.service.ListPens(reqCtx)
	if err != nil {
		logger.Errorf("%s: 业务逻辑失败: %v", action, err)
		return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "获取列表失败", action, "业务逻辑失败", nil)
	}

	return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "获取成功", pens, action, "获取成功", pens)
}

// UpdatePen godoc
// @Summary      更新猪栏
// @Description  更新一个已存在的猪栏信息
// @Tags         猪场管理
// @Security     BearerAuth
// @Accept       json
// @Produce      json
// @Param        id path int true "猪栏ID"
// @Param        body body dto.UpdatePenRequest true "猪栏信息"
// @Success      200 {object} controller.Response{data=dto.PenResponse} "更新成功"
// @Router       /api/v1/pens/{id} [put]
func (c *PigFarmController) UpdatePen(ctx echo.Context) error {
	reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "UpdatePen")
	const action = "更新猪栏"
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
	}

	var req dto.UpdatePenRequest
	if err := ctx.Bind(&req); err != nil {
		return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req)
	}

	pen, err := c.service.UpdatePen(reqCtx, uint32(id), req.PenNumber, req.HouseID, req.Capacity, req.Status)
	if err != nil {
		if errors.Is(err, service.ErrPenNotFound) {
			return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪栏不存在", action, "猪栏不存在", id)
		}
		// 其他业务逻辑错误可以在这里添加处理
		logger.Errorf("%s: 业务逻辑失败: %v", action, err)
		return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新失败", action, "业务逻辑失败", req)
	}

	return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "更新成功", pen, action, "更新成功", pen)
}

// DeletePen godoc
// @Summary      删除猪栏
// @Description  根据ID删除一个猪栏
// @Tags         猪场管理
// @Security     BearerAuth
// @Produce      json
// @Param        id path int true "猪栏ID"
// @Success      200 {object} controller.Response "删除成功"
// @Router       /api/v1/pens/{id} [delete]
func (c *PigFarmController) DeletePen(ctx echo.Context) error {
	reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "DeletePen")
	const action = "删除猪栏"
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
	}

	if err := c.service.DeletePen(reqCtx, uint32(id)); err != nil {
		if errors.Is(err, service.ErrPenNotFound) {
			return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, "猪栏不存在", action, "猪栏不存在", id)
		}
		// 检查是否是业务逻辑错误
		if errors.Is(err, service.ErrPenInUse) {
			return controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), action, err.Error(), id)
		}
		logger.Errorf("%s: 业务逻辑失败: %v", action, err)
		return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "删除失败", action, "业务逻辑失败", id)
	}

	return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "删除成功", nil, action, "删除成功", id)
}

// UpdatePenStatus godoc
// @Summary      更新猪栏状态
// @Description  更新指定猪栏的当前状态
// @Tags         猪场管理
// @Security     BearerAuth
// @Accept       json
// @Produce      json
// @Param        id path int true "猪栏ID"
// @Param        body body dto.UpdatePenStatusRequest true "新的猪栏状态"
// @Success      200 {object} controller.Response{data=dto.PenResponse} "更新成功"
// @Router       /api/v1/pens/{id}/status [put]
func (c *PigFarmController) UpdatePenStatus(ctx echo.Context) error {
	reqCtx, logger := logs.Trace(ctx.Request().Context(), c.ctx, "UpdatePenStatus")
	const action = "更新猪栏状态"
	id, err := strconv.ParseUint(ctx.Param("id"), 10, 32)
	if err != nil {
		return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的ID格式", action, "ID格式错误", ctx.Param("id"))
	}

	var req dto.UpdatePenStatusRequest
	if err := ctx.Bind(&req); err != nil {
		return controller.SendErrorWithAudit(ctx, controller.CodeBadRequest, "无效的请求体", action, "请求体绑定失败", req)
	}

	pen, err := c.service.UpdatePenStatus(reqCtx, uint32(id), req.Status)
	if err != nil {
		if errors.Is(err, service.ErrPenNotFound) {
			return controller.SendErrorWithAudit(ctx, controller.CodeNotFound, err.Error(), action, err.Error(), id)
		} else if errors.Is(err, service.ErrPenStatusInvalidForOccupiedPen) || errors.Is(err, service.ErrPenStatusInvalidForUnoccupiedPen) {
			return controller.SendErrorWithAudit(ctx, controller.CodeConflict, err.Error(), action, err.Error(), id)
		}
		logger.Errorf("%s: 业务逻辑失败: %v", action, err)
		return controller.SendErrorWithAudit(ctx, controller.CodeInternalError, "更新猪栏状态失败", action, err.Error(), id)
	}

	return controller.SendSuccessWithAudit(ctx, controller.CodeSuccess, "更新成功", pen, action, "更新成功", pen)
}
