package admin

import (
	"encoding/json"
	"fmt"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"com.sclktx/m/v2/internal/common/model"
	"com.sclktx/m/v2/internal/common/response"
	"com.sclktx/m/v2/internal/common/utils"
	"com.sclktx/m/v2/internal/pkg/wechat"

	"github.com/gin-gonic/gin"
	"github.com/xuri/excelize/v2"
	"gorm.io/gorm"
)

// AdminHandler 管理员处理器
type AdminHandler struct {
	db       *gorm.DB
	wxClient *wechat.MiniProgramClient
}

func NewAdminHandler(db *gorm.DB, wxClient *wechat.MiniProgramClient) *AdminHandler {
	return &AdminHandler{db: db, wxClient: wxClient}
}

// ============ 用户管理 ============

// UserVO 用户视图对象
type UserVO struct {
	ID        uint   `json:"id"`
	Openid    string `json:"openid"`
	Nickname  string `json:"nickname"`
	RealName  string `json:"real_name"`
	Phone     string `json:"phone"`
	AvatarURL string `json:"avatar_url"`
	Role      string `json:"role"`
	RoleName  string `json:"role_name"`
	Status    int    `json:"status"`
	CreatedAt string `json:"created_at"`
}

// roleName 角色编码转中文名
func roleName(code string) string {
	switch code {
	case "employee":
		return "员工"
	case "guard":
		return "保安"
	default:
		return "访客"
	}
}

// @Summary      用户列表
// @Description  分页查询用户列表，支持关键词搜索
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        page      query     int     false  "页码"   default(1)
// @Param        page_size query     int     false  "每页数量"  default(10)
// @Param        keyword   query     string  false  "搜索关键词（姓名/昵称/手机号）"
// @Success      200  {object}  response.Response{data=response.PageData{list=[]UserVO}}  "成功"
// @Router       /admin/users [get]

// ListUsers 用户列表
func (h *AdminHandler) ListUsers(c *gin.Context) {
	page, pageSize := utils.ParsePagination(c)
	keyword := c.DefaultQuery("keyword", "")
	userType := c.DefaultQuery("type", "") // employee / visitor / guard
	statusStr := c.DefaultQuery("status", "")

	var users []model.User
	var total int64

	query := h.db.Model(&model.User{})
	if keyword != "" {
		query = query.Where("real_name LIKE ? OR nickname LIKE ? OR phone LIKE ?",
			"%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%")
	}
	if userType != "" {
		query = query.Where("role = ?", userType)
	}
	if statusStr != "" {
		query = query.Where("status = ?", statusStr)
	}

	query.Count(&total)
	query.Offset(utils.GetOffset(page, pageSize)).Limit(pageSize).Order("created_at DESC, id DESC").Find(&users)

	var vos []UserVO
	for _, u := range users {
		vos = append(vos, userToVO(&u))
	}

	response.SuccessPage(c, vos, total, page, pageSize)
}

// @Summary      更新用户信息
// @Description  管理员更新用户信息（昵称、姓名、手机号、状态、角色等）
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        id    path  int         true  "用户ID"
// @Param        body  body  object{real_name=string,nickname=string,phone=string,status=int,role=string}  true  "更新信息"
// @Success      200   {object}  response.Response  "成功"
// @Router       /admin/users/{id} [put]

// UpdateUser 更新用户信息（管理员操作）
func (h *AdminHandler) UpdateUser(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "参数错误")
		return
	}

	var req struct {
		RealName string `json:"real_name"`
		Nickname string `json:"nickname"`
		Phone    string `json:"phone"`
		Status   *int   `json:"status"`
		Role     string `json:"role"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "参数错误")
		return
	}

	updates := map[string]interface{}{}
	if req.RealName != "" {
		updates["real_name"] = req.RealName
	}
	if req.Nickname != "" {
		updates["nickname"] = req.Nickname
	}
	if req.Phone != "" {
		updates["phone"] = req.Phone
	}
	if req.Status != nil {
		updates["status"] = *req.Status
	}
	if req.Role != "" {
		updates["role"] = req.Role
	}

	if err := h.db.Model(&model.User{}).Where("id = ?", id).Updates(updates).Error; err != nil {
		response.InternalError(c, "更新失败")
		return
	}

	// 如果设为员工角色且尚无 Employee 记录，自动创建
	if req.Role == "employee" {
		var count int64
		h.db.Model(&model.UserDepartment{}).Where("user_id = ?", id).Count(&count)
		if count == 0 {
			h.db.Model(&model.User{}).Where("id = ?", id).Update("role", "employee")
			// 同时创建 UserDepartment 记录
			h.db.Create(&model.UserDepartment{
				UserID:         uint(id),
				EmployeeStatus: 1,
				EmployeeType:   "employee",
			})
		} else {
			h.db.Model(&model.User{}).Where("id = ?", id).Update("role", "employee")
			h.db.Model(&model.UserDepartment{}).Where("user_id = ?", id).Update("employee_status", 1)
		}
	}

	response.SuccessWithMessage(c, "更新成功", nil)
}

func userToVO(u *model.User) UserVO {
	code := u.Role
	if code == "" {
		code = "visitor"
	}
	return UserVO{
		ID:        u.ID,
		Openid:    u.Openid,
		Nickname:  u.Nickname,
		RealName:  u.RealName,
		Phone:     u.Phone,
		AvatarURL: u.AvatarURL,
		Status:    u.Status,
		Role:      code,
		RoleName:  roleName(code),
		CreatedAt: u.CreatedAt.Format("2006-01-02 15:04:05"),
	}
}

// RegisterRoutes 注册管理路由
func (h *AdminHandler) RegisterRoutes(r *gin.RouterGroup, jwtMiddleware gin.HandlerFunc) {
	admin := r.Group("/admin")
	admin.Use(jwtMiddleware)
	{
		// 用户管理
		admin.GET("/users", h.ListUsers)
		admin.PUT("/users/:id", h.UpdateUser)

		// Banner 管理
		admin.GET("/banners", h.ListBanners)

		// 员工列表（审批配置用）
		admin.GET("/employees", h.ListEmployees)
		admin.POST("/banners", h.CreateBanner)
		admin.PUT("/banners/:id", h.UpdateBanner)
		admin.DELETE("/banners/:id", h.DeleteBanner)

		// 通知管理
		admin.GET("/notices", h.ListNotices)
		admin.POST("/notices", h.CreateNotice)
		admin.PUT("/notices/:id", h.UpdateNotice)
		admin.DELETE("/notices/:id", h.DeleteNotice)

		// 组织架构（部门树）
		admin.GET("/departments", h.ListDepartments)

		// 员工认证审核
		admin.GET("/certifications", h.ListCertifications)
		admin.PUT("/certifications/:id/audit", h.AuditCertification)

		// 部门管理（树形结构）
		admin.GET("/department-tree", h.ListDepartmentTree)
		admin.GET("/departments-all", h.ListAllDepartments)
		admin.POST("/departments", h.CreateDepartment)
		admin.PUT("/departments/:id", h.UpdateDepartment)
		admin.DELETE("/departments/:id", h.DeleteDepartment)

		// 员工-部门关联
		admin.PUT("/employees/:userId/department", h.SetEmployeeDepartment)
		admin.DELETE("/employees/:userId/department", h.ClearEmployeeDepartment)
		admin.GET("/employee-departments", h.ListEmployeeDepartments)

		// 到访区域管理
		admin.GET("/visitor-areas", h.ListVisitorAreas)
		admin.POST("/visitor-areas", h.CreateVisitorArea)
		admin.PUT("/visitor-areas/:id", h.UpdateVisitorArea)
		admin.DELETE("/visitor-areas/:id", h.DeleteVisitorArea)

		// 来访目的管理
		admin.GET("/visit-types", h.ListVisitTypes)
		admin.POST("/visit-types", h.CreateVisitType)
		admin.PUT("/visit-types/:id", h.UpdateVisitType)
		admin.DELETE("/visit-types/:id", h.DeleteVisitType)

		// 预约管理（仅查看，审核走工作流引擎）
		admin.GET("/appointments", h.ListAppointments)

		// 审批流配置：部门分管领导（存储在 department.vp_user_ids）
		admin.PUT("/departments/:id/vp-users", h.SetDepartmentVPs)

		// 审批流配置：设置部门指定审批人
		admin.PUT("/departments/:id/approver", h.SetDepartmentApprover)

		// 待确认员工管理（通讯录导入）
		admin.POST("/employees/import", h.ImportPendingEmployees)
		admin.POST("/employees/import-excel", h.ImportPendingEmployeesExcel)
		admin.GET("/employees/pending", h.ListPendingEmployees)
		admin.GET("/employees/pending/stats", h.GetPendingEmployeeStats)
		admin.POST("/employees/pending/:id/match", h.MatchPendingEmployee)
		admin.POST("/employees/pending/sync-all", h.SyncAllPendingEmployees)

		// 全局兜底审批人
		admin.GET("/global-approvers", h.ListGlobalApprovers)
		admin.POST("/global-approvers", h.CreateGlobalApprover)
		admin.DELETE("/global-approvers/:id", h.DeleteGlobalApprover)
	}
}

// ============ Banner 管理 ============

// @Summary      Banner列表
// @Description  获取所有Banner列表，按排序字段升序
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Success      200  {object}  response.Response{data=[]model.Banner}  "成功"
// @Router       /admin/banners [get]

// ListBanners Banner 列表
func (h *AdminHandler) ListBanners(c *gin.Context) {
	var banners []model.Banner
	h.db.Order("sort ASC").Find(&banners)
	response.Success(c, banners)
}

// @Summary      创建Banner
// @Description  创建一个新的Banner
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        body  body  object{image_url=string,jump_path=string,is_jump=bool,sort=int}  true  "Banner信息"
// @Success      200   {object}  response.Response{data=model.Banner}  "成功"
// @Router       /admin/banners [post]

// CreateBanner 创建 Banner
func (h *AdminHandler) CreateBanner(c *gin.Context) {
	var req struct {
		ImageURL string `json:"image_url" binding:"required"`
		JumpPath string `json:"jump_path"`
		IsJump   bool   `json:"is_jump"`
		Sort     int    `json:"sort"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "参数错误")
		return
	}
	banner := model.Banner{
		ImageURL: req.ImageURL,
		JumpPath: req.JumpPath,
		IsJump:   req.IsJump,
		Sort:     req.Sort,
		IsValid:  true,
	}
	if err := h.db.Create(&banner).Error; err != nil {
		response.InternalError(c, "创建失败")
		return
	}
	response.SuccessWithMessage(c, "创建成功", banner)
}

// @Summary      更新Banner
// @Description  更新指定Banner的信息
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        id    path  int     true  "Banner ID"
// @Param        body  body  object{image_url=string,jump_path=string,is_jump=bool,sort=int,is_valid=bool}  true  "更新信息"
// @Success      200   {object}  response.Response  "成功"
// @Router       /admin/banners/{id} [put]

// UpdateBanner 更新 Banner
func (h *AdminHandler) UpdateBanner(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "参数错误")
		return
	}
	var banner model.Banner
	if err := h.db.First(&banner, id).Error; err != nil {
		response.NotFound(c, "Banner 不存在")
		return
	}
	var req struct {
		ImageURL string `json:"image_url"`
		JumpPath string `json:"jump_path"`
		IsJump   *bool  `json:"is_jump"`
		Sort     *int   `json:"sort"`
		IsValid  *bool  `json:"is_valid"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "参数错误")
		return
	}
	updates := map[string]interface{}{}
	if req.ImageURL != "" {
		updates["image_url"] = req.ImageURL
	}
	if req.JumpPath != "" {
		updates["jump_path"] = req.JumpPath
	}
	if req.IsJump != nil {
		updates["is_jump"] = *req.IsJump
	}
	if req.Sort != nil {
		updates["sort"] = *req.Sort
	}
	if req.IsValid != nil {
		updates["is_valid"] = *req.IsValid
	}
	if err := h.db.Model(&banner).Updates(updates).Error; err != nil {
		response.InternalError(c, "更新失败")
		return
	}
	response.SuccessWithMessage(c, "更新成功", nil)
}

// @Summary      删除Banner
// @Description  删除指定Banner
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        id  path  int  true  "Banner ID"
// @Success      200  {object}  response.Response  "成功"
// @Router       /admin/banners/{id} [delete]

// DeleteBanner 删除 Banner
func (h *AdminHandler) DeleteBanner(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "参数错误")
		return
	}
	if err := h.db.Delete(&model.Banner{}, id).Error; err != nil {
		response.InternalError(c, "删除失败")
		return
	}
	response.SuccessWithMessage(c, "删除成功", nil)
}

// ============ 通知管理 ============

// @Summary      通知列表
// @Description  获取所有通知列表，按排序字段升序
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Success      200  {object}  response.Response{data=[]model.Notice}  "成功"
// @Router       /admin/notices [get]

// ListNotices 通知列表
func (h *AdminHandler) ListNotices(c *gin.Context) {
	var notices []model.Notice
	h.db.Order("sort ASC").Find(&notices)
	response.Success(c, notices)
}

// @Summary      创建通知
// @Description  创建一个新的通知
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        body  body  object{title=string,content=string,sort=int}  true  "通知信息"
// @Success      200   {object}  response.Response{data=model.Notice}  "成功"
// @Router       /admin/notices [post]

// CreateNotice 创建通知
func (h *AdminHandler) CreateNotice(c *gin.Context) {
	var req struct {
		Title   string `json:"title" binding:"required"`
		Content string `json:"content" binding:"required"`
		Sort    int    `json:"sort"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "参数错误")
		return
	}
	notice := model.Notice{
		Title:   req.Title,
		Content: req.Content,
		Sort:    req.Sort,
		IsValid: true,
	}
	if err := h.db.Create(&notice).Error; err != nil {
		response.InternalError(c, "创建失败")
		return
	}
	response.SuccessWithMessage(c, "创建成功", notice)
}

// @Summary      更新通知
// @Description  更新指定通知的信息
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        id    path  int     true  "通知ID"
// @Param        body  body  object{title=string,content=string,sort=int,is_valid=bool}  true  "更新信息"
// @Success      200   {object}  response.Response  "成功"
// @Router       /admin/notices/{id} [put]

// UpdateNotice 更新通知
func (h *AdminHandler) UpdateNotice(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "参数错误")
		return
	}
	var notice model.Notice
	if err := h.db.First(&notice, id).Error; err != nil {
		response.NotFound(c, "通知不存在")
		return
	}
	var req struct {
		Title   string `json:"title"`
		Content string `json:"content"`
		Sort    *int   `json:"sort"`
		IsValid *bool  `json:"is_valid"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "参数错误")
		return
	}
	updates := map[string]interface{}{}
	if req.Title != "" {
		updates["title"] = req.Title
	}
	if req.Content != "" {
		updates["content"] = req.Content
	}
	if req.Sort != nil {
		updates["sort"] = *req.Sort
	}
	if req.IsValid != nil {
		updates["is_valid"] = *req.IsValid
	}
	if err := h.db.Model(&notice).Updates(updates).Error; err != nil {
		response.InternalError(c, "更新失败")
		return
	}
	response.SuccessWithMessage(c, "更新成功", nil)
}

// @Summary      删除通知
// @Description  删除指定通知
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        id  path  int  true  "通知ID"
// @Success      200  {object}  response.Response  "成功"
// @Router       /admin/notices/{id} [delete]

// DeleteNotice 删除通知
func (h *AdminHandler) DeleteNotice(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "参数错误")
		return
	}
	if err := h.db.Delete(&model.Notice{}, id).Error; err != nil {
		response.InternalError(c, "删除失败")
		return
	}
	response.SuccessWithMessage(c, "删除成功", nil)
}

// ============ 员工列表 ============

// @Summary      员工列表
// @Description  获取所有员工列表（供审批配置选择用），包含正式员工和role为employee的用户
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Success      200  {object}  response.Response{data=[]object{id=uint,user_id=uint,name=string,department_name=string}}  "成功"
// @Router       /admin/employees [get]

// ListEmployees 员工列表（供审批配置选择用）
func (h *AdminHandler) ListEmployees(c *gin.Context) {
	type EmployeeItem struct {
		ID             uint   `json:"id"`
		UserID         uint   `json:"user_id"`
		Name           string `json:"name"`
		DepartmentName string `json:"department_name"`
		Position       string `json:"position"`
		EmployeeType   string `json:"employee_type"`
	}

	var items []EmployeeItem

	// 查询所有状态正常的 role=employee 用户，左连接 user_departments 获取部门信息
	var rows []struct {
		model.User
		DeptName     string `gorm:"column:dept_name"`
		DeptPosition string `gorm:"column:dept_position"`
		DeptType     string `gorm:"column:dept_employee_type"`
	}
	h.db.Table("users").
		Select("users.*, COALESCE(ud.department_name, '') as dept_name, COALESCE(ud.position, '') as dept_position, COALESCE(ud.employee_type, 'employee') as dept_employee_type").
		Joins("LEFT JOIN user_departments ud ON ud.user_id = users.id").
		Where("users.role = ? AND users.status = ?", "employee", 1).
		Order("users.real_name ASC").
		Scan(&rows)

	employeeUserIDs := make(map[uint]bool)
	for _, r := range rows {
		employeeUserIDs[r.User.ID] = true
		name := r.User.RealName
		if name == "" {
			name = r.User.RealName
		}
		items = append(items, EmployeeItem{
			ID:             r.User.ID,
			UserID:         r.User.ID,
			Name:           name,
			DepartmentName: r.DeptName,
			Position:       r.DeptPosition,
			EmployeeType:   r.DeptType,
		})
	}

	// 补充 role='employee' 但尚未有关联记录的用户（兼容旧数据）
	var users []model.User
	h.db.Where("role = ? AND status = ?", "employee", 1).Find(&users)
	for _, u := range users {
		if !employeeUserIDs[u.ID] {
			items = append(items, EmployeeItem{
				ID:             u.ID,
				UserID:         u.ID,
				Name:           u.RealName,
				DepartmentName: "",
				Position:       "",
				EmployeeType:   "employee",
			})
		}
	}

	if items == nil {
		items = []EmployeeItem{}
	}
	response.Success(c, items)
}

// ============ 组织架构 ============

// DepartmentVO 部门视图
type DepartmentVO struct {
	Name      string          `json:"name"`
	Employees []EmployeeBrief `json:"employees"`
}

// EmployeeBrief 员工简要信息
type EmployeeBrief struct {
	ID           uint   `json:"id"`
	UserID       uint   `json:"user_id"`
	Name         string `json:"name"`
	Phone        string `json:"phone"`
	Position     string `json:"position"`
	EmployeeType string `json:"employee_type"`
}

// @Summary      组织架构
// @Description  获取组织架构列表，按部门分组显示员工
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Success      200  {object}  response.Response{data=[]DepartmentVO}  "成功"
// @Router       /admin/departments [get]

// ListDepartments 获取组织架构（按部门分组）
func (h *AdminHandler) ListDepartments(c *gin.Context) {
	type EmpRow struct {
		model.User
		DeptName     string `gorm:"column:dept_name"`
		DeptPosition string `gorm:"column:dept_position"`
		DeptType     string `gorm:"column:dept_employee_type"`
	}
	var rows []EmpRow
	h.db.Table("users").
		Select("users.*, COALESCE(ud.department_name, '') as dept_name, COALESCE(ud.position, '') as dept_position, COALESCE(ud.employee_type, 'employee') as dept_employee_type").
		Joins("LEFT JOIN user_departments ud ON ud.user_id = users.id").
		Where("users.status = ?", 1).
		Order("dept_name ASC, users.real_name ASC").
		Scan(&rows)

	depMap := make(map[string][]EmployeeBrief)
	for _, r := range rows {
		dept := r.DeptName
		if dept == "" {
			dept = "未分配部门"
		}
		depMap[dept] = append(depMap[dept], EmployeeBrief{
			ID:           r.User.ID,
			UserID:       r.User.ID,
			Name:         r.User.RealName,
			Phone:        r.User.Phone,
			Position:     r.DeptPosition,
			EmployeeType: r.DeptType,
		})
	}

	var depts []DepartmentVO
	for name, emps := range depMap {
		depts = append(depts, DepartmentVO{Name: name, Employees: emps})
	}

	response.Success(c, depts)
}

// ============ 员工认证审核 ============

// @Summary      员工认证申请列表
// @Description  分页查询员工认证申请列表，支持按状态筛选和关键词搜索
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        page      query  int     false  "页码"   default(1)
// @Param        page_size query  int     false  "每页数量"  default(10)
// @Param        status    query  int     false  "审核状态（0待审核 1通过 2拒绝）"
// @Param        keyword   query  string  false  "搜索关键词"
// @Success      200  {object}  response.Response{data=response.PageData{list=[]model.EmployeeCertification}}  "成功"
// @Router       /admin/certifications [get]

// ListCertifications 员工认证申请列表
func (h *AdminHandler) ListCertifications(c *gin.Context) {
	page, pageSize := utils.ParsePagination(c)
	statusStr := c.DefaultQuery("status", "")
	keyword := c.Query("keyword")

	var certs []model.EmployeeCertification
	var total int64

	query := h.db.Model(&model.EmployeeCertification{}).
		Preload("User").
		Preload("Department").
		Preload("Approver")
	if statusStr != "" {
		status, _ := strconv.Atoi(statusStr)
		query = query.Where("status = ?", status)
	}
	if keyword != "" {
		query = query.Where("real_name LIKE ? OR phone LIKE ?", "%"+keyword+"%", "%"+keyword+"%")
	}

	query.Count(&total)
	query.Offset(utils.GetOffset(page, pageSize)).Limit(pageSize).Order("created_at DESC").Find(&certs)

	response.SuccessPage(c, certs, total, page, pageSize)
}

// @Summary      审核员工认证
// @Description  审核员工认证申请（通过/拒绝），通过时需分配部门
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        id    path  int     true  "认证申请ID"
// @Param        body  body  object{status=int,department_id=uint,comment=string}  true  "审核信息（status:1通过 2拒绝）"
// @Success      200   {object}  response.Response  "成功"
// @Router       /admin/certifications/{id}/audit [put]

// AuditCertification 审核员工认证申请
func (h *AdminHandler) AuditCertification(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "参数错误")
		return
	}

	var req struct {
		Status       int    `json:"status" binding:"required"` // 1 通过 2 拒绝
		RealName     string `json:"real_name"`
		Phone        string `json:"phone"`
		DepartmentID *uint  `json:"department_id"`
		Position     string `json:"position"`
		Role         string `json:"role"`
		Comment      string `json:"comment"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "参数错误")
		return
	}

	if req.Status != 1 && req.Status != 2 {
		response.BadRequest(c, "状态值无效")
		return
	}

	var cert model.EmployeeCertification
	if err := h.db.First(&cert, id).Error; err != nil {
		response.NotFound(c, "申请不存在")
		return
	}

	if cert.Status != 0 {
		response.BadRequest(c, "该申请已处理")
		return
	}

	approverID := utils.GetUserID(c)

	realName := req.RealName
	if realName == "" {
		realName = cert.RealName
	}
	phone := req.Phone
	if phone == "" {
		phone = cert.Phone
	}

	updates := map[string]interface{}{
		"status":      req.Status,
		"approver_id": approverID,
		"real_name":   realName,
		"phone":       phone,
		"comment":     req.Comment,
	}

	// 如果通过，设置分配的部门、职位、角色类型
	if req.Status == 1 {
		if req.DepartmentID == nil {
			response.BadRequest(c, "通过时必须分配部门")
			return
		}
		var dept model.Department
		if err := h.db.First(&dept, *req.DepartmentID).Error; err != nil {
			response.BadRequest(c, "部门不存在")
			return
		}
		updates["department_id"] = *req.DepartmentID
		updates["position"] = req.Position
		updates["role"] = req.Role
	}

	if err := h.db.Model(&cert).Updates(updates).Error; err != nil {
		response.InternalError(c, "审核失败")
		return
	}

	// 如果通过，同步用户表 + 员工-部门关联表
	if req.Status == 1 {
		// 用户角色取认证申请时的角色类型（employee / guard）
		userRole := cert.Role
		if userRole == "" {
			userRole = "employee"
		}
		h.db.Model(&model.User{}).Where("id = ?", cert.UserID).Updates(map[string]interface{}{
			"role":      userRole,
			"real_name": realName,
			"phone":     phone,
		})

		// 同步员工-部门关联表（含职位、员工类型、状态）
		pos := req.Position
		if pos == "" {
			pos = cert.Position
		}
		empType := req.Role
		if empType == "" {
			empType = "employee"
		}
		// 查找通讯录中的钉钉UserId（如已导入）
		var pendingEmp model.PendingEmployee
		dingTalkUserID := ""
		if err := h.db.Where("phone = ?", phone).First(&pendingEmp).Error; err == nil {
			dingTalkUserID = pendingEmp.DingTalkUserID
		}

		udData := map[string]interface{}{
			"position":        pos,
			"employee_type":   empType,
			"employee_status": 1,
			"ding_talk_user_id": dingTalkUserID,
		}
		if req.DepartmentID != nil {
			var dept model.Department
			if err := h.db.First(&dept, *req.DepartmentID).Error; err == nil {
				udData["department_id"] = *req.DepartmentID
				udData["department_name"] = dept.Name
			}
		}
		var ud model.UserDepartment
		result := h.db.Where("user_id = ?", cert.UserID).First(&ud)
		if result.Error != nil {
			udData["user_id"] = cert.UserID
			h.db.Model(&model.UserDepartment{}).Create(udData)
		} else {
			h.db.Model(&ud).Updates(udData)
		}
	}

	response.SuccessWithMessage(c, "审核完成", nil)
}

// ============ 部门管理（树形结构）============

// DepartmentTreeNode 部门树节点
type DepartmentTreeNode struct {
	model.Department
	Children []*DepartmentTreeNode `json:"children"`
}

// buildDeptTree 构建部门树
func buildDeptTree(departments []model.Department, parentID *uint) []*DepartmentTreeNode {
	var nodes []*DepartmentTreeNode
	for _, d := range departments {
		if (parentID == nil && d.ParentID == nil) ||
			(parentID != nil && d.ParentID != nil && *d.ParentID == *parentID) {
			node := &DepartmentTreeNode{
				Department: d,
				Children:   buildDeptTree(departments, &d.ID),
			}
			nodes = append(nodes, node)
		}
	}
	return nodes
}

// @Summary      部门树
// @Description  获取部门树形结构
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Success      200  {object}  response.Response{data=[]DepartmentTreeNode}  "成功"
// @Router       /admin/department-tree [get]

// ListDepartmentTree 获取部门树
func (h *AdminHandler) ListDepartmentTree(c *gin.Context) {
	var departments []model.Department
	h.db.Where("status = ?", 1).Order("sort ASC, id ASC").Find(&departments)

	tree := buildDeptTree(departments, nil)
	response.Success(c, tree)
}

// DepartmentItem 部门扁平列表项
type DepartmentItem struct {
	ID              uint   `json:"id"`
	Name            string `json:"name"`
	ParentID        *uint  `json:"parent_id"`
	LeaderName      string `json:"leader_name"`
	LeaderPhone     string `json:"leader_phone"`
	ApproverUserIDs string `json:"approver_user_ids"`
	VpUserIDs       string `json:"vp_user_ids"`
	Sort            int    `json:"sort"`
	Status          int    `json:"status"`
	CreatedAt       string `json:"created_at"`
}

// @Summary      所有部门列表
// @Description  获取所有部门扁平列表
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Success      200  {object}  response.Response{data=[]DepartmentItem}  "成功"
// @Router       /admin/departments-all [get]

// ListAllDepartments 获取所有部门（扁平列表）
func (h *AdminHandler) ListAllDepartments(c *gin.Context) {
	var departments []model.Department
	h.db.Where("status = 1").Preload("Leader").Order("sort ASC, id ASC").Find(&departments)

	var items []DepartmentItem
	for _, d := range departments {
		item := DepartmentItem{
			ID:        d.ID,
			Name:      d.Name,
			ParentID:  d.ParentID,
			Sort:      d.Sort,
			Status:    d.Status,
			CreatedAt: d.CreatedAt.Format("2006-01-02 15:04:05"),
		}
		if d.Leader != nil {
			item.LeaderName = d.Leader.RealName
			item.LeaderPhone = d.Leader.Phone
		}
		item.ApproverUserIDs = d.ApproverUserIDs
		item.VpUserIDs = d.VpUserIDs
		items = append(items, item)
	}

	response.Success(c, items)
}

// @Summary      创建部门
// @Description  创建一个新的部门
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        body  body  object{name=string,parent_id=uint,leader_id=uint,deputy_id=uint,sort=int,description=string}  true  "部门信息"
// @Success      200   {object}  response.Response{data=model.Department}  "成功"
// @Router       /admin/departments [post]

// CreateDepartment 创建部门
func (h *AdminHandler) CreateDepartment(c *gin.Context) {
	var req struct {
		Name        string `json:"name" binding:"required"`
		ParentID    *uint  `json:"parent_id"`
		LeaderID    *uint  `json:"leader_id"`
		DeputyID    *uint  `json:"deputy_id"`
		Sort        int    `json:"sort"`
		Description string `json:"description"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "参数错误")
		return
	}

	// 如果指定了上级部门，检查是否存在
	if req.ParentID != nil {
		var parent model.Department
		if err := h.db.First(&parent, *req.ParentID).Error; err != nil {
			response.BadRequest(c, "上级部门不存在")
			return
		}
	}

	dept := model.Department{
		Name:        req.Name,
		ParentID:    req.ParentID,
		LeaderID:    req.LeaderID,
		DeputyID:    req.DeputyID,
		Sort:        req.Sort,
		Status:      1,
		Description: req.Description,
	}

	if err := h.db.Create(&dept).Error; err != nil {
		response.InternalError(c, "创建失败")
		return
	}

	response.SuccessWithMessage(c, "创建成功", dept)
}

// @Summary      更新部门
// @Description  更新指定部门的信息
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        id    path  int     true  "部门ID"
// @Param        body  body  object{name=string,parent_id=uint,leader_id=uint,deputy_id=uint,sort=int,status=int,description=string}  true  "更新信息"
// @Success      200   {object}  response.Response  "成功"
// @Router       /admin/departments/{id} [put]

// UpdateDepartment 更新部门
func (h *AdminHandler) UpdateDepartment(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "参数错误")
		return
	}

	var dept model.Department
	if err := h.db.First(&dept, id).Error; err != nil {
		response.NotFound(c, "部门不存在")
		return
	}

	var req struct {
		Name        string `json:"name"`
		ParentID    *uint  `json:"parent_id"`
		LeaderID    *uint  `json:"leader_id"`
		DeputyID    *uint  `json:"deputy_id"`
		Sort        *int   `json:"sort"`
		Status      *int   `json:"status"`
		Description string `json:"description"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "参数错误")
		return
	}

	// 不能将自己的 parent_id 设为自己
	if req.ParentID != nil && *req.ParentID == dept.ID {
		response.BadRequest(c, "上级部门不能是自己")
		return
	}

	updates := map[string]interface{}{}
	if req.Name != "" {
		updates["name"] = req.Name
	}
	if req.ParentID != nil {
		updates["parent_id"] = *req.ParentID
	}
	if req.LeaderID != nil {
		updates["leader_id"] = *req.LeaderID
	}
	if req.DeputyID != nil {
		updates["deputy_id"] = *req.DeputyID
	}
	if req.Sort != nil {
		updates["sort"] = *req.Sort
	}
	if req.Status != nil {
		updates["status"] = *req.Status
	}
	if req.Description != "" {
		updates["description"] = req.Description
	}

	if err := h.db.Model(&dept).Updates(updates).Error; err != nil {
		response.InternalError(c, "更新失败")
		return
	}

	response.SuccessWithMessage(c, "更新成功", nil)
}

// @Summary      删除部门
// @Description  删除指定部门及其关联检查
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        id  path  int  true  "部门ID"
// @Success      200  {object}  response.Response  "成功"
// @Router       /admin/departments/{id} [delete]

// DeleteDepartment 删除部门
func (h *AdminHandler) DeleteDepartment(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "参数错误")
		return
	}

	var dept model.Department
	if err := h.db.First(&dept, id).Error; err != nil {
		response.NotFound(c, "部门不存在")
		return
	}

	// 检查是否有子部门
	var childCount int64
	h.db.Model(&model.Department{}).Where("parent_id = ?", id).Count(&childCount)
	if childCount > 0 {
		response.BadRequest(c, "该部门下存在子部门，请先删除子部门")
		return
	}

	// 检查是否有员工关联
	var empCount int64
	h.db.Model(&model.EmployeeCertification{}).Where("department_id = ? AND status = 1", id).Count(&empCount)
	if empCount > 0 {
		response.BadRequest(c, "该部门下有认证员工，请先移除关联")
		return
	}

	if err := h.db.Delete(&dept).Error; err != nil {
		response.InternalError(c, "删除失败")
		return
	}

	response.SuccessWithMessage(c, "删除成功", nil)
}

// ============ 员工-部门关联 ============

// @Summary      设置员工部门
// @Description  为指定员工设置所属部门
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        userId  path  int   true  "用户ID"
// @Param        body    body  object{department_id=uint}  true  "部门ID"
// @Success      200  {object}  response.Response  "成功"
// @Router       /admin/employees/{userId}/department [put]

// SetEmployeeDepartment 设置员工部门
func (h *AdminHandler) SetEmployeeDepartment(c *gin.Context) {
	userID, err := strconv.ParseUint(c.Param("userId"), 10, 64)
	if err != nil {
		response.BadRequest(c, "参数错误")
		return
	}

	var req struct {
		DepartmentID uint   `json:"department_id" binding:"required"`
		Position     string `json:"position"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "参数错误")
		return
	}

	// 检查用户是否存在
	var user model.User
	if err := h.db.First(&user, userID).Error; err != nil {
		response.NotFound(c, "用户不存在")
		return
	}

	// 检查部门是否存在
	var dept model.Department
	if err := h.db.First(&dept, req.DepartmentID).Error; err != nil {
		response.NotFound(c, "部门不存在")
		return
	}

	// 使用 UserDepartment 关联，有则更新，无则创建
	var ud model.UserDepartment
	result := h.db.Where("user_id = ?", userID).First(&ud)
	fields := map[string]interface{}{
		"department_id":   req.DepartmentID,
		"department_name": dept.Name,
		"position":        req.Position,
	}
	if result.Error != nil {
		// 创建新关联
		ud = model.UserDepartment{
			UserID:         uint(userID),
			DepartmentID:   req.DepartmentID,
			DepartmentName: dept.Name,
			Position:       req.Position,
		}
		if err := h.db.Create(&ud).Error; err != nil {
			response.InternalError(c, "设置部门失败")
			return
		}
	} else {
		// 更新已有关联
		if err := h.db.Model(&ud).Updates(fields).Error; err != nil {
			response.InternalError(c, "设置部门失败")
			return
		}
	}

	response.SuccessWithMessage(c, "设置成功", nil)
}

// @Summary      清除员工部门
// @Description  移除指定员工的部门归属
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Param        userId  path  int  true  "用户ID"
// @Success      200  {object}  response.Response  "成功"
// @Router       /admin/employees/{userId}/department [delete]

// ClearEmployeeDepartment 清除员工部门
func (h *AdminHandler) ClearEmployeeDepartment(c *gin.Context) {
	userID, err := strconv.ParseUint(c.Param("userId"), 10, 64)
	if err != nil {
		response.BadRequest(c, "参数错误")
		return
	}

	if err := h.db.Where("user_id = ?", userID).Delete(&model.UserDepartment{}).Error; err != nil {
		response.InternalError(c, "清除部门失败")
		return
	}

	response.SuccessWithMessage(c, "已移除", nil)
}

// @Summary      员工-部门关联列表
// @Description  获取所有员工-部门关联关系
// @Tags         管理员
// @Accept       json
// @Produce      json
// @Security     BearerAuth
// @Success      200  {object}  response.Response{data=[]model.UserDepartment}  "成功"
// @Router       /admin/employee-departments [get]

// ListEmployeeDepartments 员工-部门关联列表
func (h *AdminHandler) ListEmployeeDepartments(c *gin.Context) {
	var list []model.UserDepartment
	h.db.Preload("Department").Find(&list)
	if list == nil {
		list = []model.UserDepartment{}
	}
	response.Success(c, list)
}

// ============ 到访区域管理 ============

// ListVisitorAreas 到访区域列表
func (h *AdminHandler) ListVisitorAreas(c *gin.Context) {
	var areas []model.VisitorArea
	h.db.Order("sort ASC, id ASC").Find(&areas)
	if areas == nil {
		areas = []model.VisitorArea{}
	}
	response.Success(c, areas)
}

// CreateVisitorArea 创建到访区域
func (h *AdminHandler) CreateVisitorArea(c *gin.Context) {
	var req struct {
		Name string `json:"name" binding:"required"`
		Sort int    `json:"sort"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "参数错误")
		return
	}
	area := model.VisitorArea{Name: req.Name, Sort: req.Sort, Status: 1}
	if err := h.db.Create(&area).Error; err != nil {
		response.InternalError(c, "创建失败")
		return
	}
	response.SuccessWithMessage(c, "创建成功", area)
}

// UpdateVisitorArea 更新到访区域
func (h *AdminHandler) UpdateVisitorArea(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "参数错误")
		return
	}
	var area model.VisitorArea
	if err := h.db.First(&area, id).Error; err != nil {
		response.NotFound(c, "区域不存在")
		return
	}
	var req struct {
		Name   *string `json:"name"`
		Sort   *int    `json:"sort"`
		Status *int    `json:"status"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "参数错误")
		return
	}
	updates := map[string]interface{}{}
	if req.Name != nil {
		updates["name"] = *req.Name
	}
	if req.Sort != nil {
		updates["sort"] = *req.Sort
	}
	if req.Status != nil {
		updates["status"] = *req.Status
	}
	if len(updates) > 0 {
		h.db.Model(&area).Updates(updates)
	}
	response.SuccessWithMessage(c, "更新成功", nil)
}

// DeleteVisitorArea 删除到访区域
func (h *AdminHandler) DeleteVisitorArea(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "参数错误")
		return
	}
	if err := h.db.Delete(&model.VisitorArea{}, id).Error; err != nil {
		response.InternalError(c, "删除失败")
		return
	}
	response.SuccessWithMessage(c, "删除成功", nil)
}

// ============ 来访目的管理 ============

// ListVisitTypes 来访目的列表
func (h *AdminHandler) ListVisitTypes(c *gin.Context) {
	var types []model.VisitType
	h.db.Order("sort ASC, id ASC").Find(&types)
	if types == nil {
		types = []model.VisitType{}
	}
	response.Success(c, types)
}

// CreateVisitType 创建来访目的
func (h *AdminHandler) CreateVisitType(c *gin.Context) {
	var req struct {
		Name string `json:"name" binding:"required"`
		Sort int    `json:"sort"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "参数错误")
		return
	}
	vt := model.VisitType{Name: req.Name, Sort: req.Sort, Status: 1}
	if err := h.db.Create(&vt).Error; err != nil {
		response.InternalError(c, "创建失败")
		return
	}
	response.SuccessWithMessage(c, "创建成功", vt)
}

// UpdateVisitType 更新来访目的
func (h *AdminHandler) UpdateVisitType(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "参数错误")
		return
	}
	var vt model.VisitType
	if err := h.db.First(&vt, id).Error; err != nil {
		response.NotFound(c, "类型不存在")
		return
	}
	var req struct {
		Name   *string `json:"name"`
		Sort   *int    `json:"sort"`
		Status *int    `json:"status"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "参数错误")
		return
	}
	updates := map[string]interface{}{}
	if req.Name != nil {
		updates["name"] = *req.Name
	}
	if req.Sort != nil {
		updates["sort"] = *req.Sort
	}
	if req.Status != nil {
		updates["status"] = *req.Status
	}
	if len(updates) > 0 {
		h.db.Model(&vt).Updates(updates)
	}
	response.SuccessWithMessage(c, "更新成功", nil)
}

// DeleteVisitType 删除来访目的
func (h *AdminHandler) DeleteVisitType(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "参数错误")
		return
	}
	if err := h.db.Delete(&model.VisitType{}, id).Error; err != nil {
		response.InternalError(c, "删除失败")
		return
	}
	response.SuccessWithMessage(c, "删除成功", nil)
}

// ============ 预约管理（管理员） ============

// ListAppointments 管理员查看所有预约
func (h *AdminHandler) ListAppointments(c *gin.Context) {
	page, pageSize := utils.ParsePagination(c)
	statusStr := c.DefaultQuery("status", "")
	keyword := c.DefaultQuery("keyword", "")

	var appointments []model.Appointment
	var total int64

	query := h.db.Model(&model.Appointment{})
	if statusStr != "" {
		status, _ := strconv.Atoi(statusStr)
		query = query.Where("status = ?", status)
	}
	if keyword != "" {
		query = query.Where("visitor_info LIKE ? OR employee_info LIKE ?",
			"%"+keyword+"%", "%"+keyword+"%")
	}

	query.Count(&total)
	query.Offset(utils.GetOffset(page, pageSize)).Limit(pageSize).
		Order("created_at DESC").Find(&appointments)

	response.SuccessPage(c, appointments, total, page, pageSize)
}

// ApproveAppointment 管理员审核预约
// ============ 新审批流配置 ============

// SetDepartmentVPs 设置部门的分管领导用户ID列表
func (h *AdminHandler) SetDepartmentVPs(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "参数错误")
		return
	}

	var req struct {
		VpUserIDs []uint `json:"vp_user_ids"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "参数错误")
		return
	}

	// 序列化为 JSON 数组字符串
	b, _ := json.Marshal(req.VpUserIDs)
	vpIDsStr := string(b)
	if req.VpUserIDs == nil {
		vpIDsStr = ""
	}

	if err := h.db.Model(&model.Department{}).Where("id = ?", id).Update("vp_user_ids", vpIDsStr).Error; err != nil {
		response.InternalError(c, "更新失败")
		return
	}
	response.SuccessWithMessage(c, "更新成功", nil)
}

// SetDepartmentApprover 设置部门指定审批人列表
func (h *AdminHandler) SetDepartmentApprover(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "参数错误")
		return
	}

	var req struct {
		ApproverUserIDs []uint `json:"approver_user_ids"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "参数错误")
		return
	}

	// 序列化为 JSON 数组字符串
	b, _ := json.Marshal(req.ApproverUserIDs)
	idsStr := string(b)
	if req.ApproverUserIDs == nil {
		idsStr = ""
	}

	if err := h.db.Model(&model.Department{}).Where("id = ?", id).Update("approver_user_ids", idsStr).Error; err != nil {
		response.InternalError(c, "更新失败")
		return
	}
	response.SuccessWithMessage(c, "更新成功", nil)
}

// ============ 待确认员工管理 ============

// ImportPendingEmployees 批量导入待确认员工
func (h *AdminHandler) ImportPendingEmployees(c *gin.Context) {
	var req struct {
		Employees []struct {
			RealName       string `json:"real_name" binding:"required"`
			Phone          string `json:"phone" binding:"required"`
			DepartmentID   uint   `json:"department_id" binding:"required"`
			DepartmentName string `json:"department_name"`
			Position       string `json:"position"`
			EmployeeType   string `json:"employee_type"`
			DingTalkUserID string `json:"dingtalk_user_id"`
		} `json:"employees" binding:"required"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "参数错误")
		return
	}

	imported := 0
	updated := 0
	for _, emp := range req.Employees {
		if emp.EmployeeType == "" {
			emp.EmployeeType = "employee"
		}

		var existing model.PendingEmployee
		result := h.db.Where("phone = ?", emp.Phone).First(&existing)
		if result.RowsAffected > 0 {
			// 已存在 → 更新（岗位调动等情况）
			if err := h.db.Model(&existing).Updates(map[string]interface{}{
				"real_name":        emp.RealName,
				"department_id":    emp.DepartmentID,
				"department_name":  emp.DepartmentName,
				"position":         emp.Position,
				"employee_type":    emp.EmployeeType,
				"ding_talk_user_id": emp.DingTalkUserID,
			}).Error; err != nil {
				fmt.Printf("更新待确认员工失败(JSON): phone=%s err=%v\n", emp.Phone, err)
				continue
			}
			updated++
			continue
		}

		pe := model.PendingEmployee{
			RealName:       emp.RealName,
			Phone:          emp.Phone,
			DepartmentID:   emp.DepartmentID,
			DepartmentName: emp.DepartmentName,
			Position:       emp.Position,
			EmployeeType:   emp.EmployeeType,
			DingTalkUserID: emp.DingTalkUserID,
		}
		if err := h.db.Create(&pe).Error; err != nil {
			fmt.Printf("创建待确认员工失败: phone=%s err=%v\n", emp.Phone, err)
			continue
		}
		imported++
	}
	response.Success(c, gin.H{
		"imported": imported,
		"updated":  updated,
		"total":    len(req.Employees),
	})
}

// ListPendingEmployees 待确认员工列表
func (h *AdminHandler) ListPendingEmployees(c *gin.Context) {
	page, pageSize := utils.ParsePagination(c)
	status := c.DefaultQuery("status", "")
	keyword := c.DefaultQuery("keyword", "")
	var list []model.PendingEmployee
	var total int64
	query := h.db.Model(&model.PendingEmployee{})
	if status == "matched" {
		query = query.Where("is_matched = ?", true)
	} else if status == "pending" {
		query = query.Where("is_matched = ?", false)
	}
	if keyword != "" {
		query = query.Where("real_name LIKE ? OR phone LIKE ?", "%"+keyword+"%", "%"+keyword+"%")
	}
	deptIDStr := c.DefaultQuery("department_id", "")
	if deptIDStr != "" {
		deptID, _ := strconv.ParseUint(deptIDStr, 10, 64)
		if deptID > 0 {
			query = query.Where("department_id = ?", deptID)
		}
	}
	query.Count(&total)
	query.Order("created_at DESC").Offset(utils.GetOffset(page, pageSize)).Limit(pageSize).Find(&list)
	if list == nil {
		list = []model.PendingEmployee{}
	}
	response.SuccessPage(c, list, total, page, pageSize)
}

// GetPendingEmployeeStats 待确认员工统计
func (h *AdminHandler) GetPendingEmployeeStats(c *gin.Context) {
	var total, pending, matched int64
	h.db.Model(&model.PendingEmployee{}).Count(&total)
	h.db.Model(&model.PendingEmployee{}).Where("is_matched = ?", false).Count(&pending)
	h.db.Model(&model.PendingEmployee{}).Where("is_matched = ?", true).Count(&matched)
	response.Success(c, gin.H{
		"total":   total,
		"pending": pending,
		"matched": matched,
	})
}

// MatchPendingEmployee 手动匹配待确认员工到用户（按手机号）
func (h *AdminHandler) MatchPendingEmployee(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "参数错误")
		return
	}

	var pending model.PendingEmployee
	if err := h.db.First(&pending, id).Error; err != nil {
		response.NotFound(c, "记录不存在")
		return
	}
	if pending.IsMatched {
		// 已匹配过的也允许重新同步，不阻塞
	}

	// 按手机号查找用户（不要求 phone_verified，手机号本身即可）
	var user model.User
	if err := h.db.Where("phone = ?", pending.Phone).First(&user).Error; err != nil {
		response.BadRequest(c, "未找到已绑定该手机号的用户，请先让员工登录并绑定手机")
		return
	}

	now := time.Now()
	// 创建 UserDepartment
	ud := model.UserDepartment{
		UserID:         user.ID,
		DepartmentID:   pending.DepartmentID,
		DepartmentName: pending.DepartmentName,
		Position:       pending.Position,
		EmployeeType:   pending.EmployeeType,
		EmployeeStatus: 1,
		DingTalkUserID: pending.DingTalkUserID,
	}
	h.db.Where("user_id = ?", user.ID).Assign(ud).FirstOrCreate(&model.UserDepartment{UserID: user.ID})

	// 升级角色 + 同步真实姓名
	updates := map[string]interface{}{
		"role": "employee",
	}
	if user.RealName == "" || user.RealName != pending.RealName {
		updates["real_name"] = pending.RealName
	}
	h.db.Model(&user).Updates(updates)

	// 标记已匹配
	h.db.Model(&pending).Updates(map[string]interface{}{
		"is_matched":      true,
		"matched_user_id": &user.ID,
		"matched_at":      &now,
	})

	response.SuccessWithMessage(c, "匹配成功", gin.H{
		"user_id":   user.ID,
		"real_name": user.RealName,
		"phone":     user.Phone,
	})
}

// SyncAllPendingEmployees 一键同步所有待确认员工信息到用户
func (h *AdminHandler) SyncAllPendingEmployees(c *gin.Context) {
	var pendings []model.PendingEmployee
	h.db.Find(&pendings)

	synced := 0
	skipped := 0
	for _, p := range pendings {
		var user model.User
		if err := h.db.Where("phone = ?", p.Phone).First(&user).Error; err != nil {
			skipped++
			continue
		}

		now := time.Now()
		// 创建或更新 UserDepartment
		ud := model.UserDepartment{
			UserID:         user.ID,
			DepartmentID:   p.DepartmentID,
			DepartmentName: p.DepartmentName,
			Position:       p.Position,
			EmployeeType:   p.EmployeeType,
			EmployeeStatus: 1,
			DingTalkUserID: p.DingTalkUserID,
		}
		h.db.Where("user_id = ?", user.ID).Assign(ud).FirstOrCreate(&model.UserDepartment{UserID: user.ID})

		// 升级角色 + 同步姓名
		userUpdates := map[string]interface{}{
			"role": "employee",
		}
		if user.RealName == "" || user.RealName != p.RealName {
			userUpdates["real_name"] = p.RealName
		}
		h.db.Model(&user).Updates(userUpdates)

		// 标记已匹配
		h.db.Model(&p).Updates(map[string]interface{}{
			"is_matched":      true,
			"matched_user_id": &user.ID,
			"matched_at":      &now,
		})
		synced++
	}

	response.Success(c, gin.H{
		"synced":  synced,
		"skipped": skipped,
		"total":   len(pendings),
	})
}

// ============ 全局兜底审批人 ============

func (h *AdminHandler) ListGlobalApprovers(c *gin.Context) {
	var list []model.GlobalApprover
	h.db.Preload("User").Order("created_at ASC").Find(&list)
	if list == nil {
		list = []model.GlobalApprover{}
	}
	response.Success(c, list)
}

func (h *AdminHandler) CreateGlobalApprover(c *gin.Context) {
	var req struct {
		UserID uint `json:"user_id" binding:"required"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		response.BadRequest(c, "参数错误")
		return
	}
	ga := model.GlobalApprover{UserID: req.UserID}
	if err := h.db.Create(&ga).Error; err != nil {
		response.InternalError(c, "创建失败")
		return
	}
	h.db.Preload("User").First(&ga, ga.ID)
	response.SuccessWithMessage(c, "创建成功", ga)
}

func (h *AdminHandler) DeleteGlobalApprover(c *gin.Context) {
	id, err := strconv.ParseUint(c.Param("id"), 10, 64)
	if err != nil {
		response.BadRequest(c, "参数错误")
		return
	}
	if err := h.db.Delete(&model.GlobalApprover{}, id).Error; err != nil {
		response.InternalError(c, "删除失败")
		return
	}
	response.SuccessWithMessage(c, "删除成功", nil)
}

// ImportPendingEmployeesExcel 通过 Excel 文件导入待确认员工
func (h *AdminHandler) ImportPendingEmployeesExcel(c *gin.Context) {
	file, err := c.FormFile("file")
	if err != nil {
		response.BadRequest(c, "请上传 Excel 文件")
		return
	}

	ext := strings.ToLower(filepath.Ext(file.Filename))
	if ext != ".xlsx" && ext != ".xls" {
		response.BadRequest(c, "仅支持 .xlsx 或 .xls 文件")
		return
	}

	src, err := file.Open()
	if err != nil {
		response.InternalError(c, "无法读取文件")
		return
	}
	defer src.Close()

	f, err := excelize.OpenReader(src)
	if err != nil {
		response.BadRequest(c, "无法解析 Excel 文件")
		return
	}

	rows, err := f.GetRows(f.GetSheetName(0))
	if err != nil || len(rows) < 4 {
		response.BadRequest(c, "Excel 文件为空或格式不正确")
		return
	}

	var departments []model.Department
	h.db.Where("status = 1").Find(&departments)
	deptMap := make(map[string]uint)
	for _, d := range departments {
		deptMap[d.Name] = d.ID
	}

	var imported, updated, noDept int
	for i := 3; i < len(rows); i++ {
		row := rows[i]
		if len(row) < 4 {
			continue
		}
		dingTalkUserID := strings.TrimSpace(row[0])
		name := strings.TrimSpace(row[1])
		phone := strings.TrimSpace(row[2])
		deptFull := strings.TrimSpace(row[3])

		if name == "" || phone == "" || deptFull == "" {
			continue
		}
		if !strings.Contains(deptFull, "四川") {
			continue
		}

		phone = strings.ReplaceAll(phone, "+86-", "")
		phone = strings.ReplaceAll(phone, "+86", "")
		phone = strings.TrimSpace(phone)

		subDept := deptFull
		if idx := strings.Index(deptFull, "-"); idx >= 0 {
			subDept = strings.TrimSpace(deptFull[idx+1:])
		}

		deptID, ok := deptMap[subDept]
		if !ok {
			deptID, ok = deptMap[deptFull]
		}
		if !ok {
			noDept++
			continue
		}

		updates := map[string]interface{}{
			"real_name":        name,
			"department_id":    deptID,
			"department_name":  subDept,
			"position":         "",
			"employee_type":    "employee",
			"ding_talk_user_id": dingTalkUserID,
		}

		var existing model.PendingEmployee
		result := h.db.Where("phone = ?", phone).First(&existing)
		if result.RowsAffected > 0 {
			// 已存在 → 更新
			if err := h.db.Model(&existing).Updates(updates).Error; err != nil {
				continue
			}
			updated++
			updated++
			continue
		}

		pe := model.PendingEmployee{
			RealName:       name,
			Phone:          phone,
			DepartmentID:   deptID,
			DepartmentName: subDept,
			Position:       "",
			EmployeeType:   "employee",
			DingTalkUserID: dingTalkUserID,
		}
		if err := h.db.Create(&pe).Error; err != nil {
			continue
		}
		imported++
	}

	response.Success(c, gin.H{
		"imported": imported,
		"updated":  updated,
		"noDept":   noDept,
		"total":    imported + updated + noDept,
	})
}
