import type { Middleware, Placement } from "@floating-ui/dom";
import { flip, offset, shift } from "@floating-ui/dom";
import type { Accessor, JSX } from "solid-js";
import { createSignal, createUniqueId } from "solid-js";
import { createControllableSignal } from "../../primitives/create-controllable-signal";
import { createDisclosureState, type CreateDisclosureStateOptions } from "../../primitives/create-disclosure-state";
import { createFloating } from "../../primitives/create-floating";
import { DatePickerContextProvider } from "./date-picker-context";
import type { DatePickerRootProps } from "./date-picker.props";

/** Formats an ISO date string using Intl.DateTimeFormat for the given locale. */
function formatDate(iso: string, locale: string): string {
  const [y, m, d] = iso.split("-").map(Number);
  return new Intl.DateTimeFormat(locale, { year: "numeric", month: "long", day: "numeric" }).format(
    new Date(y, m - 1, d),
  );
}

/** Root component for DatePicker. Manages open state, date value, floating position, and provides context. */
export function DatePickerRoot(props: DatePickerRootProps): JSX.Element {
  const disclosure = createDisclosureState({
    get open() { return props.open; },
    get defaultOpen() { return props.defaultOpen; },
    get onOpenChange() { return props.onOpenChange; },
  } as CreateDisclosureStateOptions);

  const [value, setValue] = createControllableSignal<string | undefined>({
    value: () => props.value,
    defaultValue: () => props.defaultValue,
    onChange: props.onValueChange,
  });

  const contentId = createUniqueId();
  const [triggerRef, setTriggerRef] = createSignal<HTMLElement | null>(null);
  const [contentRef, setContentRef] = createSignal<HTMLElement | null>(null);

  const floating = createFloating({
    anchor: triggerRef,
    floating: contentRef,
    placement: (() => "bottom-start") as Accessor<Placement>,
    middleware: (() => [offset(8), flip(), shift({ padding: 8 })]) as Accessor<Middleware[]>,
    open: disclosure.isOpen,
  });

  const handleSelect = (iso: string) => {
    setValue(iso);
    disclosure.close();
  };

  const ctx = {
    isOpen: disclosure.isOpen,
    setOpen: (open: boolean) => (open ? disclosure.open() : disclosure.close()),
    toggle: disclosure.toggle,
    value,
    setValue: handleSelect,
    formatDate: (iso: string) => formatDate(iso, props.locale ?? "en-US"),
    placeholder: () => props.placeholder ?? "Select date",
    disabled: () => props.disabled ?? false,
    name: () => props.name,
    minDate: () => props.minDate,
    maxDate: () => props.maxDate,
    locale: () => props.locale ?? "en-US",
    contentId: () => contentId,
    triggerRef,
    setTriggerRef,
    contentRef,
    setContentRef,
    floatingStyle: floating.style,
  };

  return (
    <DatePickerContextProvider value={ctx}>
      {props.children}
    </DatePickerContextProvider>
  );
}
