import { createSignal, createEffect, For, Show, JSXElement } from "solid-js";
import { Icon } from "./Icons.tsx";

// Baseline Tailwind for the scoped .ui-accordion stack.  The ui-* class
// names are kept so page-specific CSS overrides (e.g. sale.css,
// licensing.css) can continue to layer on top.

const ROOT = "ui-accordion border border-neutral-200 rounded-default overflow-hidden";
const ITEM = "ui-accordion-item border-b border-neutral-200 last:border-b-0";
const TRIGGER = "ui-accordion-trigger flex items-center justify-between w-full py-3 px-4 text-left font-medium text-neutral-900 bg-neutral-50 cursor-pointer border-none transition-colors hover:bg-neutral-100 active:bg-neutral-200 focus:outline-hidden disabled:text-neutral-400 disabled:cursor-not-allowed disabled:bg-neutral-50";
const TITLE = "ui-accordion-title flex-1";
const CONTENT = "ui-accordion-content px-4 pb-4 text-neutral-700";

function iconCls(open: boolean): string {
    return "ui-accordion-icon text-neutral-500 leading-none transition-transform duration-200" +
        (open ? " rotate-180" : "");
}

interface AccordionItemProps {
    startOpen?: boolean;
    isOpen?: boolean;
    disabled?: boolean;
    title?: string;
    children?: JSXElement;
}

export function AccordionItem(props: AccordionItemProps) {
    const getStartOpen = () => typeof props.startOpen === "function" ? (props.startOpen as () => boolean)() : !!props.startOpen;
    const [isOpen, setIsOpen] = createSignal(getStartOpen());

    createEffect(() => {
        if (props.isOpen === undefined) return;
        const v = typeof props.isOpen === "function" ? (props.isOpen as () => boolean)() : !!props.isOpen;
        setIsOpen(v);
    });

    const isDisabled = () => typeof props.disabled === "function" ? (props.disabled as () => boolean)() : !!props.disabled;
    const title = () => typeof props.title === "function" ? (props.title as () => string)() : props.title;

    const toggle = () => {
        if (isDisabled()) return;
        setIsOpen(!isOpen());
    };

    return (
        <div class={ITEM}>
            <button type="button" class={TRIGGER} disabled={isDisabled()} onclick={toggle} aria-expanded={isOpen()}>
                <span class={TITLE}>{title()}</span>
                <Show when={!isDisabled()}>
                    <span class={iconCls(isOpen())}>
                        <Icon icon={isOpen() ? "chevron-up" : "chevron-down"} size={18}/>
                    </span>
                </Show>
            </button>
            <Show when={isOpen() && !isDisabled()}>
                <div class={CONTENT}>
                    {props.children}
                </div>
            </Show>
        </div>
    );
}

interface AccordionItemData {
    title: string;
    content: JSXElement;
    disabled?: boolean;
}

interface AccordionProps {
    items?: AccordionItemData[];
}

export function Accordion(props: AccordionProps) {
    const items = () => props.items || [];
    return (
        <div class={ROOT}>
            <For each={items()}>{(item) => (
                <AccordionItem title={(() => {
                    const t = item.title;
                    return typeof t === "function" ? (t as () => string)() : t;
                })()} disabled={(() => {
                    const d = item.disabled;
                    return typeof d === "function" ? (d as () => boolean)() : !!d;
                })()}>
                    {item.content}
                </AccordionItem>
            )}</For>
        </div>
    );
}

interface SingleAccordionProps {
    items?: AccordionItemData[];
    startOpen?: number;
}

export function SingleAccordion(props: SingleAccordionProps) {
    const items = () => props.items || [];
    const [openIndex, setOpenIndex] = createSignal(props.startOpen ?? 0);

    const toggleItem = (index: number) => {
        setOpenIndex(openIndex() === index ? -1 : index);
    };

    return (
        <div class={ROOT}>
            <For each={items()}>{(item, index) => (
                <div class={ITEM}>
                    <button type="button" class={TRIGGER} disabled={!!item.disabled} onclick={() => toggleItem(index())} aria-expanded={openIndex() === index()}>
                        <span class={TITLE}>{item.title}</span>
                        <Show when={!item.disabled}>
                            <span class={iconCls(openIndex() === index())}>
                                <Icon icon={openIndex() === index() ? "chevron-up" : "chevron-down"} size={18}/>
                            </span>
                        </Show>
                    </button>
                    <Show when={openIndex() === index() && !item.disabled}>
                        <div class={CONTENT}>
                            {item.content}
                        </div>
                    </Show>
                </div>
            )}</For>
        </div>
    );
}
