import { Duration } from "@gnu-taler/taler-util";
import { Fragment, VNode, h } from "preact";
import { useEffect, useRef } from "preact/hooks";
import { useTranslationContext } from "../../index.browser.js";
import { UIFormProps } from "../FormProvider.js";
import { noHandlerPropsAndNoContextForField } from "./InputArray.js";
import { InputWrapper } from "./InputLine.js";

export function InputDuration(props: UIFormProps<Duration>): VNode {
  const { name, placeholder, before, after, converter, disabled } = props;
  const { i18n } = useTranslationContext();
  const { value, onChange, error } =
    props.handler ?? noHandlerPropsAndNoContextForField(props.name);

  const specDuration = !value ? undefined : Duration.toSpec(value as Duration);
  // const [seconds, setSeconds] = useState(sd?.seconds ?? 0);
  // const [hours, setHours] = useState(sd?.hours ?? 0);
  // const [minutes, setMinutes] = useState(sd?.minutes ?? 0);
  // const [days, setDays] = useState(sd?.days ?? 0);
  // const [months, setMonths] = useState(sd?.month ?? 0);
  // const [years, setYears] = useState(sd?.years ?? 0);

  const secondsRef = useRef<HTMLInputElement>(null);
  const hoursRef = useRef<HTMLInputElement>(null);
  const minutesRef = useRef<HTMLInputElement>(null);
  const daysRef = useRef<HTMLInputElement>(null);
  const monthsRef = useRef<HTMLInputElement>(null);
  const yearsRef = useRef<HTMLInputElement>(null);

  // useEffect(() => {
  //   onChange(
  //     Duration.fromSpec({
  //       days,
  //       hours,
  //       minutes,
  //       seconds,
  //       months,
  //       years,
  //     }),
  //   );
  // }, [days, hours, minutes, seconds, months, years]);
  const fromString: (s: string) => any =
    converter?.fromStringUI ?? defaultFromString;
  const toString: (s: any) => string = converter?.toStringUI ?? defaultToString;

  const strSeconds = toString(specDuration?.seconds ?? 0) ?? "";
  const strHours = toString(specDuration?.hours ?? 0) ?? "";
  const strMinutes = toString(specDuration?.minutes ?? 0) ?? "";
  const strDays = toString(specDuration?.days ?? 0) ?? "";
  const strMonths = toString(specDuration?.month ?? 0) ?? "";
  const strYears = toString(specDuration?.years ?? 0) ?? "";

  useEffect(() => {
    if (!secondsRef.current) return;
    if (secondsRef.current === document.activeElement) return;
    secondsRef.current.value = strSeconds;
  }, [strSeconds]);
  useEffect(() => {
    if (!minutesRef.current) return;
    if (minutesRef.current === document.activeElement) return;
    minutesRef.current.value = strMinutes;
  }, [strMinutes]);
  useEffect(() => {
    if (!hoursRef.current) return;
    if (hoursRef.current === document.activeElement) return;
    hoursRef.current.value = strHours;
  }, [strHours]);
  useEffect(() => {
    if (!daysRef.current) return;
    if (daysRef.current === document.activeElement) return;
    daysRef.current.value = strDays;
  }, [strDays]);
  useEffect(() => {
    if (!monthsRef.current) return;
    if (monthsRef.current === document.activeElement) return;
    monthsRef.current.value = strMonths;
  }, [strMonths]);
  useEffect(() => {
    if (!yearsRef.current) return;
    if (yearsRef.current === document.activeElement) return;
    yearsRef.current.value = strYears;
  }, [strYears]);

  if (props.hidden) {
    return <Fragment />;
  }

  let clazz =
    "block w-full rounded-md border-0 py-1.5 shadow-sm ring-1 ring-inset focus:ring-2 focus:ring-inset sm:text-sm sm:leading-6 disabled:cursor-not-allowed disabled:bg-gray-50 disabled:text-gray-500 disabled:ring-gray-200";
  // if (before) {
  //   switch (before.type) {
  //     case "icon": {
  //       clazz += " pl-10";
  //       break;
  //     }
  //     case "button": {
  //       clazz += " rounded-none rounded-r-md ";
  //       break;
  //     }
  //     case "text": {
  clazz += " min-w-0 flex-1 rounded-r-md rounded-none ";
  //       break;
  //     }
  //   }
  // }
  if (after) {
    switch (after.type) {
      case "icon": {
        clazz += " pr-10";
        break;
      }
      case "button": {
        clazz += " rounded-none rounded-l-md";
        break;
      }
      case "text": {
        clazz += " min-w-0 flex-1 rounded-l-md rounded-none ";
        break;
      }
    }
  }
  const showError = value !== undefined && error;
  if (showError) {
    clazz +=
      " text-red-900 ring-red-300  placeholder:text-red-300 focus:ring-red-500";
  } else {
    clazz +=
      " text-gray-900 ring-gray-300 placeholder:text-gray-400 focus:ring-indigo-600";
  }
  // FIXME: Fix the types!
  return (
    <InputWrapper
      {...props}
      converter={{
        //@ts-ignore
        fromStringUI(v) {
          return v ?? "";
        },
        //@ts-ignore
        toStringUI(v) {
          return v ?? "";
        },
      }}
      help={props.help}
      disabled={disabled ?? false}
      error={showError ? error : undefined}
    >
      <div class="flex flex-col gap-1">
        <div class="flex">
          <span class="ml-2 inline-flex items-center rounded-l-md border border-r-0 border-gray-300 px-3 text-gray-500 sm:text-sm">
            <i18n.Translate>years</i18n.Translate>
          </span>
          <input
            name={String(name)}
            type="number"
            onChange={(e) => {
              onChange(
                Duration.fromSpec({
                  ...specDuration,
                  years: fromString(e.currentTarget.value),
                }),
              );
            }}
            placeholder={placeholder ? placeholder : undefined}
            ref={yearsRef}
            // value={toString(sd?.years) ?? ""}
            // onBlur={() => {
            //   onChange(fromString(value as any));
            // }}
            // defaultValue={toString(value)}
            disabled={disabled ?? false}
            aria-invalid={showError}
            // aria-describedby="email-error"
            class={clazz}
          />
          <span class="ml-2 inline-flex items-center rounded-l-md border border-r-0 border-gray-300 px-3 text-gray-500 sm:text-sm">
            <i18n.Translate>months</i18n.Translate>
          </span>
          <input
            name={String(name)}
            type="number"
            ref={monthsRef}
            onChange={(e) => {
              onChange(
                Duration.fromSpec({
                  ...specDuration,
                  months: fromString(e.currentTarget.value),
                }),
              );
            }}
            placeholder={placeholder ? placeholder : undefined}
            // value={toString(specDuration?.month) ?? ""}
            // onBlur={() => {
            //   onChange(fromString(value as any));
            // }}
            // defaultValue={toString(value)}
            disabled={disabled ?? false}
            aria-invalid={showError}
            // aria-describedby="email-error"
            class={clazz}
          />
        </div>
        <div class="flex">
          <span class="ml-2 inline-flex items-center rounded-l-md border border-r-0 border-gray-300 px-3 text-gray-500 sm:text-sm">
            <i18n.Translate>days</i18n.Translate>
          </span>
          <input
            name={String(name)}
            type="number"
            ref={daysRef}
            onChange={(e) => {
              onChange(
                Duration.fromSpec({
                  ...specDuration,
                  days: fromString(e.currentTarget.value),
                }),
              );
            }}
            placeholder={placeholder ? placeholder : undefined}
            // value={toString(specDuration?.days) ?? ""}
            // onBlur={() => {
            //   onChange(fromString(value as any));
            // }}
            // defaultValue={toString(value)}
            disabled={disabled ?? false}
            aria-invalid={showError}
            // aria-describedby="email-error"
            class={clazz}
          />
          <span class="ml-2 inline-flex items-center rounded-l-md border border-r-0 border-gray-300 px-3 text-gray-500 sm:text-sm">
            <i18n.Translate>hours</i18n.Translate>
          </span>
          <input
            name={String(name)}
            type="number"
            ref={hoursRef}
            onChange={(e) => {
              onChange(
                Duration.fromSpec({
                  ...specDuration,
                  hours: fromString(e.currentTarget.value),
                }),
              );
            }}
            placeholder={placeholder ? placeholder : undefined}
            // value={toString(specDuration?.hours) ?? ""}
            // onBlur={() => {
            //   onChange(fromString(value as any));
            // }}
            // defaultValue={toString(value)}
            disabled={disabled ?? false}
            aria-invalid={showError}
            // aria-describedby="email-error"
            class={clazz}
          />
        </div>
        <div class="flex">
          <span class="ml-2 inline-flex items-center rounded-l-md border border-r-0 border-gray-300 px-3 text-gray-500 sm:text-sm">
            <i18n.Translate>minutes</i18n.Translate>
          </span>
          <input
            name={String(name)}
            type="number"
            ref={minutesRef}
            onChange={(e) => {
              onChange(
                Duration.fromSpec({
                  ...specDuration,
                  minutes: fromString(e.currentTarget.value),
                }),
              );
            }}
            placeholder={placeholder ? placeholder : undefined}
            // value={toString(specDuration?.minutes) ?? ""}
            // onBlur={() => {
            //   onChange(fromString(value as any));
            // }}
            // defaultValue={toString(value)}
            disabled={disabled ?? false}
            aria-invalid={showError}
            // aria-describedby="email-error"
            class={clazz}
          />
          <span class="ml-2 inline-flex items-center rounded-l-md border border-r-0 border-gray-300 px-3 text-gray-500 sm:text-sm">
            <i18n.Translate>seconds</i18n.Translate>
          </span>
          <input
            name={String(name)}
            type="number"
            ref={secondsRef}
            onChange={(e) => {
              // setSeconds(fromString(e.currentTarget.value));
              onChange(
                Duration.fromSpec({
                  ...specDuration,
                  seconds: fromString(e.currentTarget.value),
                }),
              );
            }}
            placeholder={placeholder ? placeholder : undefined}
            // value={toString(specDuration?.seconds) ?? ""}
            // onBlur={() => {
            //   onChange(fromString(value as any));
            // }}
            // defaultValue={toString(value)}
            disabled={disabled ?? false}
            aria-invalid={showError}
            // aria-describedby="email-error"
            class={clazz}
          />
        </div>
      </div>
    </InputWrapper>
  );
}

function defaultToString(v: unknown) {
  return v === undefined ? "" : typeof v !== "object" ? String(v) : "";
}

function defaultFromString(v: string) {
  return v;
}
