import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"

import { cn } from "@/lib/utils"

type RadioCardType =
  | "with-icon"
  | "icon-radio-right"
  | "payment"
  | "with-avatar"
  | "company-icon"
  | "icon-radio-left"
  | "radio-label"

type RadioCardState = "default" | "active" | "disabled"
type RadioCardDirection = "ltr" | "rtl"

const radioCardVariants = cva(
  [
    "group/radio-card relative inline-block w-[var(--bh-radio-card-width)] max-w-full shrink-0",
    "rounded-[var(--bh-radius-xl-10)] p-[var(--bh-space-3xl-16)]",
    "bg-[var(--bh-radio-card-bg)] text-start shadow-[var(--shadow-radio-card-current)] outline-none",
    "transition-[background-color,box-shadow]",
    "[--bh-radio-card-bg:var(--bh-bg-raised)]",
    "[--bh-radio-card-border:var(--bh-border-default)]",
    "[--shadow-radio-card-current:var(--shadow-radio-card)]",
    "has-[:focus-visible]:[--bh-radio-card-border:var(--bh-border-brand-strong)]",
    "has-[:disabled]:pointer-events-none",
    "has-[:disabled]:[--bh-radio-card-border:var(--bh-border-disabled)]",
    "has-[:disabled]:[--shadow-radio-card-current:var(--shadow-radio-card-disabled)]",
    "has-[:disabled]:[--bh-radio-card-bg:var(--bh-bg-raised)]",
  ],
  {
    variants: {
      state: {
        default:
          "hover:[--bh-radio-card-bg:var(--bh-bg-raised-hover)]",
        active:
          "[--bh-radio-card-border:var(--bh-border-brand-strong)] [--bh-radio-card-border-width:var(--bh-radio-card-border-width-active)]",
        disabled:
          "pointer-events-none [--bh-radio-card-bg:var(--bh-bg-raised)] [--bh-radio-card-border:var(--bh-border-disabled)] [--shadow-radio-card-current:var(--shadow-radio-card-disabled)]",
      },
    },
    defaultVariants: {
      state: "default",
    },
  }
)

type RadioCardProps = Omit<
  React.ComponentProps<"label">,
  "children" | "label"
> &
  VariantProps<typeof radioCardVariants> & {
    type?: RadioCardType
    direction?: RadioCardDirection
    checked?: boolean
    disabled?: boolean
    label?: React.ReactNode
    description?: React.ReactNode
    supportLabel?: React.ReactNode
    supportDescription?: React.ReactNode
    showDescription?: boolean
    showSupportItems?: boolean
    showSupportDescription?: boolean
    icon?: React.ReactNode
    media?: React.ReactNode
    inputProps?: Omit<React.ComponentProps<"input">, "type">
  }

function RadioCard({
  className,
  type = "with-icon",
  state = "default",
  direction = "ltr",
  checked,
  disabled,
  label,
  description,
  supportLabel,
  supportDescription,
  showDescription = true,
  showSupportItems = true,
  showSupportDescription = true,
  icon,
  media,
  inputProps,
  ...props
}: RadioCardProps) {
  const inputChecked =
    checked ?? inputProps?.checked ?? Boolean(inputProps?.defaultChecked)
  const isDisabled = disabled ?? inputProps?.disabled ?? state === "disabled"
  const visualState: RadioCardState = isDisabled
    ? "disabled"
    : inputChecked || state === "active"
      ? "active"
      : state ?? "default"
  const isRtl = direction === "rtl"
  const textLabel = label
  const textDescription = description

  return (
    <label
      data-slot="radio-card"
      data-state={visualState}
      data-type={type}
      data-direction={direction}
      {...props}
      dir="ltr"
      className={cn(radioCardVariants({ state: visualState }), className)}
    >
      <input
        aria-label={typeof textLabel === "string" ? textLabel : undefined}
        {...inputProps}
        checked={inputProps?.checked ?? checked}
        className={cn("sr-only", inputProps?.className)}
        disabled={isDisabled}
        type="radio"
      />
      <span
        data-slot="radio-card-layout"
        className={cn(
          "flex min-w-0 items-start [direction:ltr]",
          type === "radio-label" && "items-center",
          getCardGapClass(type, isRtl)
        )}
      >
        {renderRadioCardContent({
          type,
          direction,
          state: visualState,
          label: textLabel,
          description: textDescription,
          supportLabel,
          supportDescription,
          showDescription,
          showSupportItems,
          showSupportDescription,
          icon,
          media,
        })}
      </span>
    </label>
  )
}

function renderRadioCardContent({
  type,
  direction,
  state,
  label,
  description,
  supportLabel,
  supportDescription,
  showDescription,
  showSupportItems,
  showSupportDescription,
  icon,
  media,
}: {
  type: RadioCardType
  direction: RadioCardDirection
  state: RadioCardState
  label?: React.ReactNode
  description?: React.ReactNode
  supportLabel?: React.ReactNode
  supportDescription?: React.ReactNode
  showDescription: boolean
  showSupportItems: boolean
  showSupportDescription: boolean
  icon?: React.ReactNode
  media?: React.ReactNode
}) {
  const isRtl = direction === "rtl"
  const checked = state === "active"
  const disabled = state === "disabled"
  const radio = <RadioCardIndicator checked={checked} disabled={disabled} />

  if (type === "radio-label") {
    return isRtl ? (
      <>
        <RadioCardLabelText label={label} rtl={isRtl} disabled={disabled} />
        {radio}
      </>
    ) : (
      <>
        {radio}
        <RadioCardLabelText label={label} rtl={isRtl} disabled={disabled} />
      </>
    )
  }

  if (type === "icon-radio-right") {
    const text = (
      <RadioCardText
        description={description}
        disabled={disabled}
        gap="xxs"
        label={label}
        rtl={isRtl}
        showDescription={showDescription}
      />
    )

    return isRtl ? (
      <>
        {radio}
        {text}
      </>
    ) : (
      <>
        {text}
        {radio}
      </>
    )
  }

  if (type === "icon-radio-left") {
    const text = (
      <RadioCardText
        description={description}
        disabled={disabled}
        gap="xxs"
        label={label}
        rtl={isRtl}
        showDescription={showDescription}
      />
    )

    if (isRtl) {
      return (
        <>
          {text}
          {radio}
        </>
      )
    }

    return (
      <>
        {radio}
        {text}
        {showSupportItems &&
        (hasRenderableContent(supportLabel) ||
          hasRenderableContent(supportDescription)) ? (
          <RadioCardSupportText
            disabled={disabled}
            label={supportLabel}
            description={supportDescription}
            showDescription={showSupportDescription}
          />
        ) : null}
      </>
    )
  }

  const content = (
    <RadioCardMediaContent
      type={type}
      direction={direction}
      state={state}
      icon={icon}
      media={media}
      label={label}
      description={description}
      showDescription={showDescription}
    />
  )

  return isRtl ? (
    <>
      {radio}
      {content}
    </>
  ) : (
    <>
      {content}
      {radio}
    </>
  )
}

function RadioCardMediaContent({
  type,
  direction,
  state,
  icon,
  media,
  label,
  description,
  showDescription,
}: {
  type: RadioCardType
  direction: RadioCardDirection
  state: RadioCardState
  icon?: React.ReactNode
  media?: React.ReactNode
  label?: React.ReactNode
  description?: React.ReactNode
  showDescription: boolean
}) {
  const isRtl = direction === "rtl"
  const disabled = state === "disabled"
  const text = (
    <RadioCardText
      description={description}
      disabled={disabled}
      gap={getTextGap(type, state, isRtl)}
      label={label}
      rtl={isRtl}
      showDescription={showDescription}
    />
  )
  const visual = (
    <RadioCardMedia type={type} disabled={disabled} icon={icon} media={media} />
  )

  return (
    <span
      data-slot="radio-card-content"
      className={cn(
        "flex min-w-0 flex-1 items-start gap-[var(--bh-space-lg-10)]",
        isRtl && "justify-end",
        (type === "with-avatar" || type === "company-icon") &&
          "group-hover/radio-card:items-center",
        (type === "with-avatar" || type === "company-icon") &&
          state !== "default" &&
          "items-center",
        type === "with-avatar" &&
          isRtl &&
          state === "active" &&
          "gap-[var(--bh-space-xl-12)]"
      )}
    >
      {isRtl ? (
        <>
          {text}
          {visual}
        </>
      ) : (
        <>
          {visual}
          {text}
        </>
      )}
    </span>
  )
}

function RadioCardText({
  label,
  description,
  showDescription,
  rtl,
  disabled,
  gap,
}: {
  label?: React.ReactNode
  description?: React.ReactNode
  showDescription: boolean
  rtl: boolean
  disabled: boolean
  gap: "xxs" | "xs"
}) {
  if (!hasRenderableContent(label)) return null

  return (
    <span
      data-slot="radio-card-text"
      className={cn(
        "flex min-w-0 flex-1 flex-col",
        gap === "xxs"
          ? "gap-[var(--bh-space-xxs-2)]"
          : "gap-[var(--bh-space-xs-4)]",
        rtl ? "items-end text-right" : "items-start text-left"
      )}
    >
      {hasRenderableContent(label) ? (
        <span
          data-slot="radio-card-label"
          dir={rtl ? "rtl" : "auto"}
          className={cn(radioCardLabelClass, disabled && radioCardDisabledClass)}
        >
          {label}
        </span>
      ) : null}
      {showDescription && hasRenderableContent(description) ? (
        <span
          data-slot="radio-card-description"
          dir={rtl ? "rtl" : "auto"}
          className={cn(
            radioCardDescriptionClass,
            disabled && radioCardDisabledClass
          )}
        >
          {description}
        </span>
      ) : null}
    </span>
  )
}

function hasRenderableContent(content: React.ReactNode) {
  return (
    content !== undefined &&
    content !== null &&
    content !== false &&
    content !== ""
  )
}

function RadioCardSupportText({
  label,
  description,
  showDescription,
  disabled,
}: {
  label?: React.ReactNode
  description?: React.ReactNode
  showDescription: boolean
  disabled: boolean
}) {
  return (
    <span
      data-slot="radio-card-support"
      className="flex shrink-0 flex-col items-end gap-[var(--bh-space-xxs-2)] whitespace-nowrap text-right"
    >
      {hasRenderableContent(label) ? (
        <span
          data-slot="radio-card-support-label"
          className={cn(radioCardLabelClass, disabled && radioCardDisabledClass)}
        >
          {label}
        </span>
      ) : null}
      {showDescription && hasRenderableContent(description) ? (
        <span
          data-slot="radio-card-support-description"
          className={cn(
            radioCardDescriptionClass,
            disabled && radioCardDisabledClass
          )}
        >
          {description}
        </span>
      ) : null}
    </span>
  )
}

function RadioCardLabelText({
  label,
  rtl,
  disabled,
}: {
  label?: React.ReactNode
  rtl: boolean
  disabled: boolean
}) {
  return (
    <span
      data-slot="radio-card-label"
      dir={rtl ? "rtl" : "auto"}
      className={cn(
        radioCardLabelClass,
        "min-w-0 flex-1",
        rtl ? "text-right" : "text-left",
        disabled && radioCardDisabledClass
      )}
    >
      {label}
    </span>
  )
}

function RadioCardIndicator({
  checked,
  disabled,
}: {
  checked: boolean
  disabled: boolean
}) {
  return (
    <span
      aria-hidden="true"
      data-slot="radio-card-indicator"
      className="flex size-[var(--bh-space-4xl-20)] shrink-0 items-center justify-center"
    >
      <span
        className={cn(
          "flex size-[var(--bh-space-3xl-16)] items-center justify-center rounded-[var(--bh-radius-full)] [--shadow-radio-control:inset_0px_0px_0px_var(--bh-border-width-default)_var(--bh-radio-control-border,var(--bh-border-input)),var(--shadow-component-default)]",
          checked
            ? "bg-[var(--bh-interactive-radiobutton-default)] shadow-[var(--shadow-radio-control)] [--bh-radio-control-border:transparent]"
            : disabled
              ? "bg-[var(--bh-bg-raised)] shadow-[inset_0px_0px_0px_var(--bh-border-width-default)_var(--bh-border-disabled)]"
              : "bg-[var(--bh-bg-raised)] shadow-[var(--shadow-radio-control)] [--bh-radio-control-border:var(--bh-border-input)]"
        )}
      >
        {checked ? (
          <span className="size-[var(--bh-space-sm-6)] rounded-[var(--bh-radius-full)] bg-[var(--bh-bg-always-white)]" />
        ) : null}
      </span>
    </span>
  )
}

function RadioCardMedia({
  type,
  disabled,
  icon,
  media,
}: {
  type: RadioCardType
  disabled: boolean
  icon?: React.ReactNode
  media?: React.ReactNode
}) {
  if (media) {
    return (
      <span
        data-slot="radio-card-media"
        className={cn(
          "shrink-0",
          (type === "with-avatar" || type === "company-icon") &&
            disabled &&
            "opacity-[var(--bh-opacity-disabled-media)]"
        )}
      >
        {media}
      </span>
    )
  }

  if (type === "payment") return <RadioCardPaymentIcon />
  if (type === "with-avatar") return <RadioCardAvatarPlaceholder disabled={disabled} />
  if (type === "company-icon") return <RadioCardCompanyIcon disabled={disabled} />

  return (
    <span
      data-slot="radio-card-icon"
      className={cn(
        "flex size-[var(--bh-space-4xl-20)] shrink-0 items-center justify-center text-[var(--bh-content-subtle)]",
        disabled && "text-[var(--bh-content-disabled)]"
      )}
    >
      {icon ?? <RadioCardUserIcon />}
    </span>
  )
}

function RadioCardUserIcon() {
  return (
    <svg
      aria-hidden="true"
      className="size-[var(--bh-space-4xl-20)]"
      fill="none"
      viewBox="0 0 20 20"
    >
      <path
        d="M3.333 18.333c0-3.681 2.985-6.666 6.667-6.666s6.667 2.985 6.667 6.666H15c0-2.761-2.239-5-5-5s-5 2.239-5 5H3.333ZM10 10.833a5 5 0 1 1 0-10 5 5 0 0 1 0 10Zm0-1.666a3.333 3.333 0 1 0 0-6.667 3.333 3.333 0 0 0 0 6.667Z"
        fill="currentColor"
      />
    </svg>
  )
}

function RadioCardPaymentIcon() {
  return (
    <span
      data-slot="radio-card-payment-icon"
      className="flex h-[var(--bh-radio-card-payment-height)] w-[var(--bh-radio-card-payment-width)] shrink-0 items-center justify-center rounded-[var(--bh-radius-md-6)] bg-[var(--bh-bg-always-white)] shadow-[inset_0_0_0_var(--bh-border-width-default)_var(--bh-border-subtle)]"
    >
      <svg
        aria-hidden="true"
        className="h-[var(--bh-radio-card-payment-logo-height)] w-[var(--bh-radio-card-payment-logo-width)]"
        fill="none"
        viewBox="0 0 33 11"
      >
        <path
          clipRule="evenodd"
          d="M8.05 10.344H5.263L3.174 2.256c-.1-.372-.31-.7-.62-.856C1.78 1.011.852.701 0 .544V.233h4.489c.62 0 1.084.468 1.162 1.011l1.084 5.834L9.52.233h2.71L8.05 10.344Zm5.728 0h-2.632L13.313.233h2.632l-2.167 10.111Zm5.572-7.31c.078-.544.542-.855 1.085-.855.852-.078 1.78.078 2.554.467l.465-2.177A7.09 7.09 0 0 0 21.055 0c-2.554 0-4.413 1.401-4.413 3.344 0 1.479 1.317 2.255 2.246 2.723 1.006.467 1.393.778 1.315 1.244 0 .7-.774 1.011-1.547 1.011-.93 0-1.86-.233-2.71-.622l-.465 2.178c.93.388 1.935.545 2.864.545 2.864.076 4.644-1.323 4.644-3.423 0-2.645-3.639-2.8-3.639-3.966Zm12.85 7.31L30.11.233h-2.245c-.464 0-.929.311-1.084.778l-3.87 9.333h2.71l.541-1.477h3.329l.31 1.477H32.2ZM28.253 2.956l.773 3.811H26.86l1.394-3.811Z"
          fill="var(--bh-radio-card-payment-logo-color)"
          fillRule="evenodd"
        />
      </svg>
    </span>
  )
}

function RadioCardAvatarPlaceholder({ disabled }: { disabled: boolean }) {
  return (
    <span
      data-slot="radio-card-avatar"
      className={cn(
        "flex size-[var(--bh-space-7xl-40)] shrink-0 items-center justify-center overflow-hidden rounded-[var(--bh-radius-full)] bg-[var(--bh-bg-neutral-subtle)] shadow-[inset_0_0_0_var(--bh-border-width-default)_var(--bh-border-subtle)]",
        disabled && "opacity-[var(--bh-opacity-disabled-media)]"
      )}
    >
      <span className="size-full bg-[linear-gradient(135deg,var(--bh-bg-accent-blue-soft),var(--bh-bg-accent-purple-soft))]" />
    </span>
  )
}

function RadioCardCompanyIcon({ disabled }: { disabled: boolean }) {
  return (
    <span
      data-slot="radio-card-company-icon"
      className={cn(
        "flex size-[var(--bh-space-7xl-40)] shrink-0 items-center justify-center overflow-hidden",
        disabled && "opacity-[var(--bh-opacity-disabled-media)]"
      )}
    >
      <svg aria-hidden="true" className="size-full" fill="none" viewBox="0 0 40 40">
        <path
          clipRule="evenodd"
          d="M20.5 37.5c9.941 0 18-8.059 18-18s-8.059-18-18-18-18 8.059-18 18 8.059 18 18 18Zm2.778-22.093a3.929 3.929 0 0 0 0-5.556 3.929 3.929 0 0 0-5.556 0 3.929 3.929 0 0 0 0 5.556l2.778 2.778 2.778-2.778Zm1.315 6.871a3.929 3.929 0 0 0 5.556 0 3.929 3.929 0 0 0 0-5.556 3.929 3.929 0 0 0-5.556 0L21.815 19.5l2.778 2.778Zm-1.315 6.871a3.929 3.929 0 0 0 0-5.556L20.5 20.815l-2.778 2.778a3.929 3.929 0 0 0 0 5.556 3.929 3.929 0 0 0 5.556 0Zm-12.427-6.871a3.929 3.929 0 0 1 0-5.556 3.929 3.929 0 0 1 5.556 0L19.185 19.5l-2.778 2.778a3.929 3.929 0 0 1-5.556 0Z"
          fill="var(--bh-radio-card-company-mark-color)"
          fillRule="evenodd"
        />
      </svg>
    </span>
  )
}

function getCardGapClass(type: RadioCardType, rtl: boolean) {
  if (rtl && (type === "company-icon" || type === "icon-radio-left")) {
    return "gap-[var(--bh-space-xl-12)]"
  }

  return "gap-[var(--bh-space-lg-10)]"
}

function getTextGap(type: RadioCardType, state: RadioCardState, rtl: boolean) {
  if (type === "with-icon" && state === "default" && !rtl) return "xxs"
  if (type === "icon-radio-right" || type === "icon-radio-left") return "xxs"
  return "xs"
}

const radioCardLabelClass =
  "block min-w-0 break-words text-[length:var(--bh-text-body-md-medium-font-size)] font-[var(--bh-text-body-md-medium-font-weight)] leading-[var(--bh-text-body-md-medium-line-height)] tracking-[var(--bh-text-body-md-medium-letter-spacing)] text-[var(--bh-content-default)]"

const radioCardDescriptionClass =
  "block min-w-0 break-words text-[length:var(--bh-text-body-sm-regular-font-size)] font-[var(--bh-text-body-sm-regular-font-weight)] leading-[var(--bh-text-body-sm-regular-line-height)] tracking-[var(--bh-text-body-sm-regular-letter-spacing)] text-[var(--bh-content-subtle)]"

const radioCardDisabledClass = "text-[var(--bh-content-disabled)]"

export {
  RadioCard,
  radioCardVariants,
  type RadioCardDirection,
  type RadioCardProps,
  type RadioCardState,
  type RadioCardType,
}
