"use client";

import { zodResolver } from "@hookform/resolvers/zod";
import { CloudCog, Rocket } from "lucide-react";
import Link from "next/link";
import { useRouter, useSearchParams } from "next/navigation";
import { useForm } from "react-hook-form";
import { z } from "zod";

import { scanOnDemand } from "@/actions/scans";
import { AccountsSelector } from "@/app/(prowler)/_overview/_components/accounts-selector";
import { Field, FieldError, FieldLabel, Input } from "@/components/shadcn";
import { Modal } from "@/components/shadcn/modal";
import { FormButtons } from "@/components/ui/form";
import { toast, ToastAction } from "@/components/ui/toast";
import { SCAN_JOBS_TAB } from "@/types";
import type { ProviderProps } from "@/types/providers";

import { scanAliasSchema } from "./scan-alias-validation";
import { getScanJobsTab } from "./scans.utils";

const launchScanSchema = z.object({
  providerId: z.string().min(1, "Select a provider to launch a scan."),
  scanAlias: scanAliasSchema.optional(),
});

type LaunchScanFormValues = z.infer<typeof launchScanSchema>;

interface LaunchScanModalProps {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  providers: ProviderProps[];
}

interface LaunchScanFormProps {
  providers: ProviderProps[];
  onClose: () => void;
}

function LaunchScanForm({ providers, onClose }: LaunchScanFormProps) {
  const router = useRouter();
  const searchParams = useSearchParams();
  const form = useForm<LaunchScanFormValues>({
    resolver: zodResolver(launchScanSchema),
    defaultValues: { providerId: "", scanAlias: "" },
  });

  const providerId = form.watch("providerId");
  const activeTab = getScanJobsTab(searchParams.get("tab") ?? undefined);
  const shouldShowActiveTabAction = activeTab !== SCAN_JOBS_TAB.ACTIVE;
  const disconnectedProviderIds = providers
    .filter((provider) => provider.attributes.connection.connected !== true)
    .map((provider) => provider.id);

  const onSubmit = form.handleSubmit(async ({ providerId, scanAlias }) => {
    const formData = new FormData();
    formData.set("providerId", providerId);
    const trimmedAlias = scanAlias?.trim();
    if (trimmedAlias) {
      formData.set("scanName", trimmedAlias);
    }

    const result = await scanOnDemand(formData);

    if (result?.error) {
      form.setError("root", { message: String(result.error) });
      return;
    }

    if (result?.errors && result.errors.length > 0) {
      form.setError("root", {
        message: String(result.errors[0]?.detail ?? "Failed to launch scan."),
      });
      return;
    }

    toast({
      title: "Scan launched",
      description: "The scan was launched successfully.",
      action: shouldShowActiveTabAction ? (
        <ToastAction altText="View scan in progress" asChild>
          <Link href="/scans?tab=active">View scan</Link>
        </ToastAction>
      ) : undefined,
    });
    onClose();
    router.refresh();
  });

  const providerError = form.formState.errors.providerId?.message;
  const aliasError = form.formState.errors.scanAlias?.message;
  const rootError = form.formState.errors.root?.message;
  const isSubmitting = form.formState.isSubmitting;

  return (
    <form onSubmit={onSubmit} className="flex flex-col gap-8">
      <div className="flex items-center gap-2">
        <CloudCog className="text-text-neutral-secondary size-4" />
        <span className="text-text-neutral-secondary text-sm">
          Select the provider you would like to scan
        </span>
      </div>

      <Field>
        <FieldLabel htmlFor="launch-scan-account">Providers</FieldLabel>
        <AccountsSelector
          id="launch-scan-account"
          providers={providers}
          disabledValues={disconnectedProviderIds}
          onBatchChange={(_, values) =>
            form.setValue("providerId", values.at(-1) ?? "", {
              shouldValidate: true,
            })
          }
          selectedValues={providerId ? [providerId] : []}
          closeOnSelect
        />
        {providerError && <FieldError>{providerError}</FieldError>}
      </Field>

      <Field>
        <FieldLabel htmlFor="launch-scan-alias">Alias (optional)</FieldLabel>
        <Input
          id="launch-scan-alias"
          aria-label="Alias"
          {...form.register("scanAlias")}
        />
        {aliasError && <FieldError>{aliasError}</FieldError>}
      </Field>

      {rootError && <FieldError>{rootError}</FieldError>}

      <FormButtons
        onCancel={onClose}
        submitText={isSubmitting ? "Launching..." : "Launch Scan"}
        loadingText="Launching..."
        isDisabled={isSubmitting || !providers.length}
        rightIcon={<Rocket className="size-4" />}
      />
    </form>
  );
}

export function LaunchScanModal({
  open,
  onOpenChange,
  providers,
}: LaunchScanModalProps) {
  return (
    <Modal
      open={open}
      onOpenChange={onOpenChange}
      title="Launch A Scan"
      size="xl"
      className="gap-8"
    >
      <LaunchScanForm
        providers={providers}
        onClose={() => onOpenChange(false)}
      />
    </Modal>
  );
}
