import clsx from "clsx";
import { ReactNode } from "react";
import {
  Form,
  FormProps,
  Navigation,
  useActionData,
  useNavigation,
  FormMethod,
} from "react-router";
import { Details } from "#components/details";
import { ErrorView } from "#components/errors";
import { FormSection } from "./sections/section";
import { ButtonSubmit } from "./submit_button";

import * as styles from "./router.module.scss";

export interface IFormProps<IActionData extends unknown = unknown>
  extends Omit<FormProps, "children" | "method"> {
  method: Uppercase<FormMethod>;
  statusSection?: null;
  submitButton?: (state: Navigation["state"]) => ReactNode;
  successElement?: (data: IActionData) => ReactNode;
  children?: ReactNode | ((state: Navigation["state"]) => ReactNode);
}

/**
 * TODO: incorporate [`useFetcher`](https://reactrouter.com/6.28.1/hooks/use-fetcher)
 */
export function FormRouter<IActionData extends unknown = unknown>({
  className,
  statusSection,
  submitButton,
  successElement,
  children,
  ...props
}: IFormProps<IActionData>) {
  const { state } = useNavigation();
  const actionData = useActionData() as IActionData;

  return (
    <Form className={clsx("form", className)} {...props}>
      {typeof children !== "function" ? children : children(state)}

      {statusSection !== null && (
        <FormSection>
          {state === "loading" ? (
            "Loading..."
          ) : state === "submitting" ? (
            "Submitting..."
          ) : actionData instanceof Error ? (
            <ul>
              <li>
                <Details summary={"Error details"}>
                  <ErrorView error={actionData} />
                </Details>
              </li>
            </ul>
          ) : actionData && successElement ? (
            successElement(actionData)
          ) : (
            "Ready for submit"
          )}
        </FormSection>
      )}

      {submitButton && (
        <FormSection>
          <ButtonSubmit disabled={state !== "idle"}>
            {submitButton(state)}
          </ButtonSubmit>
        </FormSection>
      )}
    </Form>
  );
}
