package service

import (
	"cold-delivery/common/actions"
	cDto "cold-delivery/common/dto"
	"cold-delivery/common/global"
	"cold-delivery/common/nats/nats_server"
	"encoding/json"
	"errors"
	"fmt"

	"gogs.baozhida.cn/zoie/OAuth-core/service"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"

	"cold-delivery/app/admin/model"
	"cold-delivery/app/admin/service/dto"

	"gogs.baozhida.cn/zoie/OAuth-core/pkg"
)

type Company struct {
	service.Service
}

// GetPage 获取Address列表
func (e *Company) GetPage(c *dto.CompanyGetPageReq, list *[]model.SysDept, count *int64) error {
	var err error
	var data model.SysDept

	err = e.Orm.Model(&data).
		Scopes(
			cDto.MakeCondition(c.GetNeedSearch()),
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
		).
		Find(list).Limit(-1).Offset(-1).
		Count(count).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.GetFailedErr
	}
	return nil
}

func CompanyIdScopes(id int) func(db *gorm.DB) *gorm.DB {

	return func(db *gorm.DB) *gorm.DB {
		if id == 0 {
			return db
		}
		return db.Where("id = ? ", id)
	}
}
func CompanyIdScopesUser(id int) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		if id == 0 {
			return db
		}
		return db.Where("id = ? ", id).Or("parent_id =?", id)
	}
}

func (e *Company) GetAll(c *dto.CompanyGetAllReq, list *[]model.SysDept, count *int64, p *actions.DataPermission) error {
	var err error
	var data model.SysDept

	err = e.Orm.Model(&data).
		Scopes(
			CompanyIdScopes(p.DeptId),
			cDto.MakeCondition(c.GetNeedSearch()),
		).
		Find(list).Limit(-1).Offset(-1).
		Count(count).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.GetFailedErr
	}
	return nil
}

// Get 获取SysDept对象
func (e *Company) Get(d *dto.CompanyGetReq, deptModel *model.SysDept) error {
	err := e.Orm.
		First(deptModel, d.GetId()).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return global.GetNotFoundOrNoPermissionErr
		}
		return global.GetFailedErr
	}
	return nil
}

// GetCurrentCompany 获取登录用户的公司信息
func (e *Company) GetCurrentCompany(p *actions.DataPermission, list *[]model.SysDept, c *dto.CompanyGetPageReq, count *int64) error {
	// 检查 e.Orm 是否为 nil
	var err error
	var data model.SysDept
	err = e.Orm.Model(&data).
		Scopes(
			CompanyIdScopesUser(p.DeptId),
			cDto.MakeCondition(c.GetNeedSearch()),
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
		).
		Find(list).Limit(-1).Offset(-1).
		Count(count).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.GetFailedErr
	}
	return nil
}

// Insert 创建SysDept对象
func (e *Company) Insert(c *dto.CompanyInsertReq) error {
	var err error
	var data model.SysDept
	tx := e.Orm.Debug().Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()

	var i int64
	err = e.Orm.Model(&data).Where("name = ?", c.Name).Count(&i).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.CreateFailedErr
	}
	if i > 0 {
		err = errors.New("公司名称已存在！")
		e.Log.Errorf("db error: %s", err)
		return err
	}
	var coldCompany nats_server.Company_R
	coldCompany, err = nats_server.Cold_ReadCompanyByT_key(c.ColdKey)
	if err != nil {
		e.Log.Errorf("获取3.0秘钥失败: %s", err)
		err = errors.New("冷链3.0公司秘钥错误！")
		return err
	}
	data.ColdPid = coldCompany.Id
	c.Generate(&data)
	err = tx.Create(&data).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.CreateFailedErr
	}

	c.Id = data.Id
	deptPath := pkg.IntToString(data.Id) + "/"
	if data.ParentId != 0 {
		var deptP model.SysDept
		tx.First(&deptP, data.ParentId)
		deptPath = deptP.Path + deptPath
	} else {
		deptPath = "/0/" + deptPath
	}
	var mp = map[string]string{}
	mp["path"] = deptPath

	err = tx.Model(&data).Update("path", deptPath).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.CreateFailedErr
	}
	return nil
}

// Update 修改SysDept对象
func (e *Company) Update(c *dto.CompanyUpdateReq) error {
	var err error
	var deptModel = model.SysDept{}
	tx := e.Orm.Debug().Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()

	err = tx.First(&deptModel, c.GetId()).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return global.UpdateNotFoundOrNoPermissionErr
		}
		return global.UpdateFailedErr
	}

	if c.ColdKey != deptModel.ColdKey {
		var coldCompany nats_server.Company_R
		coldCompany, err = nats_server.Cold_ReadCompanyByT_key(c.ColdKey)
		if err != nil {
			e.Log.Errorf("获取3.0秘钥失败: %s", err)
			err = errors.New("冷链3.0公司秘钥错误！")
			return err
		}
		deptModel.ColdPid = coldCompany.Id
	}

	c.Generate(&deptModel)

	DeptPath := pkg.IntToString(deptModel.Id) + "/"
	if deptModel.ParentId != 0 {
		var DeptP model.SysDept
		tx.First(&DeptP, deptModel.ParentId)
		DeptPath = DeptP.Path + DeptPath
	} else {
		DeptPath = "/0/" + DeptPath
	}
	deptModel.Path = DeptPath
	db := tx.Save(&deptModel)
	if err = db.Error; err != nil {
		e.Log.Errorf("UpdateSysDept error: %s", err)
		return err
	}
	return nil
}

// Remove 删除SysDept
// 删除部门 同时删除其子部门、部门下的用户
func (e *Company) Remove(d *dto.CompanyDeleteReq, p *actions.DataPermission) error {
	var err error

	tx := e.Orm.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	var dept model.SysDept
	err = e.Orm.
		First(&dept, d.GetId()).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return global.GetNotFoundOrNoPermissionErr
		}
		return global.DeleteFailedErr
	}

	var deptList = make([]model.SysDept, 0)
	var deptIds = make([]int, 0)
	tx.Where("path like ?", dept.Path+"%").Find(&deptList)

	// 获取部门及其子部门下ID
	for _, v := range deptList {
		deptIds = append(deptIds, v.Id)
	}

	db := tx.Select(clause.Associations).Delete(&deptList)
	if err = db.Error; err != nil {
		e.Log.Errorf("Delete error: %s", err)
		return global.DeleteFailedErr
	}

	if db.RowsAffected == 0 {
		return global.DeleteNotFoundOrNoPermissionErr
	}
	// 删除部门下的用户
	dbUser := tx.Where("dept_id in (?)", deptIds).Delete(&model.SysUser{})
	if err = dbUser.Error; err != nil {
		e.Log.Errorf("Delete User error: %s", err)
		return global.DeleteFailedErr
	}

	return nil
}

// GetCompanyTreeByTKey 根据T_name获取公司树结构
func (e *Company) GetCompanyTreeByTname(T_name string) (data []nats_server.Company_R, err error) {
	data, err = nats_server.Cold_CompanyTreeByT_name(T_name)
	if err != nil {
		e.Log.Errorf("获取公司树失败: %s", err)
		return nil, err
	}
	return data, nil
}

// ImportThirdCompanyTree 批量导入第三方平台公司树结构
// Id    -> ColdPid
// T_key -> ColdKey
func (e *Company) ImportThirdCompanyTree(nodes []dto.ThirdCompanyTreeReq) (err error) {
	tx := e.Orm.Begin()
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()

	for _, node := range nodes {
		_, err = e.importThirdCompanyNode(tx, node, 0)
		if err != nil {
			e.Log.Errorf("import third company tree error: %s", err)
			return err
		}
	}

	return nil
}

// importThirdCompanyNode 递归导入单个节点及其子节点
func (e *Company) importThirdCompanyNode(tx *gorm.DB, node dto.ThirdCompanyTreeReq, parentDeptId int) (deptId int, err error) {
	var dept model.SysDept

	// 根据 ColdPid 查找是否已存在
	dbErr := tx.Where("cold_pid = ?", node.Id).First(&dept).Error
	if dbErr != nil {
		if errors.Is(dbErr, gorm.ErrRecordNotFound) {
			// 新建
			dept = model.SysDept{}
		} else {
			e.Log.Errorf("db error when query by cold_pid: %s", dbErr)
			return 0, global.GetFailedErr
		}
	}

	isNew := dept.Id == 0

	dept.Name = node.TName
	dept.ColdKey = node.TKey
	dept.ColdPid = node.Id
	dept.CompanyAddress = node.TAddress
	dept.ParentId = parentDeptId

	if isNew {
		err = tx.Create(&dept).Error
		if err != nil {
			e.Log.Errorf("db error when create dept: %s", err)
			return 0, global.CreateFailedErr
		}
	} else {
		err = tx.Save(&dept).Error
		if err != nil {
			e.Log.Errorf("db error when update dept: %s", err)
			return 0, global.UpdateFailedErr
		}
	}

	// 生成 path
	deptPath := pkg.IntToString(dept.Id) + "/"
	if parentDeptId != 0 {
		var parentDept model.SysDept
		err = tx.First(&parentDept, parentDeptId).Error
		if err != nil {
			e.Log.Errorf("db error when query parent dept: %s", err)
			return 0, global.GetFailedErr
		}
		deptPath = parentDept.Path + deptPath
	} else {
		deptPath = "/0/" + deptPath
	}

	err = tx.Model(&dept).Update("path", deptPath).Error
	if err != nil {
		e.Log.Errorf("db error when update dept path: %s", err)
		return 0, global.UpdateFailedErr
	}

	// 递归处理子节点
	for _, child := range node.Children {
		_, err = e.importThirdCompanyNode(tx, child, dept.Id)
		if err != nil {
			return dept.Id, err
		}
	}

	return dept.Id, nil
}

// SetDeptPage 设置Dept页面数据
func (e *Company) SetDeptPage(c *dto.CompanyGetPageReq, p *actions.DataPermission) (m []model.SysDept, err error) {
	var list []model.SysDept
	err = e.getList(c, &list, p)
	for i := 0; i < len(list); i++ {
		if list[i].ParentId != 0 {
			continue
		}
		info := e.DeptPageCall(&list, list[i])
		m = append(m, info)
	}

	if len(m) == 0 {
		parentMap, flag := getDeptParent(list)
		if flag {
			for i := 0; i < len(list); i++ {
				if parentMap[list[i].ParentId] {
					continue
				}
				info := e.DeptPageCall(&list, list[i])
				m = append(m, info)
			}
		} else {
			for i := 0; i < len(list); i++ {
				info := e.DeptPageCall(&list, list[i])
				m = append(m, info)
			}
		}
	}

	return
}
func getDeptParent(deptList []model.SysDept) (map[int]bool, bool) {
	list := deptList
	var flag = false
	var parentMap = map[int]bool{}
	for j := 0; j < len(list); j++ {
		parentMap[list[j].ParentId] = false
	}

	for j := 0; j < len(list); j++ {
		if _, ok := parentMap[list[j].Id]; !ok {
			continue
		}
		parentMap[list[j].Id] = true
		flag = true
	}
	return parentMap, flag
}

// getList 获取组织数据
func (e *Company) getList(c *dto.CompanyGetPageReq, list *[]model.SysDept, p *actions.DataPermission) error {
	var err error
	var data model.SysDept
	if len(c.Name) == 0 && p.DeptId == 0 {
		err = e.Orm.Model(&data).
			Scopes(
				cDto.MakeCondition(c.GetNeedSearch()),
			).
			Find(list).Error
		if err != nil {
			e.Log.Errorf("db error:%s", err)
			return err
		}

		return nil
	}

	var tempList []model.SysDept
	err = e.Orm.Model(&data).Where("id in (select id from sys_dept where dept_path like ? )", "%/"+pkg.IntToString(p.DeptId)+"/%").
		Scopes(
			cDto.MakeCondition(c.GetNeedSearch()),
		).
		Order("id desc").
		Find(&tempList).Error
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.GetFailedErr
	}

	// 获取部门及其子部门下ID
	for _, dept := range tempList {
		var deptList = make([]model.SysDept, 0)
		err = e.Orm.Where("dept_path like ?", dept.Path+"%").Order(fmt.Sprintf("sort %s", c.SortOrder)).Find(&deptList).Error
		*list = append(*list, deptList...)
	}
	if err != nil {
		e.Log.Errorf("db error: %s", err)
		return global.GetFailedErr
	}

	*list = DeduplicateDept(*list)

	return nil
}

func (e *Company) DeptPageCall(deptList *[]model.SysDept, menu model.SysDept) model.SysDept {
	list := *deptList
	min := make([]model.SysDept, 0)
	for j := 0; j < len(list); j++ {
		if menu.Id != list[j].ParentId {
			continue
		}
		mi := model.SysDept{}
		mi.Id = list[j].Id
		mi.ParentId = list[j].ParentId
		mi.ColdKey = list[j].ColdKey
		mi.Path = list[j].Path
		mi.Name = list[j].Name
		mi.Sort = list[j].Sort
		mi.Status = list[j].Status
		mi.Remark = list[j].Remark
		mi.CreatedAt = list[j].CreatedAt
		mi.IsCoolerReleaseCold = list[j].IsCoolerReleaseCold
		mi.IsCoolerShow = list[j].IsCoolerShow
		mi.IsIceReleaseCold = list[j].IsIceReleaseCold
		mi.IsOutStorage = list[j].IsOutStorage
		mi.CompanyAddress = list[j].CompanyAddress
		mi.IceRaftManage = list[j].IceRaftManage
		mi.AppName = list[j].AppName
		mi.Children = []model.SysDept{}
		ms := e.DeptPageCall(deptList, mi)
		min = append(min, ms)
	}
	menu.Children = min
	return menu
}

func DeduplicateDept(list []model.SysDept) []model.SysDept {
	seen := make(map[string]bool)
	deduplicated := []model.SysDept{}

	for _, v := range list {
		// 将结构体编码为 JSON 字符串
		key, err := json.Marshal(v)
		if err != nil {
			// 处理错误
			continue
		}
		// 将 JSON 字符串作为键插入到 map 中
		if _, ok := seen[string(key)]; !ok {
			seen[string(key)] = true
			deduplicated = append(deduplicated, v)
		}
	}

	return deduplicated
}
