package api

// @title 猪场管理系统 API
// @version 1.0
// @description 这是一个用于管理猪场设备的后端服务。
// @contact.name Divano
// @contact.url http://www.example.com
// @contact.email divano@example.com
// @license.name Apache 2.0
// @license.url http://www.apache.org/licenses/LICENSE-2.0.html
// @securityDefinitions.apikey BearerAuth
// @in header
// @name Authorization

import (
	"context"
	"fmt"
	"net/http"
	"time"

	_ "git.huangwc.com/pig/pig-farm-controller/docs" // 引入 swag 生成的 docs
	"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/alarm"
	"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/device"
	"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/feed"
	"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/health"
	"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/inventory"
	"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/management"
	"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/monitor"
	"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/plan"
	"git.huangwc.com/pig/pig-farm-controller/internal/app/controller/user"
	"git.huangwc.com/pig/pig-farm-controller/internal/app/listener"
	"git.huangwc.com/pig/pig-farm-controller/internal/app/service"
	domain_plan "git.huangwc.com/pig/pig-farm-controller/internal/domain/plan"
	"git.huangwc.com/pig/pig-farm-controller/internal/infra/config"
	"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
	"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
	"git.huangwc.com/pig/pig-farm-controller/internal/infra/utils/token"

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

// API 结构体定义了 HTTP 服务器及其依赖
type API struct {
	echo                  *echo.Echo                           // Echo 引擎实例，用于处理 HTTP 请求
	Ctx                   context.Context                      // API 组件的上下文，包含日志记录器
	userRepo              repository.UserRepository            // 用户数据仓库接口，用于用户数据操作
	tokenGenerator        token.Generator                      // Token 服务接口，用于 JWT token 的生成和解析
	auditService          service.AuditService                 // 审计服务，用于记录用户操作
	httpServer            *http.Server                         // 标准库的 HTTP 服务器实例，用于启动和停止服务
	config                config.ServerConfig                  // API 服务器的配置，使用 infra/config 包中的 ServerConfig
	userController        *user.Controller                     // 用户控制器实例
	deviceController      *device.Controller                   // 设备控制器实例
	planController        *plan.Controller                     // 计划控制器实例
	pigFarmController     *management.PigFarmController        // 猪场管理控制器实例
	pigBatchController    *management.PigBatchController       // 猪群控制器实例
	monitorController     *monitor.Controller                  // 数据监控控制器实例
	healthController      *health.Controller                   // 健康检查控制器实例
	alarmController       *alarm.ThresholdAlarmController      // 阈值告警控制器
	nutrientController    *feed.NutrientController             // 营养控制器实例
	pigAgeStageController *feed.PigAgeStageController          // 猪龄阶段控制器实例
	pigBreedController    *feed.PigBreedController             // 猪品种控制器实例
	pigTypeController     *feed.PigTypeController              // 猪种类控制器实例
	rawMaterialController *feed.RawMaterialController          // 原料控制器实例
	recipeController      *feed.RecipeController               // 配方控制器实例
	inventoryController   *inventory.InventoryController       // 库存控制器实例
	listenHandler         listener.ListenHandler               // 设备上行事件监听器
	analysisTaskManager   *domain_plan.AnalysisPlanTaskManager // 计划触发器管理器实例
}

// NewAPI 创建并返回一个新的 API 实例
// 负责初始化 Echo 引擎、设置全局中间件，并注入所有必要的依赖。
func NewAPI(cfg config.ServerConfig,
	ctx context.Context,
	userRepo repository.UserRepository,
	pigFarmService service.PigFarmService,
	pigBatchService service.PigBatchService,
	monitorService service.MonitorService,
	deviceService service.DeviceService,
	planService service.PlanService,
	userService service.UserService,
	auditService service.AuditService,
	alarmService service.ThresholdAlarmService,
	nutrientService service.NutrientService,
	rawMaterialService service.RawMaterialService,
	pigBreedService service.PigBreedService,
	pigAgeStageService service.PigAgeStageService,
	pigTypeService service.PigTypeService,
	recipeService service.RecipeService,
	inventoryService service.InventoryService,
	tokenGenerator token.Generator,
	listenHandler listener.ListenHandler,
) *API {
	// 使用 echo.New() 创建一个 Echo 引擎实例
	e := echo.New()

	// 根据配置设置 Echo 的调试模式
	e.Debug = cfg.Mode == "debug"

	// 添加 Echo Recovery 中间件，用于捕获 panic 并恢复，防止服务崩溃
	// Echo 的 Logger 中间件默认会记录请求信息，如果需要自定义，可以替换
	e.Use(middleware.Recover())

	// 初始化 API 结构体
	baseCtx := context.Background()
	api := &API{
		echo:                  e,
		Ctx:                   ctx,
		userRepo:              userRepo,
		tokenGenerator:        tokenGenerator,
		auditService:          auditService,
		config:                cfg,
		listenHandler:         listenHandler,
		userController:        user.NewController(logs.AddCompName(baseCtx, "UserController"), userService),
		deviceController:      device.NewController(logs.AddCompName(baseCtx, "DeviceController"), deviceService),
		planController:        plan.NewController(logs.AddCompName(baseCtx, "PlanController"), planService),
		pigFarmController:     management.NewPigFarmController(logs.AddCompName(baseCtx, "PigFarmController"), pigFarmService),
		pigBatchController:    management.NewPigBatchController(logs.AddCompName(baseCtx, "PigBatchController"), pigBatchService),
		monitorController:     monitor.NewController(logs.AddCompName(baseCtx, "MonitorController"), monitorService),
		healthController:      health.NewController(logs.AddCompName(baseCtx, "HealthController")),
		alarmController:       alarm.NewThresholdAlarmController(logs.AddCompName(baseCtx, "ThresholdAlarmController"), alarmService),
		nutrientController:    feed.NewNutrientController(logs.AddCompName(baseCtx, "NutrientController"), nutrientService),
		pigAgeStageController: feed.NewPigAgeStageController(logs.AddCompName(baseCtx, "PigAgeStageController"), pigAgeStageService),
		pigBreedController:    feed.NewPigBreedController(logs.AddCompName(baseCtx, "PigBreedController"), pigBreedService),
		pigTypeController:     feed.NewPigTypeController(logs.AddCompName(baseCtx, "PigTypeController"), pigTypeService),
		rawMaterialController: feed.NewRawMaterialController(logs.AddCompName(baseCtx, "RawMaterialController"), rawMaterialService),
		recipeController:      feed.NewRecipeController(logs.AddCompName(baseCtx, "RecipeController"), recipeService),
		inventoryController:   inventory.NewInventoryController(logs.AddCompName(baseCtx, "InventoryController"), inventoryService),
	}

	api.setupRoutes() // 设置所有路由
	return api
}

// Start 启动 HTTP 服务器
// 接收一个地址字符串 (例如 ":8080")，并在一个新的 goroutine 中启动服务器，
// 以便主线程可以继续执行其他任务（例如监听操作系统信号）。
func (a *API) Start() {
	logger := logs.TraceLogger(a.Ctx, a.Ctx, "Start")
	// 构建监听地址字符串
	addr := fmt.Sprintf(":%d", a.config.Port)

	// 初始化标准库的 http.Server 实例
	a.httpServer = &http.Server{
		Addr:    addr,   // 服务器监听的地址从配置中获取
		Handler: a.echo, // 将 Echo 引擎作为 HTTP 请求的处理程序
	}

	// 在独立的 goroutine 中启动服务器
	// ListenAndServe 会阻塞，所以放在 goroutine 中可以避免阻塞主线程
	go func() {
		// 启动服务器，并检查错误。http.ErrServerClosed 是正常关闭时的错误，无需处理。
		if err := a.httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed {
			logger.Fatalf("HTTP 服务器监听失败: %s", err)
		}
	}()
	// 记录服务器已启动的信息
	logger.Infof("HTTP 服务器正在监听 %s", addr)
}

// Stop 优雅地停止 HTTP 服务器
// 在停止服务器时，会给一个超时时间，确保正在处理的请求能够完成。
func (a *API) Stop() {
	logger := logs.TraceLogger(a.Ctx, a.Ctx, "Stop")
	// 记录服务器正在关闭的信息
	logger.Info("正在关闭 HTTP 服务器...")

	// 创建一个带有 5 秒超时时间的上下文
	// 在此时间内，服务器会尝试完成所有活跃的连接。
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel() // 确保上下文在函数退出时被取消，释放资源

	// 尝试优雅地关闭 HTTP 服务器
	// 如果在超时时间内未能关闭，Shutdown 会返回错误。
	if err := a.httpServer.Shutdown(ctx); err != nil {
		// 如果关闭失败，记录致命错误并退出
		logger.Fatalf("HTTP 服务器关闭失败: %s", err)
	}
	// 记录服务器已停止的信息
	logger.Info("HTTP 服务器已停止。")
}
