package webui

import "kjol/vdom"

// Port of web/kit/Accordion.tsx.
//
// NOTE: The TSX AccordionItem kept its open state in an internal signal (seeded
// by startOpen, synced from an optional isOpen prop via createEffect). Per the
// porting guide, selection state collapses to a plain value + callback: IsOpen
// is a plain bool and OnToggle fires on click (the caller flips its own state).
// The TSX startOpen prop collapses into the caller-supplied initial IsOpen /
// open[] / openIndex.

const accordionRootCls = "ui-accordion border border-line rounded-default overflow-hidden"
const accordionItemCls = "ui-accordion-item border-b border-line last:border-b-0"
const accordionTriggerCls = "ui-accordion-trigger flex items-center justify-between w-full py-3 px-4 text-left font-medium text-ink bg-surface-muted cursor-pointer border-none transition-colors hover:bg-surface-raised active:bg-surface-strong focus:outline-hidden disabled:text-ink-faint disabled:cursor-not-allowed disabled:bg-surface-muted"
const accordionTitleCls = "ui-accordion-title flex-1"
const accordionContentCls = "ui-accordion-content px-4 pb-4 text-ink-soft"

func accordionIconCls(open bool) string {
	c := "ui-accordion-icon text-ink-muted leading-none transition-transform duration-200"
	if open {
		c += " rotate-180"
	}
	return c
}

// AccordionItemProps configures a single AccordionItem. IsOpen is the current
// open state; OnToggle fires when the (enabled) trigger is clicked.
type AccordionItemProps struct {
	IsOpen   bool
	Disabled bool
	Title    string
	OnToggle func()
}

// AccordionItem is one collapsible row: a trigger button plus its content
// (children), shown when open and not disabled.
func AccordionItem(p AccordionItemProps, children ...*vdom.VNode) *vdom.VNode {
	ariaExpanded := "false"
	if p.IsOpen {
		ariaExpanded = "true"
	}
	trigger := []vdom.Mod{
		vdom.Attr("type", "button"),
		vdom.Attr("class", accordionTriggerCls),
		vdom.Attr("aria-expanded", ariaExpanded),
		vdom.On(vdom.EVENT_CLICK, func() {
			if p.Disabled {
				return
			}
			if p.OnToggle != nil {
				p.OnToggle()
			}
		}),
		vdom.Span(vdom.Attr("class", accordionTitleCls), vdom.Text(p.Title)),
	}
	if p.Disabled {
		trigger = append(trigger, vdom.Attr("disabled", "disabled"))
	} else {
		chev := "chevron-down"
		if p.IsOpen {
			chev = "chevron-up"
		}
		trigger = append(trigger, vdom.Span(vdom.Attr("class", accordionIconCls(p.IsOpen)),
			Icon(chev, 18, ""),
		))
	}

	mods := []vdom.Mod{vdom.Attr("class", accordionItemCls), vdom.Button(trigger...)}
	if p.IsOpen && !p.Disabled {
		mods = append(mods, vdom.Div(kids([]vdom.Mod{vdom.Attr("class", accordionContentCls)}, children)...))
	}
	return vdom.Div(mods...)
}

// AccordionItemData is one entry for Accordion / SingleAccordion.
type AccordionItemData struct {
	Title    string
	Content  *vdom.VNode
	Disabled bool
}

// Accordion renders independently-collapsible items. open[i] is item i's open
// state (missing entries are closed); clicking item i calls onToggle(i) — the
// caller flips open[i].
func Accordion(items []AccordionItemData, open []bool, onToggle func(int)) *vdom.VNode {
	mods := []vdom.Mod{vdom.Attr("class", accordionRootCls)}
	for i, item := range items {
		idx := i
		isOpen := i < len(open) && open[i]
		mods = append(mods, AccordionItem(AccordionItemProps{
			IsOpen:   isOpen,
			Disabled: item.Disabled,
			Title:    item.Title,
			OnToggle: func() {
				if onToggle != nil {
					onToggle(idx)
				}
			},
		}, item.Content))
	}
	return vdom.Div(mods...)
}

// SingleAccordion renders items where at most one is open. openIndex is the open
// item (-1 = none); clicking an item calls onChange with the new open index —
// the clicked index, or -1 if that item was already open.
func SingleAccordion(items []AccordionItemData, openIndex int, onChange func(int)) *vdom.VNode {
	mods := []vdom.Mod{vdom.Attr("class", accordionRootCls)}
	for i, item := range items {
		idx := i
		mods = append(mods, AccordionItem(AccordionItemProps{
			IsOpen:   openIndex == i,
			Disabled: item.Disabled,
			Title:    item.Title,
			OnToggle: func() {
				if onChange == nil {
					return
				}
				if openIndex == idx {
					onChange(-1)
				} else {
					onChange(idx)
				}
			},
		}, item.Content))
	}
	return vdom.Div(mods...)
}
