import { createMemo, For } from "solid-js";
import {
    AUTOTABLE_HEADER_COLOR_BLUE,
    AUTOTABLE_HEADER_COLOR_DARK_BLUE,
    AUTOTABLE_HEADER_COLOR_DEFAULT,
    AUTOTABLE_HEADER_COLOR_GRAY,
    AUTOTABLE_HEADER_COLOR_GREEN,
    AUTOTABLE_SIZE_DEFAULT,
    BODY_PADDING_CLS,
    COL_POS_LEFT,
    HEADER_COLOR_CLS,
    HEADER_CONTENT,
    HEADER_INNER_BASE,
    HEADER_INNER_POS,
    HEADER_PADDING_CLS,
    HEADER_TEXT_CLS,
    POS_CLS,
    TBL_BASE,
    TBL_CONTAINER,
    TBL_WRAPPER,
    type AutoTableHeaderColor,
    type AutoTableSize,
    type ColumnPosition,
} from "./AutoTable.tsx";

const PT_ROW_HOVER_CLS: Record<AutoTableHeaderColor, string> = {
    [AUTOTABLE_HEADER_COLOR_DEFAULT]:   "[&_tr:hover]:!bg-surface-strong",
    [AUTOTABLE_HEADER_COLOR_BLUE]:      "[&_tr:hover]:!bg-sky-100 dark:bg-sky-950/50",
    [AUTOTABLE_HEADER_COLOR_GREEN]:     "[&_tr:hover]:!bg-green-100 dark:bg-green-950/50",
    [AUTOTABLE_HEADER_COLOR_GRAY]:      "[&_tr:hover]:!bg-surface-strong",
    [AUTOTABLE_HEADER_COLOR_DARK_BLUE]: "[&_tr:hover]:!bg-sky-100 dark:bg-sky-950/50",
};

export interface PrettyTableColumn {
    displayName: string;
    displayPosition?: ColumnPosition;
    headerClasses?: string;
}

export interface PrettyTableOptions {
    size?: AutoTableSize;
    shadow?: boolean;
    hover?: boolean;
    alternate?: boolean;
    headerBorderY?: boolean;
    surroundingBorder?: boolean;
    borderX?: boolean;
    borderY?: boolean;
    color?: AutoTableHeaderColor;
    tableLayoutAuto?: boolean;
}

export interface PrettyTableProps {
    columns: PrettyTableColumn[];
    // Body rows: <tr>s built with AutoTable's TdLeft/TdRight/TdCenter cells.
    children?: any;
    options?: PrettyTableOptions;
}

export function PrettyTable(props: PrettyTableProps) {
    const opts = createMemo(() => ({
        size: AUTOTABLE_SIZE_DEFAULT,
        shadow: false,
        hover: false,
        alternate: false,
        headerBorderY: false,
        surroundingBorder: false,
        borderX: false,
        borderY: false,
        color: AUTOTABLE_HEADER_COLOR_DEFAULT,
        tableLayoutAuto: false,
        ...props.options,
    }));

    const bodyClass = () => {
        let c = BODY_PADDING_CLS[opts().size];
        if (opts().borderY) c += " [&_td+td]:border-l [&_td+td]:border-line-strong";
        if (opts().alternate) c += " [&_tr:nth-child(even)]:bg-surface-raised";
        if (opts().borderX) c += " [&_tr:not(:last-child)]:border-b [&_tr:not(:last-child)]:border-line-strong";
        if (opts().hover) c += " " + PT_ROW_HOVER_CLS[opts().color];
        return c;
    };

    return (
        <div class={TBL_CONTAINER
            + (opts().surroundingBorder ? " border border-line-strong" : "")
            + (opts().shadow ? " shadow-sm" : "")}>
            <div class={TBL_WRAPPER}>
                <table class={TBL_BASE + (opts().tableLayoutAuto ? "" : " table-fixed")}>
                    <thead class="[&_th]:border-b [&_th]:border-line-strong">
                        <tr>
                            <For each={props.columns}>
                                {(col: PrettyTableColumn, displayIdx: () => number) => {
                                    const pos = col.displayPosition ?? COL_POS_LEFT;
                                    const posCls = POS_CLS[pos];
                                    const headerInnerPosCls = HEADER_INNER_POS[pos];
                                    return (
                                        <th
                                            class={HEADER_PADDING_CLS[opts().size] + " " + HEADER_COLOR_CLS[opts().color]
                                                + (posCls ? " " + posCls : "")
                                                + (opts().headerBorderY && displayIdx() > 0 ? " border-l border-l-neutral-300" : "")
                                                + (col.headerClasses ? " " + col.headerClasses : "")}
                                        >
                                            <div class={HEADER_CONTENT}>
                                                <div class={HEADER_INNER_BASE + (headerInnerPosCls ? " " + headerInnerPosCls : "")}>
                                                    <div class={"grow text-sm " + HEADER_TEXT_CLS[opts().color]}>
                                                        {col.displayName}
                                                    </div>
                                                </div>
                                            </div>
                                        </th>
                                    );
                                }}
                            </For>
                        </tr>
                    </thead>
                    <tbody class={bodyClass()}>
                        {props.children}
                    </tbody>
                </table>
            </div>
        </div>
    );
}

export default PrettyTable;
