import {
  Button,
  Form,
  FormControl,
  FormDescription,
  FormItem,
  FormLabel,
  FormMessage,
  Input,
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
  Switch,
  Textarea
} from "@ai-ui/ui";
import type { Meta, StoryObj } from "@storybook/react";
import { Controller, useForm } from "react-hook-form";
import { useState } from "react";

type LaunchFormValues = {
  email: string;
  notifications: boolean;
  role: string;
  summary: string;
};

async function waitForCondition(
  predicate: () => boolean,
  message: string,
  timeoutMs = 2000
) {
  const startedAt = Date.now();

  while (Date.now() - startedAt < timeoutMs) {
    if (predicate()) {
      return;
    }

    await new Promise((resolve) => window.setTimeout(resolve, 16));
  }

  throw new Error(message);
}

function LaunchSettingsForm() {
  const [submitted, setSubmitted] = useState<LaunchFormValues | null>(null);
  const form = useForm<LaunchFormValues>({
    defaultValues: {
      email: "",
      notifications: true,
      role: "design",
      summary: ""
    }
  });

  return (
    <Form {...form}>
      <form
        className="grid w-[620px] gap-5 rounded-[var(--radius-lg)] border border-[var(--color-border)] bg-[var(--color-card)] p-6 shadow-[var(--shadow-sm)]"
        noValidate
        onSubmit={form.handleSubmit((values) => {
          setSubmitted(values);
        })}
      >
        <div className="space-y-2">
          <h2 className="m-0 text-xl font-semibold tracking-[var(--tracking-tight)]">
            Launch settings
          </h2>
          <p className="m-0 text-sm leading-6 text-[var(--color-muted-foreground)]">
            This story uses <code>react-hook-form</code> with the new form primitives.
          </p>
        </div>

        <FormItem name="email" required>
          <FormLabel>Email address</FormLabel>
          <FormControl>
            <Input
              placeholder="team@cadence.dev"
              {...form.register("email", {
                required: "Email is required.",
                pattern: {
                  value: /\S+@\S+\.\S+/,
                  message: "Enter a valid email address."
                }
              })}
            />
          </FormControl>
          <FormDescription>Release notes and alerts will be sent here.</FormDescription>
          <FormMessage />
        </FormItem>

        <Controller
          control={form.control}
          name="role"
          rules={{
            required: "Choose a review lane."
          }}
          render={({ field }) => (
            <FormItem name="role">
              <FormLabel>Review lane</FormLabel>
              <FormControl>
                <Select value={field.value} onValueChange={field.onChange}>
                  <SelectTrigger aria-label="Review lane">
                    <SelectValue placeholder="Choose a lane" />
                  </SelectTrigger>
                  <SelectContent>
                    <SelectItem value="design">Design</SelectItem>
                    <SelectItem value="engineering">Engineering</SelectItem>
                    <SelectItem value="legal">Legal</SelectItem>
                  </SelectContent>
                </Select>
              </FormControl>
              <FormDescription>
                The selected team becomes the primary reviewer for this launch.
              </FormDescription>
              <FormMessage />
            </FormItem>
          )}
        />

        <FormItem name="summary">
          <FormLabel>Launch summary</FormLabel>
          <FormControl>
            <Textarea
              placeholder="Summarize the rollout, scope, and known risks."
              {...form.register("summary", {
                minLength: {
                  value: 24,
                  message: "Summary must be at least 24 characters."
                }
              })}
            />
          </FormControl>
          <FormDescription>Shown in the changelog card and Slack digest.</FormDescription>
          <FormMessage />
        </FormItem>

        <Controller
          control={form.control}
          name="notifications"
          render={({ field }) => (
            <FormItem name="notifications">
              <div className="flex items-start justify-between gap-4 rounded-[var(--radius-md)] border border-[var(--color-border)] bg-[var(--color-surface)] p-4">
                <div className="space-y-1">
                  <FormLabel>Weekly digest</FormLabel>
                  <FormDescription>
                    Send a Friday summary of all rollout changes to stakeholders.
                  </FormDescription>
                </div>
                <FormControl className="gap-0">
                  <Switch
                    aria-label="Weekly digest"
                    checked={field.value}
                    onCheckedChange={field.onChange}
                  />
                </FormControl>
              </div>
              <FormMessage />
            </FormItem>
          )}
        />

        <div className="flex items-center justify-end gap-3">
          <Button
            type="button"
            variant="ghost"
            onClick={() => {
              form.reset();
              setSubmitted(null);
            }}
          >
            Reset
          </Button>
          <Button type="submit">Save settings</Button>
        </div>

        <div className="rounded-[var(--radius-md)] border border-[var(--color-border)] bg-[var(--color-background)] p-4">
          <p className="m-0 text-xs uppercase tracking-[var(--tracking-caps)] text-[var(--color-muted-foreground)]">
            Submitted payload
          </p>
          <pre className="m-0 mt-3 overflow-x-auto text-sm leading-6 text-[var(--color-foreground)]">
            <code>{submitted ? JSON.stringify(submitted, null, 2) : "Submit the form to inspect values."}</code>
          </pre>
        </div>
      </form>
    </Form>
  );
}

const meta = {
  title: "Components/Form",
  component: LaunchSettingsForm,
  parameters: {
    layout: "centered"
  },
  tags: ["autodocs"]
} satisfies Meta<typeof LaunchSettingsForm>;

export default meta;

type Story = StoryObj<typeof meta>;

export const LaunchSettings: Story = {
  play: async ({ canvasElement }) => {
    const emailInput = canvasElement.querySelector('input[placeholder="team@cadence.dev"]');

    if (!(emailInput instanceof HTMLInputElement)) {
      throw new Error("Expected the email input to render.");
    }

    emailInput.focus();
    emailInput.value = "team@cadence.dev";
    emailInput.dispatchEvent(new Event("input", { bubbles: true }));
    emailInput.dispatchEvent(new Event("change", { bubbles: true }));

    const roleTrigger = [...canvasElement.querySelectorAll('[data-slot="trigger"]')].find(
      (element) => element.textContent?.includes("Design")
    );

    if (!(roleTrigger instanceof HTMLElement)) {
      throw new Error("Expected the role select trigger to render.");
    }

    roleTrigger.click();

    await waitForCondition(
      () => document.body.querySelector('[role="listbox"]') instanceof HTMLElement,
      "Expected the role select content to open."
    );

    const legalOption = [...document.body.querySelectorAll('[role="option"]')].find((element) =>
      element.textContent?.includes("Legal")
    );

    if (!(legalOption instanceof HTMLElement)) {
      throw new Error("Expected to find the Legal option.");
    }

    legalOption.click();

    const summaryInput = canvasElement.querySelector("textarea");

    if (!(summaryInput instanceof HTMLTextAreaElement)) {
      throw new Error("Expected the launch summary textarea to render.");
    }

    summaryInput.value = "This release coordinates approvals, copy, and rollout risks.";
    summaryInput.dispatchEvent(new Event("input", { bubbles: true }));
    summaryInput.dispatchEvent(new Event("change", { bubbles: true }));

    const submitButton = [...canvasElement.querySelectorAll("button")].find((element) =>
      element.textContent?.includes("Save settings")
    );

    if (!(submitButton instanceof HTMLButtonElement)) {
      throw new Error("Expected the form submit button to render.");
    }

    submitButton.click();

    await waitForCondition(
      () => canvasElement.textContent?.includes('"email": "team@cadence.dev"') ?? false,
      "Expected the submitted payload preview to update."
    );
  }
};
