import {
  Button,
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger
} from "@ai-ui/ui";
import type { Meta, StoryObj } from "@storybook/react";

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

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

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

  throw new Error(message);
}

type LaunchDialogProps = {
  description?: string;
  size?: "sm" | "md" | "lg";
  title?: string;
  triggerLabel?: string;
};

function LaunchDialog({
  description = "This will notify the routing team and publish the release note to the activity feed.",
  size = "md",
  title = "Launch this release?",
  triggerLabel = "Open approval dialog"
}: LaunchDialogProps) {
  return (
    <Dialog>
      <DialogTrigger asChild>
        <Button>{triggerLabel}</Button>
      </DialogTrigger>
      <DialogContent size={size}>
        <DialogHeader>
          <DialogTitle>{title}</DialogTitle>
          <DialogDescription>{description}</DialogDescription>
        </DialogHeader>
        <DialogFooter>
          <Button variant="ghost">Cancel</Button>
          <Button>Confirm launch</Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

const meta = {
  title: "Components/Dialog",
  component: Dialog,
  parameters: {
    docs: {
      description: {
        component:
          "Dialog is the system's blocking overlay for focused decisions, confirmation flows, and dense tasks that must temporarily interrupt the surrounding page. It ships with a portal, overlay, close affordance, semantic title and description wiring, and token-driven motion on both the surface and backdrop."
      }
    },
    layout: "centered"
  },
  tags: ["autodocs"]
} satisfies Meta<typeof Dialog>;

export default meta;

type Story = StoryObj<typeof meta>;

export const Playground: Story = {
  render: () => <LaunchDialog />,
  play: async ({ canvasElement }) => {
    const trigger = [...canvasElement.querySelectorAll("button")].find((element) =>
      element.textContent?.includes("Open approval dialog")
    );

    if (!(trigger instanceof HTMLButtonElement)) {
      throw new Error("Expected the dialog trigger to render.");
    }

    trigger.click();

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

    const closeButton = document.body.querySelector('[aria-label="Close dialog"]');

    if (!(closeButton instanceof HTMLButtonElement)) {
      throw new Error("Expected the dialog close control to render.");
    }

    closeButton.click();

    await waitForCondition(
      () => document.body.querySelector('[role="dialog"]') === null,
      "Expected the dialog to close."
    );
  }
};

export const Sizes: Story = {
  render: () => (
    <div className="grid w-[720px] gap-3 sm:grid-cols-2">
      <LaunchDialog
        description="Use the compact size for short confirmations that only need a title, one supporting sentence, and one primary action."
        size="sm"
        title="Publish summary?"
        triggerLabel="Compact dialog"
      />
      <LaunchDialog
        description="Use the large size when the flow needs denser copy, audit context, or multi-step review detail before a final action."
        size="lg"
        title="Review rollout checklist"
        triggerLabel="Large dialog"
      />
    </div>
  )
};

export const Anatomy: Story = {
  render: () => (
    <div className="w-[700px] rounded-[var(--radius-lg)] border border-[var(--color-border)] bg-[var(--color-card)] p-6 text-[var(--color-foreground)] shadow-[var(--shadow-sm)]">
      <div className="space-y-3">
        <p className="text-xs uppercase tracking-[var(--tracking-caps)] text-[var(--color-muted-foreground)]">
          Dialog anatomy
        </p>
        <LaunchDialog triggerLabel="Preview dialog structure" />
        <div className="grid gap-3 text-sm leading-6 text-[var(--color-muted-foreground)]">
          <p>
            <code className="text-[var(--color-foreground)]">data-slot="overlay"</code> sits
            behind the surface and carries the backdrop motion.
          </p>
          <p>
            <code className="text-[var(--color-foreground)]">data-slot="content"</code> wraps
            the modal panel and exposes <code className="text-[var(--color-foreground)]">data-size</code>.
          </p>
          <p>
            <code className="text-[var(--color-foreground)]">data-slot="header"</code>,{" "}
            <code className="text-[var(--color-foreground)]">data-slot="footer"</code>,{" "}
            <code className="text-[var(--color-foreground)]">data-slot="label"</code>, and{" "}
            <code className="text-[var(--color-foreground)]">data-slot="description"</code>
            provide stable hooks for structure and docs.
          </p>
          <p>
            The close button is built into <code className="text-[var(--color-foreground)]">DialogContent</code>,
            so every dialog gets a dismiss affordance even when the footer stays minimal.
          </p>
        </div>
      </div>
    </div>
  )
};

export const Accessibility: Story = {
  parameters: {
    docs: {
      description: {
        story:
          "Use dialog only when the user must resolve or dismiss a blocking task. Focus is trapped while open, Escape closes the surface, and the title and description are announced through the Radix dialog semantics."
      }
    }
  },
  render: () => (
    <div className="grid w-[760px] gap-4 lg:grid-cols-[minmax(0,0.95fr)_minmax(0,1.05fr)]">
      <article className="rounded-[var(--radius-lg)] border border-[var(--color-border)] bg-[var(--color-card)] p-6 shadow-[var(--shadow-sm)]">
        <h3 className="text-lg font-semibold tracking-[var(--tracking-tight)]">
          Accessibility notes
        </h3>
        <div className="mt-4 grid gap-3 text-sm leading-6 text-[var(--color-muted-foreground)]">
          <p>Keep the title outcome-oriented so assistive tech announces the decision clearly.</p>
          <p>
            Use the description for the consequence or next step, not decorative copy.
          </p>
          <p>
            Keep the trigger specific. &quot;Open approval dialog&quot; is more useful than a generic
            &quot;Open&quot;.
          </p>
          <p>
            Reserve dialogs for blocking work. If the content should not trap focus, prefer
            a popover instead.
          </p>
        </div>
      </article>
      <div className="flex items-center justify-center rounded-[var(--radius-lg)] border border-dashed border-[var(--color-border-strong)] bg-[var(--color-background)] p-6">
        <LaunchDialog
          description="Keyboard focus moves into the surface, Escape closes it, and the trigger regains focus after dismissal."
          triggerLabel="Open accessible dialog"
        />
      </div>
    </div>
  )
};
