package tui

import (
	"fmt"
	"get-container/cmd/hytop/backend"
	"maps"
	"strings"

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

type ModelProcessInfo struct {
	Title            string
	DoubleMiddleLine string
	MiddleLine       string
	BottomLine       string
	NoProceseLine    string // 没有进程时显示的行
	Cache            map[int][]backend.DCUProcessInfo
	width            int
	style            lipgloss.Style
}

const (
	Processes             = " Processes:"
	ModelProcessInfoTitle = " DCU    PID      USER  DCU-MEM SDMA  %CPU  %MEM      TIME  Command"
	ModelProcessInfoNoPro = "  No running processes found"
)

func NewModelProcessInfo(width int) *ModelProcessInfo {
	result := ModelProcessInfo{width: width, Cache: make(map[int][]backend.DCUProcessInfo), style: lipgloss.NewStyle()}
	return &result
}

func (m *ModelProcessInfo) Init() tea.Cmd {
	sb := strings.Builder{}
	sb.WriteString(myBorder.Left)
	sb.WriteString(Processes)

	uah := fmt.Sprintf("%s@%s ", m.style.Foreground(lipgloss.Color("#edff2cff")).SetString(backend.User).String(),
		m.style.Foreground(lipgloss.Color("#a3ff2bff")).SetString(backend.HostName).String())
	space := strings.Repeat(" ", m.width-lipgloss.Width(Processes)-lipgloss.Width(uah)-2)

	sb.WriteString(space)
	sb.WriteString(uah)
	sb.WriteString(myBorder.Right)
	sb.WriteByte('\n')
	sb.WriteString(myBorder.Left)
	sb.WriteString(ModelProcessInfoTitle)
	sb.WriteString(strings.Repeat(" ", m.width-2-lipgloss.Width(ModelProcessInfoTitle)))
	sb.WriteString(myBorder.Right)
	sb.WriteByte('\n')
	m.Title = sb.String()
	m.DoubleMiddleLine = "╞" + strings.Repeat("═", m.width-2) + "╡\n"
	m.MiddleLine = myBorder.MiddleLeft + strings.Repeat("─", m.width-2) + myBorder.MiddleRight + "\n"
	m.BottomLine = myBorder.BottomLeft + strings.Repeat("═", m.width-2) + myBorder.BottomRight
	m.NoProceseLine = myBorder.Left + ModelProcessInfoNoPro + strings.Repeat(" ", m.width-2-lipgloss.Width(ModelProcessInfoNoPro)) + myBorder.Right + "\n"
	return nil
}

func (m *ModelProcessInfo) View() string {
	haveProcess := false
	lines := make([]string, 0)
	sb := strings.Builder{}
	for index := range 64 {
		processes, have := m.Cache[index]
		if !have {
			continue
		}
		for _, process := range processes {
			haveProcess = true
			sb.WriteString(myBorder.Left)
			sb.WriteString(FormatStr(fmt.Sprintf("%d", process.DCU), 4, lipgloss.Right))
			sb.WriteByte(' ')
			sb.WriteString(FormatStr(fmt.Sprintf("%d", process.Info.Pid), 6, lipgloss.Right))
			sb.WriteByte(' ')
			sb.WriteString(FormatStr(process.Info.User, 9, lipgloss.Right))
			sb.WriteByte(' ')
			sb.WriteString(FormatStr(process.DCUMem, 8, lipgloss.Right))
			sb.WriteByte(' ')
			sb.WriteString(FormatStr(fmt.Sprintf("%d", process.SDMA), 4, lipgloss.Right))
			sb.WriteByte(' ')
			sb.WriteString(FormatStr(fmt.Sprintf("%.1f", process.Info.CPU), 5, lipgloss.Right))
			sb.WriteByte(' ')
			sb.WriteString(FormatStr(fmt.Sprintf("%.1f", process.Info.Mem), 5, lipgloss.Right))
			sb.WriteByte(' ')
			sb.WriteString(FormatStr(process.Info.Time, 9, lipgloss.Right))
			sb.WriteString("  ")
			w := m.width - lipgloss.Width(sb.String()) - 2
			tw := lipgloss.Width(process.Info.Cmd)
			if w >= tw {
				sb.WriteString(process.Info.Cmd)
				sb.WriteString(strings.Repeat(" ", w-tw))
			} else {
				sb.WriteString(FormatStr(process.Info.Cmd, w-2, lipgloss.Left))
				sb.WriteString("..")
			}
			sb.WriteByte(' ')
			sb.WriteString(myBorder.Right)
			sb.WriteByte('\n')
			lines = append(lines, sb.String())
			sb.Reset()
		}
		lines = append(lines, m.MiddleLine)
	}

	sb.WriteString(m.Title)
	sb.WriteString(m.DoubleMiddleLine)
	if !haveProcess {
		sb.WriteString(m.NoProceseLine)
	} else {
		for _, v := range lines[:len(lines)-1] {
			sb.WriteString(v)
		}
	}
	sb.WriteString(m.BottomLine)
	return sb.String()
}

func (m *ModelProcessInfo) Update(inputMsg tea.Msg) (tea.Model, tea.Cmd) {
	switch msg := inputMsg.(type) {
	case *ModelMsg:
		clear(m.Cache)
		maps.Copy(m.Cache, msg.DCUPidInfo)
	}
	return m, nil
}
