import {
    AnchorHTMLAttributes,
    ButtonHTMLAttributes,
    ComponentProps,
    DetailedHTMLProps,
    HTMLAttributeAnchorTarget,
    HTMLAttributes,
} from "react";
import { twMerge } from "tailwind-merge";
import Loading from "../elements/Loading";

export type TWUIButtonProps = DetailedHTMLProps<
    ButtonHTMLAttributes<HTMLButtonElement>,
    HTMLButtonElement
> & {
    title: string;
    variant?: "normal" | "ghost" | "outlined";
    color?:
        | "primary"
        | "secondary"
        | "text"
        | "white"
        | "accent"
        | "gray"
        | "error"
        | "warning"
        | "success";
    size?: "small" | "smaller" | "normal" | "large" | "larger";
    loadingIconSize?: React.ComponentProps<typeof Loading>["size"];
    href?: string;
    target?: HTMLAttributeAnchorTarget;
    loading?: boolean;
    linkProps?: DetailedHTMLProps<
        AnchorHTMLAttributes<HTMLAnchorElement>,
        HTMLAnchorElement
    >;
    beforeIcon?: React.ReactNode;
    afterIcon?: React.ReactNode;
    buttonContentProps?: DetailedHTMLProps<
        HTMLAttributes<HTMLDivElement>,
        HTMLDivElement
    >;
    loadingProps?: ComponentProps<typeof Loading>;
};

/**
 * # Buttons
 * @className twui-button-general
 * @className twui-button-content-wrapper
 * @className twui-button-primary
 * @className twui-button-primary-outlined
 * @className twui-button-primary-ghost
 * @className twui-button-secondary
 * @className twui-button-secondary-outlined
 * @className twui-button-secondary-ghost
 * @className twui-button-white
 * @className twui-button-white-outlined
 * @className twui-button-white-ghost
 * @className twui-button-accent
 * @className twui-button-accent-outlined
 * @className twui-button-accent-ghost
 * @className twui-button-gray
 * @className twui-button-gray-outlined
 * @className twui-button-gray-ghost
 *
 * @example
```css
CSS directive:

//@theme inline {
    --breakpoint-xs: 350px;
    --color-primary: #000000;
    --color-primary-hover: #29292b;
    --color-primary-outline: #29292b;
    --color-primary-text: #29292b;
    --color-primary-dark: #29292b;
    --color-primary-dark-hover: #4b4b4b;
    --color-primary-dark-outline: #4b4b4b;
    --color-primary-dark-text: #4b4b4b;
    --color-secondary: #000000;
    --color-secondary-hover: #dddddd;
    --color-secondary-outline: #dddddd;
    --color-secondary-text: #dddddd;
    --color-secondary-dark: #000000;
    --color-secondary-dark-hover: #dddddd;
    --color-secondary-dark-outline: #dddddd;
    --color-secondary-dark-text: #dddddd;
    --color-accent: #000000;
    --color-accent-hover: #dddddd;
    --color-accent-outline: #dddddd;
    --color-accent-text: #dddddd;
    --color-accent-dark: #000000;
    --color-accent-dark-hover: #dddddd;
    --color-accent-dark-outline: #dddddd;
    --color-accent-dark-text: #dddddd;
}
```
 */
export default function Button({
    href,
    target,
    variant,
    color,
    size,
    buttonContentProps,
    linkProps,
    beforeIcon,
    afterIcon,
    loading,
    loadingIconSize,
    loadingProps,
    ...props
}: TWUIButtonProps) {
    const finalClassName: string = (() => {
        if (variant == "normal" || !variant) {
            if (color == "primary" || !color)
                return twMerge(
                    "bg-primary hover:bg-primary-hover text-white",
                    "dark:bg-primary-dark hover:dark:bg-primary-dark-hover text-white",
                    "twui-button-primary"
                );
            if (color == "secondary")
                return twMerge(
                    "bg-secondary hover:bg-secondary-hover text-white",
                    "twui-button-secondary"
                );
            if (color == "white")
                return twMerge(
                    "!bg-white hover:!bg-slate-200 !text-slate-800",
                    "twui-button-white"
                );
            if (color == "accent")
                return twMerge(
                    "bg-accent hover:bg-accent-hover text-white",
                    "twui-button-accent"
                );
            if (color == "gray")
                return twMerge(
                    "bg-gray hover:bg-gray-hover text-foreground-light",
                    "dark:bg-gray-dark hover:dark:bg-gray-dark-hover dark:text-foreground-dark",
                    "twui-button-gray"
                );
            if (color == "success")
                return twMerge(
                    "bg-success hover:bg-success-hover text-white",
                    "dark:bg-success hover:dark:bg-success-hover text-white",
                    "twui-button-success"
                );
            if (color == "error")
                return twMerge(
                    "bg-error hover:bg-error-hover text-white",
                    "dark:bg-error hover:dark:bg-error-hover text-white",
                    "twui-button-error"
                );
        } else if (variant == "outlined") {
            if (color == "primary" || !color)
                return twMerge(
                    "bg-transparent outline outline-1 outline-primary",
                    "text-primary-text dark:text-primary-dark-text dark:outline-primary-dark-outline",
                    "twui-button-primary-outlined"
                );
            if (color == "secondary")
                return twMerge(
                    "bg-transparent outline outline-1 outline-secondary",
                    "text-secondary",
                    "twui-button-secondary-outlined"
                );
            if (color == "accent")
                return twMerge(
                    "bg-transparent outline outline-1 outline-accent",
                    "text-accent",
                    "twui-button-accent-outlined"
                );
            if (color == "gray")
                return twMerge(
                    "bg-transparent outline outline-1 outline-slate-300",
                    "text-slate-600 dark:text-white/60 dark:outline-white/30",
                    "twui-button-gray-outlined"
                );
            if (color == "white")
                return twMerge(
                    "bg-transparent outline outline-1 outline-white/50",
                    "text-white",
                    "twui-button-white-outlined"
                );
            if (color == "error")
                return twMerge(
                    "bg-transparent outline outline-1 outline-error text-error",
                    "dark:outline-error dark:text-error-dark",
                    "twui-button-error-outlined"
                );
        } else if (variant == "ghost") {
            if (color == "primary" || !color)
                return twMerge(
                    "bg-transparent dark:bg-transparent outline-none p-2",
                    "text-primary-text dark:text-primary-dark-text hover:bg-transparent dark:hover:bg-transparent",
                    "twui-button-primary-ghost"
                );
            if (color == "secondary")
                return twMerge(
                    "bg-transparent dark:bg-transparent outline-none p-2",
                    "text-secondary hover:bg-transparent dark:hover:bg-transparent",
                    "twui-button-secondary-ghost"
                );
            if (color == "text")
                return twMerge(
                    "bg-transparent dark:bg-transparent outline-none p-2 dark:text-foreground-dark",
                    "text-foreground-light hover:bg-transparent dark:hover:bg-transparent",
                    "twui-button-secondary-ghost"
                );
            if (color == "accent")
                return twMerge(
                    "bg-transparent dark:bg-transparent outline-none p-2",
                    "text-accent hover:bg-transparent dark:hover:bg-transparent",
                    "twui-button-accent-ghost"
                );
            if (color == "gray")
                return twMerge(
                    "bg-transparent dark:bg-transparent outline-none p-2 hover:bg-transparent dark:hover:bg-transparent",
                    "text-slate-600 dark:text-white/70 hover:opacity-80",
                    "twui-button-gray-ghost"
                );
            if (color == "error")
                return twMerge(
                    "bg-transparent outline-none p-2",
                    "text-red-600 dark:text-red-400",
                    "twui-button-error-ghost"
                );
            if (color == "warning")
                return twMerge(
                    "bg-transparent outline-none p-2",
                    "text-yellow-600",
                    "twui-button-warning-ghost"
                );
            if (color == "success")
                return twMerge(
                    "bg-transparent outline-none p-2",
                    "text-success",
                    "twui-button-success-ghost"
                );
            if (color == "white")
                return twMerge(
                    "bg-transparent outline-none p-2",
                    "text-white",
                    "twui-button-white-ghost"
                );
        }

        return "";
    })();

    const buttonComponent = (
        <button
            {...props}
            className={twMerge(
                "bg-primary text-white font-medium px-4 py-2 rounded-default",
                "flex items-center justify-center relative transition-all cursor-pointer",
                props.disabled ? "opacity-40 cursor-not-allowed" : "",
                "twui-button-general",
                size == "small"
                    ? "px-3 py-1.5 twui-button-small text-sm"
                    : size == "smaller"
                    ? "px-2 py-1 text-xs twui-button-smaller"
                    : size == "large"
                    ? "text-lg twui-button-large"
                    : size == "larger"
                    ? "px-5 py-3 text-xl twui-button-larger"
                    : "twui-button-base",
                finalClassName,
                loading ? "pointer-events-none opacity-80" : "",
                props.className
            )}
            aria-label={props.title}
        >
            <div
                {...buttonContentProps}
                className={twMerge(
                    "flex flex-row items-center gap-2 whitespace-nowrap",
                    loading ? "opacity-0" : "",
                    "twui-button-content-wrapper",
                    buttonContentProps?.className
                )}
            >
                {beforeIcon && beforeIcon}
                {props.children}
                {afterIcon && afterIcon}
            </div>

            {loading && (
                <Loading
                    size={(() => {
                        if (loadingIconSize) return loadingIconSize;
                        switch (size) {
                            case "small":
                                return "small";
                            case "smaller":
                                return "smaller";

                            default:
                                return "normal";
                        }
                    })()}
                    {...loadingProps}
                    className={twMerge("absolute", loadingProps?.className)}
                />
            )}
        </button>
    );

    if (href)
        return (
            <a
                {...linkProps}
                href={href}
                target={target}
                title={props.title}
                aria-label={props.title}
            >
                {buttonComponent}
            </a>
        );
    return buttonComponent;
}
