import { FormSelectLayout } from "@/components/form-common/form-layouts";
import { FormServerErrors } from "@/components/form-common/form-server-errors";
import { BasicSelect } from "@/components/form-fields/basic-select";
import { ClusterRegionSelect } from "@/components/form-fields/cluster-region-select";
import { LabAlert } from "@/components/labs/lab-alart";
import { useMe } from "@/components/me-context";
import { useSubscribeChanges } from "@/components/tanstack-form-utils";
import { Button } from "@/components/ui/button";
import { useLocaleFunction } from "@/hooks/use-localed";
import { clusterRegionKeySchema } from "@/lib/cluster-regions";
import { handleFormElementSubmitEvent, handleSubmitErrors } from "@/lib/form";
import { useForm } from "@tanstack/react-form";
import { useRouter } from "next/navigation";
import { useTransition } from "react";
import { z } from "zod";
import {
  type DeployLabFormV2Props,
  LabLearnMoreButton,
  LabMetaInfoFields,
  LabNotAvailableAlert,
  LabRedeemButton,
  processDeployLab,
  selectDefaultRegion,
} from "./deploy-lab-form.common";

export default function DeploySelfManagedLabForm({
  lab,
  onChange,
  region,
  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: {
      onBlur: schema,
      onSubmit: schema,
    },
    defaultValues: {
      region: selectDefaultRegion(lab, region ?? "aws:tokyo"),
      tidb_version: lab.tidb_versions[lab.tidb_versions.length - 1],
    },
    async onSubmit({ value, formApi }) {
      await handleSubmitErrors(formApi, async () => {
        value = { ...value };
        await processDeployLab(
          lab,
          { tidb_environment: "TiDB Self-Managed", ...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>
      <form.Field name="tidb_version">
        {(field) => (
          <FormSelectLayout
            fieldApi={field}
            label={t("lab.meta.tidb-version")}
            disabled={disabled}
          >
            <BasicSelect options={lab.tidb_versions} />
          </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>
  );
}

const schema = z.object({
  region: clusterRegionKeySchema,
  tidb_version: z.string(),
});
