package webui

import (
	"strconv"
	"strings"

	"kjol/vdom"
)

// Port of web/kit/Tabs.tsx.
//
// NOTE: The TSX persisted the active index in localStorage (storageKey) and
// synced sibling tab groups via synthetic "storage" events on mount. Those are
// browser-only side effects with no neutral-runtime equivalent, so they are
// dropped: selection collapses to a plain ActiveIndex value plus an OnTabChange
// callback (the caller owns the state, per the porting guide). The TSX
// defaultIndex prop likewise collapses into the caller-supplied ActiveIndex.

const tabsBase = "flex items-center gap-1.5 cursor-pointer py-2 px-4 text-sm font-medium bg-transparent border-0 border-b-2 transition-[color,border-color] duration-150"
const tabsInactive = "text-text-muted border-line hover:text-text-body"
const tabsActive = "text-accent border-primary"

// TabItem is one tab: a title, an optional numeric badge (shown only when > 0),
// and optional inline panel content.
type TabItem struct {
	Title   string
	Badge   int
	Content *vdom.VNode
}

// TabGroupProps configures TabGroup. ActiveIndex is the selected tab; clicking a
// tab calls OnTabChange with its index (the caller updates ActiveIndex).
type TabGroupProps struct {
	Items       []TabItem
	ActiveIndex int
	OnTabChange func(int)
	// Actions is optional content rendered on the right side of the tab bar.
	Actions *vdom.VNode
	// Class adds extra classes on the root (e.g. "ui-tabs" for structured panel
	// CSS, "page-tabs" for tighter spacing).
	Class string
	// Fill makes tabs fill available height with internally-scrolling panels.
	Fill bool
	// Stretch is tri-state (nil = unset): when Actions is nil it defaults to
	// true, otherwise it defaults to false — matching the TSX prop semantics.
	Stretch  *bool
	PageTabs bool
}

// TabGroup renders a horizontal tab bar with optional inline panels.
func TabGroup(p TabGroupProps) *vdom.VNode {
	structured := p.Fill || strings.Contains(p.Class, "ui-tabs")
	pageTabs := p.PageTabs || strings.Contains(p.Class, "page-tabs")

	var rootCls string
	switch {
	case p.Fill:
		rootCls = cx("ui-tabs flex w-full min-h-0 flex-1 flex-col overflow-hidden", p.Class)
	case pageTabs:
		rootCls = cx("w-full page-tabs", p.Class)
	default:
		rootCls = cx("w-full pb-4", p.Class)
	}

	headerCls := "overflow-x-auto flex flex-row w-full text-sm"
	if structured {
		headerCls = "header overflow-x-auto flex flex-row w-full shrink-0 text-sm"
	}

	stretchTabs := false
	if p.Actions != nil {
		stretchTabs = p.Stretch != nil && *p.Stretch
	} else {
		stretchTabs = p.Stretch == nil || *p.Stretch
	}
	stretchCls := ""
	if stretchTabs {
		stretchCls = "flex-1 justify-center md:flex-initial md:justify-start"
	}

	panelCls := func(index int) string {
		active := index == p.ActiveIndex
		if !structured {
			if active {
				return ""
			}
			return "hidden"
		}
		if !active {
			return "panel hidden"
		}
		if p.Fill {
			return "panel flex min-h-0 flex-1 flex-col overflow-hidden"
		}
		return "panel"
	}

	header := []vdom.Mod{vdom.Attr("class", headerCls)}
	for i, item := range p.Items {
		idx := i
		state := tabsInactive
		if i == p.ActiveIndex {
			state = tabsActive
		}
		btn := []vdom.Mod{
			vdom.Attr("type", "button"),
			vdom.Attr("class", cx(tabsBase, stretchCls, state)),
			vdom.On(vdom.EVENT_CLICK, func() {
				if p.OnTabChange != nil {
					p.OnTabChange(idx)
				}
			}),
			vdom.Text(item.Title),
		}
		if item.Badge > 0 {
			btn = append(btn, vdom.Span(vdom.Attr("class", "inline-flex items-center justify-center min-w-5 h-5 px-1 text-xs font-semibold bg-primary text-white rounded-full"),
				vdom.Text(strconv.Itoa(item.Badge))))
		}
		header = append(header, vdom.Button(btn...))
	}
	if p.Actions != nil {
		header = append(header, vdom.Div(vdom.Attr("class", "tab-actions flex-1 self-end border-b-2 border-line flex items-center justify-end pb-1"),
			vdom.Div(vdom.Attr("class", "flex items-center min-w-0"), p.Actions),
		))
	}

	root := []vdom.Mod{vdom.Attr("class", rootCls), vdom.Div(header...)}

	hasInlinePanels := false
	for _, item := range p.Items {
		if item.Content != nil {
			hasInlinePanels = true
			break
		}
	}
	if hasInlinePanels {
		for i, item := range p.Items {
			if item.Content == nil {
				continue
			}
			root = append(root, vdom.Div(vdom.Attr("class", panelCls(i)), item.Content))
		}
	}
	return vdom.Div(root...)
}
