import { createSignal, createMemo, onCleanup, onMount, Show, For, JSXElement } from "solid-js";

// CrmTabGroup / CrmSubTabGroup — drop-in, behaviourally identical siblings of
// TabGroup (same props, storageKey syncing, controlled/uncontrolled index) with
// a different look:
//   - CrmTabGroup    → boxed tabs with a sky-blue top accent (ported from the old cdrl_2.0 tabs)
//   - CrmSubTabGroup → interlocking right-pointing arrows (a process-flow strip)

interface CrmTabItem {
    title: string;
    badge?: number;
    content: JSXElement;
}

interface CrmTabGroupProps {
    items: CrmTabItem[];
    storageKey?: string;
    activeIndex?: number;
    onTabChange?: (index: number) => void;
    defaultIndex?: number;
}

function resolveCrmBadge(badge: number | undefined): number | undefined {
    return typeof badge === "function" ? (badge as () => number)() : badge;
}

// Shared active-index state: mirrors TabGroup exactly (localStorage persistence,
// cross-component sync via synthetic storage events, optional controlled index).
// Takes the memoized `items` accessor (not props.items) so length checks read the
// same single evaluation the render does — see the createMemo note in CrmTabGroup.
function createCrmTabState(props: CrmTabGroupProps, items: () => CrmTabItem[]) {
    const getInitialIndex = () => {
        if (props.storageKey) {
            const stored = localStorage.getItem(props.storageKey);
            if (stored !== null) {
                const parsed = parseInt(stored, 10);
                if (!isNaN(parsed) && parsed >= 0 && parsed < items().length) {
                    return parsed;
                }
            }
        }
        return props.defaultIndex ?? 0;
    };

    const [_activeIndex, _setActiveIndex] = createSignal(getInitialIndex());

    const activeIndex = (): number => {
        const controlled = props.activeIndex;
        if (controlled != null) {
            return typeof controlled === "function" ? (controlled as () => number)() : controlled;
        }
        return _activeIndex();
    };

    const setActiveIndex = (i: number) => {
        _setActiveIndex(i);
        if (props.storageKey) {
            const v = String(i);
            localStorage.setItem(props.storageKey, v);
            window.dispatchEvent(new StorageEvent("storage", { key: props.storageKey, newValue: v }));
        }
        props.onTabChange && props.onTabChange(i);
    };

    onMount(() => {
        if (!props.storageKey) return;
        const handler = (e: StorageEvent) => {
            if (e.key !== props.storageKey || e.newValue == null) return;
            const n = parseInt(e.newValue, 10);
            if (!isNaN(n) && n >= 0 && n < items().length && n !== _activeIndex()) {
                _setActiveIndex(n);
                props.onTabChange && props.onTabChange(n);
            }
        };
        window.addEventListener("storage", handler);
        onCleanup(() => window.removeEventListener("storage", handler));
    });

    return { activeIndex, setActiveIndex };
}

function crmTabContent(items: CrmTabItem[], activeIndex: () => number) {
    return <For each={items}>{(item: CrmTabItem, index: () => number) => (
        <div class={index() === activeIndex() ? "" : "hidden"}>
            {item.content}
        </div>
    )}</For>;
}

// --- CrmTabGroup: boxed top-accent tabs -------------------------------------

// Ported from the old cdrl_2.0 TabGroup. Inactive tabs are flat with only a
// bottom border (neutral-300) that forms the baseline; a trailing flex-1 filler
// extends that baseline past the last tab to the right edge. The active tab
// drops its bottom border and gains 1px left/right borders plus a 2px sky-700
// top edge, so it reads as a raised box connected to the content below. No body
// panel — content sits flat beneath the row, as in the old design.
//
// Per-tab borders (no negative-margin overlap) mean the row's overflow-x-auto
// can't clip anything: the baseline simply has a gap under the active tab.
const CRM_TAB_ROW = "flex w-full overflow-x-auto text-sm";
const CRM_TAB_BASE = "flex items-center gap-1.5 cursor-pointer p-4 font-medium border-line-strong transition-colors";
const CRM_TAB_INACTIVE = "border-b text-ink-muted hover:text-ink";
const CRM_TAB_ACTIVE = "border-x border-t-2 border-t-sky-700 text-primary";
const CRM_TAB_BADGE = "inline-flex items-center justify-center min-w-5 h-5 px-1 text-xs font-semibold bg-primary text-white rounded-full";

export function CrmTabGroup(props: CrmTabGroupProps) {
    // Memoize props.items: callers pass items={[{content: <Comp/>}]} where each
    // `content` is eager JSX, and Solid re-evaluates a `prop={expr}` getter on every
    // read. Reading props.items directly (in the button For, the content For, and the
    // length checks reached from the onclick handler) would re-run createComponent on
    // every tab's content each time — and the read inside setActiveIndex happens outside
    // the render owner, so those rebuilt components lose their provider context
    // (useToast/useModal throw). The memo evaluates the tree once, inside this owner.
    const items = createMemo(() => props.items);
    const { activeIndex, setActiveIndex } = createCrmTabState(props, items);

    return <div class="w-full">
        <div class={CRM_TAB_ROW}>
            <For each={items()}>{(item: CrmTabItem, index: () => number) => (
                <button type="button" onclick={() => setActiveIndex(index())} class={CRM_TAB_BASE + " " + (index() === activeIndex() ? CRM_TAB_ACTIVE : CRM_TAB_INACTIVE)}>
                    {item.title}
                    <Show when={(() => {
                        const b = resolveCrmBadge(item.badge);
                        return b != null && b > 0;
                    })()}>
                        <span class={CRM_TAB_BADGE}>{resolveCrmBadge(item.badge)}</span>
                    </Show>
                </button>
            )}</For>
            <div class="flex-1 border-b border-line-strong"></div>
        </div>
        <div>
            {crmTabContent(items(), activeIndex)}
        </div>
    </div>;
}

// --- CrmSubTabGroup: segmented control --------------------------------------

// A single rounded, bordered group split into segments with dividers between
// them. The active segment is filled gray with white text; inactive segments
// are white and recede. The group is left-aligned (flush with the file-folder
// tabs) and a full-width baseline separates the bar from the content below.
const CRM_SUBTAB_WRAP = "flex pb-3 border-b border-line-strong overflow-x-auto";
const CRM_SUBTAB_GROUP = "inline-flex items-stretch rounded-md border border-line-strong overflow-hidden text-sm select-none";
const CRM_SUBTAB_BASE = "flex items-center gap-1.5 py-1 px-3 cursor-pointer font-medium whitespace-nowrap transition-colors";
const CRM_SUBTAB_DIVIDER = "border-l border-line-strong";
const CRM_SUBTAB_ACTIVE = "bg-neutral-500 text-white";
const CRM_SUBTAB_INACTIVE = "bg-surface text-ink-soft hover:bg-surface-raised hover:text-ink";
const CRM_SUBTAB_BADGE = "inline-flex items-center justify-center min-w-5 h-5 px-1 text-xs font-semibold bg-black/10 text-current rounded-full";

export function CrmSubTabGroup(props: CrmTabGroupProps) {
    // See CrmTabGroup: memoize eager `content` JSX so it's built once, in-owner.
    const items = createMemo(() => props.items);
    const { activeIndex, setActiveIndex } = createCrmTabState(props, items);

    return <div class="w-full pt-3">
        <div class={CRM_SUBTAB_WRAP}>
            <div class={CRM_SUBTAB_GROUP}>
                <For each={items()}>{(item: CrmTabItem, index: () => number) => (
                    <button type="button" onclick={() => setActiveIndex(index())} class={CRM_SUBTAB_BASE + (index() > 0 ? " " + CRM_SUBTAB_DIVIDER : "") + " " + (index() === activeIndex() ? CRM_SUBTAB_ACTIVE : CRM_SUBTAB_INACTIVE)}>
                        {item.title}
                        <Show when={(() => {
                            const b = resolveCrmBadge(item.badge);
                            return b != null && b > 0;
                        })()}>
                            <span class={CRM_SUBTAB_BADGE}>{resolveCrmBadge(item.badge)}</span>
                        </Show>
                    </button>
                )}</For>
            </div>
        </div>
        <div class="pt-3">
            {crmTabContent(items(), activeIndex)}
        </div>
    </div>;
}
