import { Switch } from "~/components/primitives/Switch";
import { Label } from "~/components/primitives/Label";
import { Hint } from "~/components/primitives/Hint";
import { TextLink } from "~/components/primitives/TextLink";
import { SimpleTooltip } from "~/components/primitives/Tooltip";
import {
  EnvironmentIcon,
  environmentFullTitle,
  environmentTextClassName,
} from "~/components/environments/EnvironmentLabel";
import { envSlugToType, type EnvSlug } from "~/v3/vercel/vercelProjectIntegrationSchema";

type BuildSettingsFieldsProps = {
  availableEnvSlugs: EnvSlug[];
  pullEnvVarsBeforeBuild: EnvSlug[];
  onPullEnvVarsChange: (slugs: EnvSlug[]) => void;
  discoverEnvVars: EnvSlug[];
  onDiscoverEnvVarsChange: (slugs: EnvSlug[]) => void;
  atomicBuilds: EnvSlug[];
  onAtomicBuildsChange: (slugs: EnvSlug[]) => void;
  envVarsConfigLink?: string;
  /** Slugs that should be forced off and disabled, with tooltip reason. */
  disabledEnvSlugs?: Partial<Record<EnvSlug, string>>;
  autoPromote?: boolean;
  onAutoPromoteChange?: (value: boolean) => void;
  /** The currently pinned TRIGGER_VERSION on Vercel production, if any. Shown under the
   * Atomic deployments toggle so the user knows what version is set on Vercel right now. */
  currentTriggerVersion?: string | null;
  /** True when the Vercel lookup for TRIGGER_VERSION failed. We show this so the user knows
   * the pin status is unknown — distinct from "not set". */
  currentTriggerVersionFetchFailed?: boolean;
  /** Hide the section-level master toggles for "Pull env vars" and "Discover new env vars". */
  hideSectionToggles?: boolean;
};

export function BuildSettingsFields({
  availableEnvSlugs,
  pullEnvVarsBeforeBuild,
  onPullEnvVarsChange,
  discoverEnvVars,
  onDiscoverEnvVarsChange,
  atomicBuilds,
  onAtomicBuildsChange,
  envVarsConfigLink,
  disabledEnvSlugs,
  autoPromote,
  onAutoPromoteChange,
  currentTriggerVersion,
  currentTriggerVersionFetchFailed,
  hideSectionToggles,
}: BuildSettingsFieldsProps) {
  const isSlugDisabled = (slug: EnvSlug) => !!disabledEnvSlugs?.[slug];
  const enabledSlugs = availableEnvSlugs.filter((s) => !isSlugDisabled(s));

  return (
    <>
      {/* Pull env vars before build */}
      <div>
        <div className="mb-2">
          <div className="flex items-center justify-between">
            <Label>Pull env vars before build</Label>
            {!hideSectionToggles && availableEnvSlugs.length > 1 && (
              <Switch
                variant="small"
                checked={
                  enabledSlugs.length > 0 &&
                  enabledSlugs.every((s) => pullEnvVarsBeforeBuild.includes(s))
                }
                onCheckedChange={(checked) => {
                  onPullEnvVarsChange(checked ? [...enabledSlugs] : []);
                }}
              />
            )}
          </div>
          <Hint className="pr-6">
            Select which environments should pull environment variables from Vercel before each
            build.{" "}
            {envVarsConfigLink && (
              <>
                <TextLink to={envVarsConfigLink}>Configure which variables to pull</TextLink>.
              </>
            )}
          </Hint>
        </div>
        <div className="flex flex-col gap-2 rounded border bg-background-bright p-3">
          {availableEnvSlugs.map((slug) => {
            const envType = envSlugToType(slug);
            const disabled = isSlugDisabled(slug);
            const disabledReason = disabledEnvSlugs?.[slug];
            const row = (
              <div
                key={slug}
                className={`flex items-center justify-between ${disabled ? "opacity-50" : ""}`}
              >
                <div className="flex items-center gap-1.5">
                  <EnvironmentIcon environment={{ type: envType }} className="size-4" />
                  <span className={`text-sm ${environmentTextClassName({ type: envType })}`}>
                    {environmentFullTitle({ type: envType })}
                  </span>
                </div>
                <Switch
                  variant="small"
                  checked={disabled ? false : pullEnvVarsBeforeBuild.includes(slug)}
                  disabled={disabled}
                  onCheckedChange={(checked) => {
                    onPullEnvVarsChange(
                      checked
                        ? [...pullEnvVarsBeforeBuild, slug]
                        : pullEnvVarsBeforeBuild.filter((s) => s !== slug)
                    );
                  }}
                />
              </div>
            );
            if (disabled && disabledReason) {
              return <SimpleTooltip key={slug} button={row} content={disabledReason} side="left" />;
            }
            return row;
          })}
        </div>
      </div>

      {/* Discover new env vars */}
      <div>
        <div className="mb-2">
          <div className="flex items-center justify-between">
            <Label>Discover new env vars</Label>
            {!hideSectionToggles && availableEnvSlugs.length > 1 && (
              <Switch
                variant="small"
                checked={
                  enabledSlugs.length > 0 &&
                  enabledSlugs.every(
                    (s) => discoverEnvVars.includes(s) || !pullEnvVarsBeforeBuild.includes(s)
                  ) &&
                  enabledSlugs.some((s) => discoverEnvVars.includes(s))
                }
                disabled={!enabledSlugs.some((s) => pullEnvVarsBeforeBuild.includes(s))}
                onCheckedChange={(checked) => {
                  onDiscoverEnvVarsChange(
                    checked ? enabledSlugs.filter((s) => pullEnvVarsBeforeBuild.includes(s)) : []
                  );
                }}
              />
            )}
          </div>
          <Hint className="pr-6">
            Select which environments should automatically discover and create new environment
            variables from Vercel during builds.
          </Hint>
        </div>
        <div className="flex flex-col gap-2 rounded border bg-background-bright p-3">
          {availableEnvSlugs.map((slug) => {
            const envType = envSlugToType(slug);
            const disabled = isSlugDisabled(slug);
            const disabledReason = disabledEnvSlugs?.[slug];
            const isPullDisabled = !pullEnvVarsBeforeBuild.includes(slug);
            const row = (
              <div
                key={slug}
                className={`flex items-center justify-between ${disabled || isPullDisabled ? "opacity-50" : ""}`}
              >
                <div className="flex items-center gap-1.5">
                  <EnvironmentIcon environment={{ type: envType }} className="size-4" />
                  <span className={`text-sm ${environmentTextClassName({ type: envType })}`}>
                    {environmentFullTitle({ type: envType })}
                  </span>
                </div>
                <Switch
                  variant="small"
                  checked={disabled ? false : discoverEnvVars.includes(slug)}
                  disabled={disabled || isPullDisabled}
                  onCheckedChange={(checked) => {
                    onDiscoverEnvVarsChange(
                      checked
                        ? [...discoverEnvVars, slug]
                        : discoverEnvVars.filter((s) => s !== slug)
                    );
                  }}
                />
              </div>
            );
            if (disabled && disabledReason) {
              return <SimpleTooltip key={slug} button={row} content={disabledReason} side="left" />;
            }
            return row;
          })}
        </div>
      </div>

      {/* Atomic deployments */}
      <div>
        <div className="flex items-center justify-between">
          <Label>Atomic deployments</Label>
          <Switch
            variant="small"
            checked={atomicBuilds.includes("prod")}
            onCheckedChange={(checked) => {
              onAtomicBuildsChange(checked ? ["prod"] : []);
            }}
          />
        </div>
        <Hint className="pr-6">
          When enabled, production deployments wait for Vercel deployment to complete before
          promoting the Trigger.dev deployment. This will disable the "Auto-assign Custom Production
          Domains" option in your Vercel project settings to perform staged deployments.{" "}
          <TextLink
            href="https://trigger.dev/docs/vercel-integration#atomic-deployments"
            target="_blank"
          >
            Learn more
          </TextLink>
          .
        </Hint>
        {currentTriggerVersion && (
          <Hint className="pr-6">
            Currently pinned to{" "}
            <span className="font-mono text-text-bright">{currentTriggerVersion}</span> in Vercel
            production.
          </Hint>
        )}
        {!currentTriggerVersion && currentTriggerVersionFetchFailed && (
          <Hint className="pr-6 text-warning">
            Couldn't read <span className="font-mono text-text-bright">TRIGGER_VERSION</span> from
            Vercel — check the Vercel dashboard to confirm the production pin.
          </Hint>
        )}
      </div>

      {/* Auto promotion — only visible when atomic deployments are on */}
      {atomicBuilds.includes("prod") && onAutoPromoteChange !== undefined && (
        <div>
          <div className="flex items-center justify-between">
            <Label>Auto promotion</Label>
            <Switch
              variant="small"
              checked={autoPromote ?? true}
              onCheckedChange={onAutoPromoteChange}
            />
          </div>
          <Hint className="pr-6">
            When enabled, the integration automatically promotes the Vercel deployment after the
            Trigger.dev build completes. Turn off to manually promote from your Vercel dashboard —
            Trigger.dev will then promote automatically once you do.
          </Hint>
        </div>
      )}
    </>
  );
}
