package tui

import (
	"get-container/cmd/hytop/backend"
	"get-container/gpu"
	"get-container/utils"
	"slices"
	"syscall"
	"time"

	tea "github.com/charmbracelet/bubbletea"
	"github.com/charmbracelet/lipgloss"
)

const (
	DCUTopVersion = "1.0.1"
)

var (
	KeyUp    = tea.KeyUp.String()
	KeyDown  = tea.KeyDown.String()
	KeyLeft  = tea.KeyLeft.String()
	KeyRight = tea.KeyRight.String()
	KeySpace = tea.KeySpace.String()
)

var (
	HeightLightStyle    = lipgloss.NewStyle().Background(lipgloss.Color("#00fffb7a")) // 高亮风格
	SelectedStyle       = lipgloss.NewStyle().Foreground(lipgloss.Color("#ffb81fe3")) // 被选中的风格
	HeightSelectedStyle = lipgloss.NewStyle().Background(lipgloss.Color("#ffb81fe3")) // 既被选中，又高亮的风格

	LowLeightStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#442d2d"))
	NormalStyle    = lipgloss.NewStyle().Foreground(lipgloss.Color("#e6e6e6eb"))

	myBorder = lipgloss.Border{
		Top:          "═",
		TopLeft:      "╒",
		TopRight:     "╕",
		Bottom:       "═",
		BottomLeft:   "╘",
		BottomRight:  "╛",
		Left:         "│",
		Right:        "│",
		MiddleLeft:   "├",
		MiddleRight:  "┤",
		Middle:       "┼",
		MiddleTop:    "┬",
		MiddleBottom: "┴",
	}
)

// ModelMsg 模型信息，在父组件和各个子组件间共享信息
type ModelMsg struct {
	t          time.Time                        // 当前时间
	Version    *gpu.HYVersionInfo               // gpu版本相关信息
	DCUPidInfo map[int][]backend.DCUProcessInfo // 使用dcu的进程信息
	systemInfo *utils.SysInfo                   // 系统信息
	MyVersion  string                           // 本软件的版本
	DCUInfo    *backend.DCUInfoMap              // dcu相关信息
}

type TickMsg time.Time
type ProcessAction int // 进程动作
type ViewMode int      // 视图

const (
	PAKill ProcessAction = 9
	PAInt  ProcessAction = 2
	PATerm ProcessAction = 15
	PANone ProcessAction = 0

	VMMain       ViewMode = 0 // 主视图
	VMTree       ViewMode = 1 // 进程树视图
	VMOneProcess ViewMode = 2 // 进程详情视图
	VMProcessEnv ViewMode = 3 // 进程环境变量视图
	VMPower      ViewMode = 4 // 功耗视图
)

func (pa ProcessAction) String() string {
	switch pa {
	case PAKill:
		return "SIGKILL"
	case PAInt:
		return "SIGINT"
	case PATerm:
		return "SIGTERM"
	default:
		return "Cancel"
	}
}

func (pa ProcessAction) Signal() syscall.Signal {
	switch pa {
	case PAKill:
		return syscall.SIGKILL
	case PAInt:
		return syscall.SIGINT
	case PATerm:
		return syscall.SIGTERM
	default:
		return syscall.SIGTERM
	}
}

// ActionMsg 动作消息
type ActionMsg struct {
	VM             ViewMode       // 所在视图，默认为0，即主视图
	VMOld          ViewMode       // 进入进程环境变量视图前的视图
	SelectPids     map[int32]bool // 选择的pid进程
	Action         *ProcessAction // 对选择的pid的动作
	PidView        *int32         // 进程视图指标的pid号，为null表示没有进入进程指标视图
	PointPid       *int32         // 指针指向的pid，为null表示没有选择进程，在主视图和进程树视图起作用
	PidEnvView     *int32         // 进程环境变量视图的pid号，为null表示不进入进程环境变量视图
	PidTreePids    []int32        // pid tree视图下，进程id的顺序列表
	TargetDCUIndex int            // PointPid使用的dcu index，为-1表示没有选择任何dcu
	HelpView       bool           // 是否进入帮助界面
}

// ModelMain tui主模型类
type ModelMain struct {
	width, height int // 终端尺寸
	Header        *ModelHeader
	DCUInfo       *ModelDCUInfo
	SysLoad       *ModelSysLoad
	ProcessInfo   *ModelProcessInfo
	modelMsg      *ModelMsg
	actionMsg     *ActionMsg
	dialog        *Dialog             // 对话框
	pstree        *ModelPsTree        // 进程树视图
	processDetail *ModelProcessDetail // 进程详情视图
	processEnv    *ModelProcessEnv    // 进程环境变量视图
	powerDetail   *ModelPowerDetail   // 功耗视图
}

func NewModelMain(width, height int) ModelMain {
	result := ModelMain{}
	result.width = width
	result.height = height
	result.Header = NewModelHeader()
	result.DCUInfo = NewModelDCUInfo(width, height)
	result.SysLoad = NewModelSysLoad(width)
	result.ProcessInfo = NewModelProcessInfo(width)
	result.dialog = NewDialog(nil)
	result.pstree = NewModelPsTree(width, height)
	result.actionMsg = &ActionMsg{
		HelpView:       false,
		TargetDCUIndex: -1,
		VM:             VMMain,
	}
	result.processEnv = nil
	result.powerDetail = nil
	return result
}

func tickCmd() tea.Cmd {
	return tea.Every(time.Second, func(t time.Time) tea.Msg {
		return TickMsg(t)
	})
}

func sendMsgCmd(modelMsg *ModelMsg) tea.Cmd {
	return func() tea.Msg {
		return *modelMsg
	}
}

// Prepare 准备数据
func (m *ModelMain) Prepare() error {
	modelMsg := ModelMsg{}
	if err := initModelInfo(&modelMsg); err != nil {
		return err
	}
	m.modelMsg = &modelMsg
	return nil
}

// Init 初始化信息
func (m *ModelMain) Init() tea.Cmd {
	cmds := make([]tea.Cmd, 0)
	if c := m.Header.Init(); c != nil {
		cmds = append(cmds, c)
	}
	if c := m.DCUInfo.Init(); c != nil {
		cmds = append(cmds, c)
	}
	if c := m.SysLoad.Init(); c != nil {
		cmds = append(cmds, c)
	}
	if c := m.ProcessInfo.Init(); c != nil {
		cmds = append(cmds, c)
	}
	if c := m.dialog.Init(); c != nil {
		cmds = append(cmds, c)
	}
	if c := m.pstree.Init(); c != nil {
		cmds = append(cmds, c)
	}
	if c := m.processEnv.Init(); c != nil {
		cmds = append(cmds, c)
	}

	// 将调用初始化方法
	cmds = append(cmds, tickCmd(), sendMsgCmd(m.modelMsg))
	return tea.Batch(cmds...)
}

func (m *ModelMain) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) {
	switch msg := inputMsg.(type) {
	case tea.KeyMsg: // 键盘事件
		switch msg.String() {
		case "a":
			cmd := m.handleKeyA(msg)
			return m, cmd
		case "q":
			return m, tea.Quit
		case "ctrl+c":
			cmd := m.handleCtrlC()
			return m, cmd
		case "up":
			cmd := m.handleKeyUp()
			return m, cmd
		case "down":
			cmd := m.handleKeyDown()
			return m, cmd
		case "enter":
			cmd := m.handleKeyEnter()
			return m, cmd
		case "h":
			m.actionMsg.HelpView = true
			return m, nil
		case KeyLeft, KeyRight:
			cmd := m.handleKeyLR(msg.String())
			return m, cmd
		case "k":
			cmd := m.handleKeyK()
			return m, cmd
		case "esc":
			cmd := m.handleKeyEsc()
			return m, cmd
		case " ":
			cmd := m.handleKeySpace()
			return m, cmd
		case "t":
			cmd := m.handleKeyT()
			return m, cmd
		case "e":
			cmd := m.handleKeyE()
			return m, cmd
		case "p":
			cmd := m.handleKeyP(msg)
			return m, cmd
		}
	case TickMsg: // 定时事件
		updateModelInfo(m.modelMsg, time.Time(msg))
		header, _ := m.Header.Update(m.modelMsg)
		dcuInfo, _ := m.DCUInfo.Update(m.modelMsg)
		sysLoad, _ := m.SysLoad.Update(m.modelMsg)
		pidinfo, _ := m.ProcessInfo.Update(m.modelMsg)
		pstree, _ := m.pstree.Update(m.modelMsg)
		m.Header = header.(*ModelHeader)
		m.DCUInfo = dcuInfo.(*ModelDCUInfo)
		m.SysLoad = sysLoad.(*ModelSysLoad)
		m.ProcessInfo = pidinfo.(*ModelProcessInfo)
		m.pstree = pstree.(*ModelPsTree)
		if m.processDetail != nil {
			detail, _ := m.processDetail.Update(m.modelMsg)
			m.processDetail = detail.(*ModelProcessDetail)
		}
		if m.powerDetail != nil {
			power, _ := m.powerDetail.Update(m.modelMsg)
			m.powerDetail = power.(*ModelPowerDetail)
		}
		return m, tickCmd()
	case ModelMsg: // 初始化
		header, _ := m.Header.Update(m.modelMsg)
		dcuInfo, _ := m.DCUInfo.Update(m.modelMsg)
		sysLoad, _ := m.SysLoad.Update(m.modelMsg)
		pidinfo, _ := m.ProcessInfo.Update(m.modelMsg)
		m.Header = header.(*ModelHeader)
		m.DCUInfo = dcuInfo.(*ModelDCUInfo)
		m.SysLoad = sysLoad.(*ModelSysLoad)
		m.ProcessInfo = pidinfo.(*ModelProcessInfo)
		return m, nil
	case tea.WindowSizeMsg: // 窗口尺寸变化
		m.width, m.height = msg.Width, msg.Height
		header, _ := m.Header.Update(msg)
		dcuInfo, _ := m.DCUInfo.Update(msg)
		sysLoad, _ := m.SysLoad.Update(msg)
		pidinfo, _ := m.ProcessInfo.Update(msg)
		m.Header = header.(*ModelHeader)
		m.DCUInfo = dcuInfo.(*ModelDCUInfo)
		m.SysLoad = sysLoad.(*ModelSysLoad)
		m.ProcessInfo = pidinfo.(*ModelProcessInfo)
		return m, nil
	}
	return m, nil
}

func (m *ModelMain) handleKeyA(k tea.KeyMsg) tea.Cmd {
	switch m.actionMsg.VM {
	case VMPower:
		power, cmd := m.powerDetail.Update(k)
		m.powerDetail = power.(*ModelPowerDetail)
		return cmd
	default:
		return nil
	}
}

func (m *ModelMain) handleKeyP(k tea.KeyMsg) tea.Cmd {
	switch m.actionMsg.VM {
	case VMMain:
		m.actionMsg.VMOld = VMMain
		m.actionMsg.VM = VMPower
		m.powerDetail = NewModelPower(m.height, m.width)
		m.powerDetail.Init()
		model, cmd := m.powerDetail.Update(m.modelMsg)
		m.powerDetail = model.(*ModelPowerDetail)
		return cmd
	case VMPower:
		power, cmd := m.powerDetail.Update(k)
		m.powerDetail = power.(*ModelPowerDetail)
		return cmd
	default:
		return nil
	}
}

func (m *ModelMain) handleKeyE() tea.Cmd {
	// 检查光标是否在某个进程上，若有，且当前为Main或Tree视图，就进入进程环境变量模式
	if m.actionMsg == nil || m.actionMsg.PointPid == nil {
		return nil
	}
	if m.actionMsg.VM != VMMain && m.actionMsg.VM != VMTree {
		return nil
	}
	if m.processEnv != nil {
		return nil
	}

	m.processEnv = NewModelProcessEnv(m.width, m.height, int(*m.actionMsg.PointPid), m.modelMsg)
	m.actionMsg.VMOld = m.actionMsg.VM
	m.actionMsg.VM = VMProcessEnv
	return nil
}

func (m *ModelMain) handleCtrlC() tea.Cmd {
	if m.actionMsg.Action != nil || m.actionMsg.VM != VMTree {
		return nil
	}
	if len(m.actionMsg.SelectPids) != 0 || m.actionMsg.PointPid != nil {
		action := PAInt
		m.actionMsg.Action = &action
		pstree, _ := m.pstree.Update(m.actionMsg)
		dialog, _ := m.dialog.Update(m.actionMsg)
		m.dialog = dialog.(*Dialog)
		m.pstree = pstree.(*ModelPsTree)
	}
	return nil
}

func (m *ModelMain) handleKeyEnter() tea.Cmd {
	if m.actionMsg.VM == VMMain && m.actionMsg.Action == nil {
		pid := *m.actionMsg.PointPid
		m.actionMsg.PidView = &pid
		m.processDetail = NewModelProcessDetail(m.width, m.height, pid)
		m.processDetail.Update(m.modelMsg)
		m.actionMsg.VM = VMOneProcess
		return nil
	}
	if m.actionMsg.Action != nil {
		target := make([]int32, 0, 8)
		if len(m.actionMsg.SelectPids) > 0 {
			for k := range m.actionMsg.SelectPids {
				target = append(target, k)
			}
		} else if m.actionMsg.PointPid != nil {
			target = append(target, *m.actionMsg.PointPid)
		}
		switch *m.actionMsg.Action {
		case PANone:
			m.actionMsg.Action = nil
			switch m.actionMsg.VM {
			case VMMain:
				header, _ := m.Header.Update(m.actionMsg)
				dcuInfo, _ := m.DCUInfo.Update(m.actionMsg)
				sysLoad, _ := m.SysLoad.Update(m.actionMsg)
				pidinfo, _ := m.ProcessInfo.Update(m.actionMsg)
				m.Header = header.(*ModelHeader)
				m.DCUInfo = dcuInfo.(*ModelDCUInfo)
				m.SysLoad = sysLoad.(*ModelSysLoad)
				m.ProcessInfo = pidinfo.(*ModelProcessInfo)
			case VMTree:
				pstree, _ := m.pstree.Update(m.actionMsg)
				m.pstree = pstree.(*ModelPsTree)
			}
		case PAKill:
			go utils.SendSignal(target, PAKill.Signal())
		case PATerm:
			go utils.SendSignal(target, PATerm.Signal())
		case PAInt:
			go utils.SendSignal(target, PAInt.Signal())
		}
	}
	return nil
}

func (m *ModelMain) handleKeyT() tea.Cmd {
	// 在主视图下，没有选择任何进程时，可以进入进程树视图，且
	if m.actionMsg.VM == VMMain && len(m.actionMsg.SelectPids) == 0 {
		m.actionMsg.VM = VMTree
		pstree, _ := m.pstree.Update(m.actionMsg)
		m.pstree = pstree.(*ModelPsTree)
		return nil
	} else if m.actionMsg.VM == VMTree {
		if len(m.actionMsg.SelectPids) != 0 || m.actionMsg.PointPid != nil {
			action := PATerm
			m.actionMsg.Action = &action
			pstree, _ := m.pstree.Update(m.actionMsg)
			dialog, _ := m.dialog.Update(m.actionMsg)
			m.dialog = dialog.(*Dialog)
			m.pstree = pstree.(*ModelPsTree)
			return nil
		} else {
			return nil
		}
	}
	return nil
}

// handleKeyLR 处理左右键消息，左右键仅在对话框中有效
func (m *ModelMain) handleKeyLR(s string) tea.Cmd {
	if m.processEnv != nil {
		switch s {
		case KeyRight:
			env, _ := m.processEnv.Update(tea.KeyRight)
			m.processEnv = env.(*ModelProcessEnv)
			return nil
		case KeyLeft:
			env, _ := m.processEnv.Update(tea.KeyLeft)
			m.processEnv = env.(*ModelProcessEnv)
			return nil
		default:
			return nil
		}
	}
	if m.actionMsg == nil || m.actionMsg.Action == nil {
		return nil
	}
	if m.dialog != nil {
		switch s {
		case KeyRight:
			switch *m.actionMsg.Action {
			case PAKill:
				*m.actionMsg.Action = PATerm
			case PATerm:
				*m.actionMsg.Action = PAInt
			case PAInt:
				*m.actionMsg.Action = PANone
			default:
				return nil
			}
		case KeyLeft:
			switch *m.actionMsg.Action {
			case PATerm:
				*m.actionMsg.Action = PAKill
			case PAInt:
				*m.actionMsg.Action = PATerm
			case PANone:
				*m.actionMsg.Action = PAInt
			default:
				return nil
			}
		default:
			return nil
		}
		dialog, _ := m.dialog.Update(m.actionMsg)
		m.dialog = dialog.(*Dialog)
		return nil
	}
	return nil
}

func (m *ModelMain) handleKeyK() tea.Cmd {
	if m.actionMsg.PointPid == nil && m.actionMsg.SelectPids == nil {
		return nil
	}
	if m.actionMsg.Action != nil {
		return nil
	}
	switch m.actionMsg.VM {
	case VMMain:
		var pa ProcessAction = PANone
		if m.actionMsg.Action == nil {
			m.actionMsg.Action = &pa
		}
		header, _ := m.Header.Update(m.actionMsg)
		dcuInfo, _ := m.DCUInfo.Update(m.actionMsg)
		sysLoad, _ := m.SysLoad.Update(m.actionMsg)
		pidinfo, _ := m.ProcessInfo.Update(m.actionMsg)
		m.Header = header.(*ModelHeader)
		m.DCUInfo = dcuInfo.(*ModelDCUInfo)
		m.SysLoad = sysLoad.(*ModelSysLoad)
		m.ProcessInfo = pidinfo.(*ModelProcessInfo)
		dialog, _ := m.dialog.Update(m.actionMsg)
		m.dialog = dialog.(*Dialog)
		return nil
	case VMTree:
		var pa ProcessAction = PAKill
		if m.actionMsg.Action == nil {
			m.actionMsg.Action = &pa
		}
		pstree, _ := m.pstree.Update(m.actionMsg)
		dialog, _ := m.dialog.Update(m.actionMsg)
		m.dialog = dialog.(*Dialog)
		m.pstree = pstree.(*ModelPsTree)
		return nil
	default:
		return nil
	}
}

// handleKeyEsc 处理Esc键，esc键在：
// VMMain视图下，取消所有选择的进程、退出单个进程模式或对话框返回
// VMTree视图下，取消所有选择的进程、退出单个进程模式或对话框返回，返回到VMMain视图
func (m *ModelMain) handleKeyEsc() tea.Cmd {
	if m.actionMsg.HelpView {
		m.actionMsg.HelpView = false
		return nil
	}
	switch m.actionMsg.VM {
	case VMMain:
		if m.actionMsg.Action != nil {
			m.actionMsg.Action = nil
		} else if m.actionMsg.SelectPids != nil {
			m.actionMsg.SelectPids = nil
		} else if m.actionMsg.PointPid != nil {
			m.actionMsg.PointPid = nil
			m.actionMsg.TargetDCUIndex = -1
		}
		header, _ := m.Header.Update(m.actionMsg)
		dcuInfo, _ := m.DCUInfo.Update(m.actionMsg)
		sysLoad, _ := m.SysLoad.Update(m.actionMsg)
		pidinfo, _ := m.ProcessInfo.Update(m.actionMsg)
		m.Header = header.(*ModelHeader)
		m.DCUInfo = dcuInfo.(*ModelDCUInfo)
		m.SysLoad = sysLoad.(*ModelSysLoad)
		m.ProcessInfo = pidinfo.(*ModelProcessInfo)
		return nil
	case VMTree:
		if m.actionMsg.Action != nil {
			m.actionMsg.Action = nil
		} else if m.actionMsg.SelectPids != nil {
			m.actionMsg.SelectPids = nil
		} else if m.actionMsg.PointPid != nil {
			m.actionMsg.PointPid = nil
		} else {
			m.actionMsg.VM = VMMain
		}
		pstree, _ := m.pstree.Update(m.actionMsg)
		m.pstree = pstree.(*ModelPsTree)
		return nil
	case VMOneProcess:
		m.actionMsg.VM = VMMain
		m.processDetail = nil
		return nil
	case VMProcessEnv:
		m.actionMsg.VM = m.actionMsg.VMOld
		m.processEnv = nil
		return nil
	case VMPower:
		m.actionMsg.VM = m.actionMsg.VMOld
		m.powerDetail = nil
		return nil
	default:
		return nil
	}
}

// handleKeySpace 处理空格键动作，空格键仅用于选择或取消进程
func (m *ModelMain) handleKeySpace() tea.Cmd {

	switch m.actionMsg.VM {
	case VMMain, VMTree:
		if len(m.modelMsg.DCUPidInfo) == 0 {
			return nil
		}
		if m.actionMsg.PointPid == nil || m.actionMsg.Action != nil {
			return nil
		}
		if m.actionMsg.VM != VMMain && m.actionMsg.VM != VMTree {
			return nil
		}
		if m.actionMsg.SelectPids == nil {
			m.actionMsg.SelectPids = make(map[int32]bool)
		}
		_, have := m.actionMsg.SelectPids[*m.actionMsg.PointPid]
		if have {
			delete(m.actionMsg.SelectPids, *m.actionMsg.PointPid)
		} else {
			m.actionMsg.SelectPids[*m.actionMsg.PointPid] = true
		}
		switch m.actionMsg.VM {
		case VMMain:
			m1, cmd1 := m.ProcessInfo.Update(m.actionMsg)
			m.ProcessInfo = m1.(*ModelProcessInfo)
			return cmd1
		case VMTree:
			m1, cmd1 := m.pstree.Update(m.actionMsg)
			m.pstree = m1.(*ModelPsTree)
			return cmd1
		default:
			return nil
		}
	case VMPower:
		power, _ := m.powerDetail.Update(tea.KeySpace)
		m.powerDetail = power.(*ModelPowerDetail)
		return nil
	default:
		return nil
	}
}

func (m *ModelMain) View() string {
	if m.actionMsg != nil && m.actionMsg.HelpView {
		return HelpStr
	}
	switch m.actionMsg.VM {
	case VMMain:
		if m.actionMsg.Action != nil {
			up := m.dialog.View()
			down := m.Header.View() + m.DCUInfo.View() + m.SysLoad.View() + m.ProcessInfo.View() + "\n"
			return StackPosition(up, down, lipgloss.Center, lipgloss.Center)
		}
		return m.Header.View() + m.DCUInfo.View() + m.SysLoad.View() + m.ProcessInfo.View() + "\n"
	case VMTree:
		if m.actionMsg.Action != nil {
			up := m.dialog.View()
			down := m.pstree.View()
			return StackPosition(up, down, lipgloss.Center, lipgloss.Center)
		}
		return m.pstree.View()
	case VMOneProcess:
		return m.processDetail.View()
	case VMProcessEnv:
		return m.processEnv.View()
	case VMPower:
		return m.powerDetail.View()
	default:
		return ""
	}
}

func initModelInfo(model *ModelMsg) error {
	model.t = time.Now()
	model.MyVersion = DCUTopVersion
	if ver, err := gpu.GetHYVersionInfo(); err != nil {
		return err
	} else {
		model.Version = ver
	}
	model.DCUInfo = backend.DCUSInfoMap
	model.DCUPidInfo = backend.DCUSInfoMap.GetDCUProcessInfo2()
	if sinfo, err := utils.GetSysInfo(); err != nil {
		return err
	} else {
		model.systemInfo = sinfo
	}
	if err := model.DCUInfo.UpdateQuickInfo(); err != nil {
		return err
	}
	if err := model.DCUInfo.UpdateSlowInfo(); err != nil {
		return err
	}
	return nil
}

// updateModelInfo 更新模型信息
func updateModelInfo(modelMsg *ModelMsg, t time.Time) error {
	modelMsg.t = t
	if sinfo, err := utils.GetSysInfo(); err != nil {
		return err
	} else {
		modelMsg.systemInfo = sinfo
	}
	modelMsg.DCUPidInfo = modelMsg.DCUInfo.GetDCUProcessInfo2()
	if err := modelMsg.DCUInfo.UpdateQuickInfo(); err != nil {
		return err
	}
	return nil
}

func (m *ModelMain) handleKeyUp() tea.Cmd {
	switch m.actionMsg.VM {
	case VMMain:
		if len(m.modelMsg.DCUPidInfo) == 0 {
			return nil
		}
		if m.actionMsg.Action != nil {
			return nil
		}
		processes := make([]backend.DCUProcessInfo, 0, 16)
		keys := make([]int, 0, 16)
		for k := range m.modelMsg.DCUPidInfo {
			keys = append(keys, k)
		}
		slices.Sort(keys)
		for _, index := range keys {
			p, have := m.modelMsg.DCUPidInfo[index]
			if have && len(p) > 0 {
				processes = append(processes, p...)
			}
		}
		processNum := len(processes)
		if processNum == 0 {
			return nil
		}
		index := 0
		if m.actionMsg.PointPid == nil {
			// 获取列表中的最后一个进程的pid
			index = processNum - 1
		} else {
			var targetIndex = -1
			for l := processNum - 1; l >= 0; l-- {
				if processes[l].Info.Pid == *m.actionMsg.PointPid {
					targetIndex = l - 1
					break
				}
			}
			if targetIndex == -1 {
				index = processNum - 1
			} else {
				index = targetIndex
			}
		}
		pid := processes[index].Info.Pid
		m.actionMsg.PointPid = &pid
		m.actionMsg.TargetDCUIndex = processes[index].DCU
		m1, cmd1 := m.ProcessInfo.Update(m.actionMsg)
		m2, cmd2 := m.DCUInfo.Update(m.actionMsg)
		m3, cmd3 := m.SysLoad.Update(m.actionMsg)
		m.ProcessInfo = m1.(*ModelProcessInfo)
		m.DCUInfo = m2.(*ModelDCUInfo)
		m.SysLoad = m3.(*ModelSysLoad)
		return tea.Batch(cmd1, cmd2, cmd3)
	case VMTree:
		if len(m.modelMsg.DCUPidInfo) == 0 {
			return nil
		}
		if m.actionMsg.Action != nil {
			return nil
		}
		if len(m.actionMsg.PidTreePids) == 0 {
			return nil
		}
		if m.actionMsg.PointPid == nil {
			pid := m.actionMsg.PidTreePids[len(m.actionMsg.PidTreePids)-1]
			m.actionMsg.PointPid = &pid
		} else {
			idx := slices.Index(m.actionMsg.PidTreePids, *m.actionMsg.PointPid)
			if idx == -1 || idx == 0 {
				*m.actionMsg.PointPid = m.actionMsg.PidTreePids[len(m.actionMsg.PidTreePids)-1]
			} else {
				*m.actionMsg.PointPid = m.actionMsg.PidTreePids[idx-1]
			}
		}
		pstree, _ := m.pstree.Update(m.actionMsg)
		m.pstree = pstree.(*ModelPsTree)
		return nil
	case VMProcessEnv:
		if m.processEnv == nil {
			return nil
		}
		env, _ := m.processEnv.Update(tea.KeyUp)
		m.processEnv = env.(*ModelProcessEnv)
		return nil
	case VMPower:
		power, _ := m.powerDetail.Update(tea.KeyUp)
		m.powerDetail = power.(*ModelPowerDetail)
		return nil
	default:
		return nil
	}

}

func (m *ModelMain) handleKeyDown() tea.Cmd {
	switch m.actionMsg.VM {
	case VMMain:
		if len(m.modelMsg.DCUPidInfo) == 0 {
			return nil
		}
		if m.actionMsg.Action != nil {
			return nil
		}
		processes := make([]backend.DCUProcessInfo, 0, 16)
		keys := make([]int, 0, 16)
		for key := range m.modelMsg.DCUPidInfo {
			keys = append(keys, key)
		}
		slices.Sort(keys)
		for _, index := range keys {
			p, have := m.modelMsg.DCUPidInfo[index]
			if have && len(p) > 0 {
				processes = append(processes, p...)
			}
		}
		processNum := len(processes)
		if processNum == 0 {
			return nil
		}
		index := 0
		if m.actionMsg.PointPid == nil {
			index = 0
		} else {
			var targetIndex = -1
			for l := 0; l < processNum-1; l++ {
				if processes[l].Info.Pid == *m.actionMsg.PointPid {
					targetIndex = l + 1
					if targetIndex >= processNum {
						targetIndex = 0
					}
					break
				}
			}
			if targetIndex == -1 {
				index = 0
			} else {
				index = targetIndex

			}
		}
		pid := processes[index].Info.Pid
		m.actionMsg.PointPid = &pid
		m.actionMsg.TargetDCUIndex = processes[index].DCU
		m1, cmd1 := m.ProcessInfo.Update(m.actionMsg)
		m2, cmd2 := m.DCUInfo.Update(m.actionMsg)
		m3, cmd3 := m.SysLoad.Update(m.actionMsg)
		m.ProcessInfo = m1.(*ModelProcessInfo)
		m.DCUInfo = m2.(*ModelDCUInfo)
		m.SysLoad = m3.(*ModelSysLoad)
		return tea.Batch(cmd1, cmd2, cmd3)
	case VMTree:
		if len(m.modelMsg.DCUPidInfo) == 0 {
			return nil
		}
		if m.actionMsg.Action != nil {
			return nil
		}
		if len(m.actionMsg.PidTreePids) == 0 {
			return nil
		}
		if m.actionMsg.PointPid == nil {
			pid := m.actionMsg.PidTreePids[0]
			m.actionMsg.PointPid = &pid
		} else {
			idx := slices.Index(m.actionMsg.PidTreePids, *m.actionMsg.PointPid)
			if idx == -1 || idx == len(m.actionMsg.PidTreePids)-1 {
				*m.actionMsg.PointPid = m.actionMsg.PidTreePids[0]
			} else {
				*m.actionMsg.PointPid = m.actionMsg.PidTreePids[idx+1]
			}
		}
		pstree, _ := m.pstree.Update(m.actionMsg)
		m.pstree = pstree.(*ModelPsTree)
		return nil
	case VMProcessEnv:
		if m.processEnv == nil {
			return nil
		}
		env, _ := m.processEnv.Update(tea.KeyDown)
		m.processEnv = env.(*ModelProcessEnv)
		return nil
	case VMPower:
		power, _ := m.powerDetail.Update(tea.KeyDown)
		m.powerDetail = power.(*ModelPowerDetail)
		return nil
	default:
		return nil
	}
}
