import { FormSelectLayout } from "@/components/form-common/form-layouts";
import { FormServerErrors } from "@/components/form-common/form-server-errors";
import { ClusterRegionSelect } from "@/components/form-fields/cluster-region-select";
import { startAuthorizeServerless } from "@/components/form-fields/serverless-cluster-select";
import type { LabMetaV2 } from "@/components/labs/hooks-v2";
import { LabAlert } from "@/components/labs/lab-alart";
import { useMe } from "@/components/me-context";
import { useSubscribeChanges } from "@/components/tanstack-form-utils";
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/tooltip";
import { useLocaleFunction } from "@/hooks/use-localed";
import {
  type ClusterRegionKey,
  clusterRegionKeySchema,
} from "@/lib/cluster-regions";
import { handleFormElementSubmitEvent, handleSubmitErrors } from "@/lib/form";
import { FieldApi, useForm } from "@tanstack/react-form";
import { RefreshCwIcon } from "lucide-react";
import { useRouter } from "next/navigation";
import { type ComponentProps, type ReactElement, useTransition } from "react";
import { z, type ZodSchema } from "zod";
import {
  type DeployLabFormV2Props,
  LabLearnMoreButton,
  LabMetaInfoFields,
  LabNotAvailableAlert,
  LabRedeemButton,
  processDeployLab,
  selectDefaultRegion,
} from "./deploy-lab-form.common";

export default function DeployEssentialLabForm({
  lab,
  region,
  onChange,
  tidbEnvironment,
  onTiDBEnvironmentChange,
}: DeployLabFormV2Props) {
  const [transitioning, startTransition] = useTransition();
  const { data: me } = useMe();
  const router = useRouter();

  const t = useLocaleFunction();

  const disabled = !me || !lab.can_start;

  const form = useForm({
    validators: {
      onChange: schema,
      onBlur: schema,
      onSubmit: schema,
    },
    defaultValues: {
      region: selectDefaultRegion(lab, region ?? "aws:tokyo"),
      tidb_version: undefined,
      serverless_cluster_type: "user-host",
      user_serverless_cluster_id: undefined,
    } as FormValues,
    async onSubmit({ value, formApi }) {
      await handleSubmitErrors(formApi, async () => {
        value = { ...value };
        await processDeployLab(
          lab,
          { tidb_environment: "TiDB Cloud Essential", ...value },
          startTransition,
          router
        );
      });
    },
  });

  useSubscribeChanges(form, onChange);

  const canRedeem = !lab.can_start && lab.suggestion && lab.credit_redeemable;
  const showStart = !!me && (lab.can_start || canRedeem);
  const showLearnMore =
    !lab.can_start && !lab.credit_redeemable && t(lab, "training_class_url");

  return (
    <form
      id="deploy-lab"
      className="space-y-4 p-4 rounded-lg"
      onSubmit={handleFormElementSubmitEvent(form)}
    >
      <LabMetaInfoFields
        lab={lab}
        tidbEnvironment={tidbEnvironment}
        onTiDBEnvironmentChange={onTiDBEnvironmentChange}
      />
      <form.Field name="region">
        {(field) => (
          <FormSelectLayout fieldApi={field} label={t("lab.meta.region")}>
            <ClusterRegionSelect allowedValues={lab.regions} />
          </FormSelectLayout>
        )}
      </form.Field>
      <FormServerErrors
        formApi={form}
        title={t("lab.alerts.failed-to-deploy")}
      />
      {!lab.can_start && lab.suggestion && <LabNotAvailableAlert lab={lab} />}
      {canRedeem && <LabRedeemButton lab={lab} />}
      {showStart && (
        <form.Subscribe
          selector={(form) => [
            lab.can_start !== true ||
              !form.canSubmit ||
              transitioning ||
              disabled,
          ]}
        >
          {([disabled]) => (
            <Button className="w-full cursor-pointer" type="submit" disabled={disabled}>
              {t("lab.start")}
            </Button>
          )}
        </form.Subscribe>
      )}
      {showLearnMore && <LabLearnMoreButton lab={lab} />}
      <LabAlert icon="alert-octagon" description="lab.alerts.experimental" />
    </form>
  );
}

function RetryAuthorizeButton({
  lab,
  field,
}: {
  lab: LabMetaV2;
  field?: FieldApi<
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any,
    any
  >;
}) {
  const t = useLocaleFunction();
  return (
    <TooltipProvider>
      <Tooltip>
        <TooltipTrigger asChild>
          <button
            type="button"
            onClick={() => startAuthorizeServerless(lab.lab_code, field)}
          >
            <RefreshCwIcon className="size-3.5 transition-all cursor-pointer text-muted-foreground hover:text-primary" />
          </button>
        </TooltipTrigger>
        <TooltipContent>
          {t("lab.meta.serverless-cluster.retry-authorize")}
        </TooltipContent>
      </Tooltip>
    </TooltipProvider>
  );
}

function ReusingClusterAlertDialog({
  children,
}: {
  children: ReactElement<ComponentProps<typeof Button>>;
}) {
  const t = useLocaleFunction();
  return (
    <AlertDialog>
      <AlertDialogTrigger asChild>{children}</AlertDialogTrigger>
      <AlertDialogContent>
        <AlertDialogHeader>
          <AlertDialogTitle>
            {t("lab.alerts.before-byo-start.title")}
          </AlertDialogTitle>
          <AlertDialogDescription>
            {t("lab.alerts.before-byo-start.description")}
          </AlertDialogDescription>
        </AlertDialogHeader>
        <AlertDialogFooter>
          <AlertDialogAction type="submit" form="deploy-lab">
            {t("lab.start")}
          </AlertDialogAction>
          <AlertDialogCancel>{t("common.cancel")}</AlertDialogCancel>
        </AlertDialogFooter>
      </AlertDialogContent>
    </AlertDialog>
  );
}

const schema: ZodSchema<FormValues, any, any> = z.object({
  region: clusterRegionKeySchema,
});

type FormValues = {
  region: ClusterRegionKey;
};
