package webui

import "kjol/wasmruntime/vdom"

// Port of web/kit/PrettyTable.tsx.
//
// PrettyTable renders only the table chrome: the container/wrapper, the styled
// <thead>, and an empty-styled <tbody> into which the CALLER passes body rows as
// children. That matches the TSX, whose body is `props.children` (rows built with
// AutoTable's TdLeft/TdRight/TdCenter cells). Those cell helpers live in AutoTable
// (not ported here), so callers build rows with the vdom tag builders directly,
// e.g. vdom.Tr(vdom.Td(vdom.Attr("class","text-right"), vdom.Text(...))).
// (CellGrid is the component that models columns + a per-cell Render func.)
//
// The enum values, class maps, and shared class strings that PrettyTable.tsx
// imports from AutoTable.tsx are inlined here (prefixed pt*/PrettyTable*) so this
// file compiles on its own and never clashes with a parallel AutoTable port.

// PrettyTableColumnPosition controls header + cell alignment.
type PrettyTableColumnPosition int

const (
	PrettyTableColLeft   PrettyTableColumnPosition = 0
	PrettyTableColRight  PrettyTableColumnPosition = 1
	PrettyTableColCenter PrettyTableColumnPosition = 2
)

// PrettyTableHeaderColor selects the header background/text palette.
type PrettyTableHeaderColor int

const (
	PrettyTableColorDefault  PrettyTableHeaderColor = 0
	PrettyTableColorBlue     PrettyTableHeaderColor = 1
	PrettyTableColorGreen    PrettyTableHeaderColor = 2
	PrettyTableColorGray     PrettyTableHeaderColor = 3
	PrettyTableColorDarkBlue PrettyTableHeaderColor = 4
)

// PrettyTableSize selects header/body padding density.
type PrettyTableSize int

const (
	PrettyTableSizeDefault      PrettyTableSize = 0
	PrettyTableSizeCompact      PrettyTableSize = 1
	PrettyTableSizeSuperCompact PrettyTableSize = 2
)

const ptTblContainer = "relative flex flex-col w-full h-full bg-surface rounded-default overflow-hidden"
const ptTblWrapper = "overflow-x-auto w-full"
const ptTblBase = "min-w-full"
const ptHeaderContent = "transition-transform duration-150 ease-in-out"
const ptHeaderInnerBase = "flex justify-between gap-2 items-center"

var ptHeaderColorCls = map[PrettyTableHeaderColor]string{
	PrettyTableColorDefault:  "bg-surface-muted",
	PrettyTableColorBlue:     "bg-sky-700 text-white",
	PrettyTableColorGreen:    "bg-green-700 text-white",
	PrettyTableColorGray:     "bg-neutral-600 text-white",
	PrettyTableColorDarkBlue: "bg-sky-900 text-white",
}

var ptHeaderTextCls = map[PrettyTableHeaderColor]string{
	PrettyTableColorDefault:  "font-bold uppercase tracking-wider",
	PrettyTableColorBlue:     "font-semibold",
	PrettyTableColorGreen:    "font-semibold",
	PrettyTableColorGray:     "font-semibold",
	PrettyTableColorDarkBlue: "font-semibold",
}

// ptRowHoverCls is applied to the tbody when Hover is on (matches the TSX
// PT_ROW_HOVER_CLS map).
var ptRowHoverCls = map[PrettyTableHeaderColor]string{
	PrettyTableColorDefault:  "[&_tr:hover]:!bg-surface-strong",
	PrettyTableColorBlue:     "[&_tr:hover]:!bg-sky-100 dark:bg-sky-900",
	PrettyTableColorGreen:    "[&_tr:hover]:!bg-green-100 dark:bg-green-900",
	PrettyTableColorGray:     "[&_tr:hover]:!bg-surface-strong",
	PrettyTableColorDarkBlue: "[&_tr:hover]:!bg-sky-100 dark:bg-sky-900",
}

var ptHeaderPaddingCls = map[PrettyTableSize]string{
	PrettyTableSizeDefault:      "p-4 text-sm",
	PrettyTableSizeCompact:      "py-1.5 px-2 text-sm",
	PrettyTableSizeSuperCompact: "py-1 px-2 text-ss",
}

var ptBodyPaddingCls = map[PrettyTableSize]string{
	PrettyTableSizeDefault:      "text-sm [&_td]:p-4",
	PrettyTableSizeCompact:      "text-sm [&_td]:py-1 [&_td]:px-2",
	PrettyTableSizeSuperCompact: "text-ss [&_td]:py-0.5 [&_td]:px-2",
}

var ptPosCls = map[PrettyTableColumnPosition]string{
	PrettyTableColLeft:   "text-left",
	PrettyTableColRight:  "text-right",
	PrettyTableColCenter: "text-center",
}

var ptHeaderInnerPos = map[PrettyTableColumnPosition]string{
	PrettyTableColLeft:   "",
	PrettyTableColRight:  "flex-row-reverse",
	PrettyTableColCenter: "justify-center",
}

// PrettyTableColumn is one header column definition.
type PrettyTableColumn struct {
	DisplayName     string
	DisplayPosition PrettyTableColumnPosition
	HeaderClasses   string
}

// PrettyTableOptions configures the table chrome. The Go zero value matches the
// TSX defaults exactly (size default, all flags off, default color, left align),
// so an unset PrettyTableOptions{} needs no merge.
type PrettyTableOptions struct {
	Size              PrettyTableSize
	Shadow            bool
	Hover             bool
	Alternate         bool
	HeaderBorderY     bool
	SurroundingBorder bool
	BorderX           bool
	BorderY           bool
	Color             PrettyTableHeaderColor
	TableLayoutAuto   bool
}

func prettyTableBodyClass(o PrettyTableOptions) string {
	c := ptBodyPaddingCls[o.Size]
	if o.BorderY {
		c = cx(c, "[&_td+td]:border-l [&_td+td]:border-line-strong")
	}
	if o.Alternate {
		c = cx(c, "[&_tr:nth-child(even)]:bg-surface-raised")
	}
	if o.BorderX {
		c = cx(c, "[&_tr:not(:last-child)]:border-b [&_tr:not(:last-child)]:border-line-strong")
	}
	if o.Hover {
		c = cx(c, ptRowHoverCls[o.Color])
	}
	return c
}

// PrettyTable renders the table container + styled header, with body rows passed
// as children (see the file comment). opts may be the zero value for defaults.
func PrettyTable(columns []PrettyTableColumn, opts PrettyTableOptions, children ...*vdom.VNode) *vdom.VNode {
	containerCls := ptTblContainer
	if opts.SurroundingBorder {
		containerCls = cx(containerCls, "border border-line-strong")
	}
	if opts.Shadow {
		containerCls = cx(containerCls, "shadow-sm")
	}

	tableCls := ptTblBase
	if !opts.TableLayoutAuto {
		tableCls = cx(tableCls, "table-fixed")
	}

	var headerCells []*vdom.VNode
	for displayIdx, col := range columns {
		pos := col.DisplayPosition
		thCls := cx(ptHeaderPaddingCls[opts.Size], ptHeaderColorCls[opts.Color], ptPosCls[pos])
		if opts.HeaderBorderY && displayIdx > 0 {
			thCls = cx(thCls, "border-l border-l-neutral-300")
		}
		thCls = cx(thCls, col.HeaderClasses)

		innerCls := cx(ptHeaderInnerBase, ptHeaderInnerPos[pos])
		headerCells = append(headerCells, vdom.Th(vdom.Attr("class", thCls),
			vdom.Div(vdom.Attr("class", ptHeaderContent),
				vdom.Div(vdom.Attr("class", innerCls),
					vdom.Div(vdom.Attr("class", cx("grow text-sm", ptHeaderTextCls[opts.Color])),
						vdom.Text(col.DisplayName),
					),
				),
			),
		))
	}

	thead := vdom.Thead(vdom.Attr("class", "[&_th]:border-b [&_th]:border-line-strong"),
		vdom.Tr(kids(nil, headerCells)...),
	)

	tbody := vdom.Tbody(kids([]vdom.Mod{vdom.Attr("class", prettyTableBodyClass(opts))}, children)...)

	return vdom.Div(vdom.Attr("class", containerCls),
		vdom.Div(vdom.Attr("class", ptTblWrapper),
			vdom.Table(vdom.Attr("class", tableCls), thead, tbody),
		),
	)
}
