import { WORKSPACE_STORAGE_TYPE } from '@learnitive/constants';
import { useCoreServices } from '@learnitive/context';
import {
  createDefaultLearnitiveProjectConfig,
  normalizeProjectSlug,
  projectFilePath,
  requestPersistentBrowserStorage,
  supportsOpfsProjectStorage,
} from '@learnitive/project-storage';
import {
  PROJECT_MODE_CATALOG,
  PROJECT_STARTERS,
  defaultProjectName,
  projectModeForProfile,
  type ProjectProfile,
} from '@learnitive/project-runtime';
import {
  Button,
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  Input,
  Label,
} from '@learnitive/ui-components';
import { WsPath } from '@learnitive/ws-path';
import { useAtom } from 'jotai';
import { Settings2 } from 'lucide-react';
import { LEARNITIVE_CAPABILITIES, LEARNITIVE_VISIBLE_PROJECT_MODE_IDS } from '../product-capabilities';
import React from 'react';
import { AI_SETTINGS_CLOSED_EVENT, AI_SETTINGS_SAVED_EVENT, openAiSettingsDialog } from '../components/ai-settings-events';
import { CloneGitRepositoryDialog } from '../components/clone-git-repository-dialog';
import { getAuthState } from '../saas/saas-api';
import { finalizeCreatedBrowserProject } from '../saas/project-mirror-service';
import {
  clearPendingHomeAiIntent,
  HOME_AI_BUILD_REQUEST_EVENT,
  HOME_PROJECT_DIALOG_REQUEST_EVENT,
  starterIdForHomeAiIntent,
  type PendingHomeAiIntent,
} from '../saas/home-ai-build-intent';

function starterIdForAiPrompt(prompt: string, fallback: string): string {
  const text = prompt.trim().toLowerCase();
  if (!text) return fallback;
  if (/\blatex\b|\btex\b|\bbibtex\b|\bsynctex\b/u.test(text)) return 'latex';
  if (/\breact\b/u.test(text)) return 'react-vite';
  if (/\bvue(?:\.js)?\b/u.test(text)) return 'vue-vite';
  if (/\bpython\b|\bpyodide\b/u.test(text)) return 'python';
  if (/\bc\+\+\b|\bcpp\b/u.test(text)) return 'cpp';
  if (/\brust\b/u.test(text)) return 'rust';
  if (/\bjava\b/u.test(text) && !/\bjavascript\b/u.test(text)) return 'java';
  if (/\bnode(?:\.js)?\b/u.test(text)) return 'node';
  if (/\bexpress\b|\brest api\b|\bapi server\b/u.test(text)) return 'express';
  if (/\bwebsite\b|\bweb page\b|\bhtml\b|\bcss\b|\bjavascript\b/u.test(text)) return 'html-css-js';
  return 'markdown';
}

function projectNameForAiPrompt(prompt: string, starterId: string): string {
  const words = prompt
    .replace(/[^A-Za-z0-9+#.-]+/gu, ' ')
    .trim()
    .split(/\s+/u)
    .filter((word) => !/^(?:please|build|create|make|generate|write|me|a|an|the|my|for|using|with)$/iu.test(word))
    .slice(0, 7);
  return normalizeProjectSlug(words.join(' '), { fallback: defaultProjectName(starterId) });
}

export function CreateWorkspaceDialog() {
  const core = useCoreServices();
  const [open, setOpen] = useAtom(core.workbenchState.$openWsDialog);
  const [starterId, setStarterId] = React.useState('markdown');
  const initialProjectName = React.useMemo(() => defaultProjectName('markdown'), []);
  const [name, setName] = React.useState(initialProjectName);
  const [busy, setBusy] = React.useState(false);
  const [error, setError] = React.useState<string>();
  const [creationPath, setCreationPath] = React.useState<'traditional' | 'ai'>('traditional');
  const [aiPrompt, setAiPrompt] = React.useState('');
  const [codeCatalogOpen, setCodeCatalogOpen] = React.useState(false);
  const [cloneOpen, setCloneOpen] = React.useState(false);
  const [aiUpgradeOpen, setAiUpgradeOpen] = React.useState(false);
  const importRef = React.useRef<HTMLInputElement>(null);
  const pendingAiBuildRef = React.useRef<string>();
  const pendingHomeStarterOverrideRef = React.useRef<string>();
  const pendingHomeAutoStartRef = React.useRef<{ prompt: string; starterId: string }>();
  const createStarterRef = React.useRef<(aiBuildRequest?: string) => Promise<void>>(async () => undefined);

  const selected = PROJECT_STARTERS.find((item) => item.id === starterId) ?? PROJECT_STARTERS[0];
  const selectedMode = projectModeForProfile(selected?.profile);
  const visibleDocumentModes = LEARNITIVE_VISIBLE_PROJECT_MODE_IDS
    .map((id) => PROJECT_MODE_CATALOG.find((mode) => mode.id === id))
    .filter((mode): mode is (typeof PROJECT_MODE_CATALOG)[number] => Boolean(mode));
  const codingLanguageModes = PROJECT_MODE_CATALOG.filter((mode) => mode.projectType !== 'document' && (!mode.frameworkId || mode.frameworkId === 'vanilla-web'));
  const codingFrameworkModes = PROJECT_MODE_CATALOG.filter((mode) => mode.projectType !== 'document' && Boolean(mode.frameworkId) && mode.frameworkId !== 'vanilla-web');
  const selectedIsCode = Boolean(selectedMode && selectedMode.projectType !== 'document');
  const chooseStarter = React.useCallback((nextStarterId: string) => {
    if (!PROJECT_STARTERS.some((item) => item.id === nextStarterId)) return;
    pendingHomeStarterOverrideRef.current = undefined;
    setName(defaultProjectName(nextStarterId));
    setStarterId(nextStarterId);
    setError(undefined);
  }, []);

  React.useEffect(() => {
    if (!open) return;
    if (!PROJECT_STARTERS.some((item) => item.id === starterId)) chooseStarter('markdown');
  }, [chooseStarter, open, starterId]);

  const wasOpenRef = React.useRef(open);
  React.useEffect(() => {
    const justOpened = open && !wasOpenRef.current;
    wasOpenRef.current = open;
    if (!justOpened || creationPath !== 'traditional') return;
    setCodeCatalogOpen(false);
    setStarterId('markdown');
    setName(defaultProjectName('markdown'));
    setError(undefined);
  }, [creationPath, open]);

  React.useEffect(() => {
    const handleHomeBuild = (event: Event) => {
      const detail = (event as CustomEvent<PendingHomeAiIntent>).detail;
      const prompt = String(detail?.prompt ?? '').trim();
      if (!prompt || detail?.source !== 'home-ai-builder') return;
      const requestedStarter = starterIdForHomeAiIntent(detail.projectIntent);
      const requestedAdvancedStarter = requestedStarter && requestedStarter !== 'markdown' && requestedStarter !== 'latex' ? requestedStarter : undefined;
      const formatStarter = detail.outputFormat === 'latex' || detail.outputFormat === 'markdown' ? detail.outputFormat : undefined;
      const inferredStarter = requestedAdvancedStarter ?? formatStarter ?? requestedStarter ?? starterIdForAiPrompt(prompt, 'markdown');
      const nextStarter = PROJECT_STARTERS.some((item) => item.id === inferredStarter) ? inferredStarter : 'markdown';
      pendingHomeStarterOverrideRef.current = detail.projectIntent || formatStarter ? nextStarter : undefined;
      setCodeCatalogOpen(false);
      setCreationPath('ai');
      setAiPrompt(prompt);
      setStarterId(nextStarter);
      setName(projectNameForAiPrompt(prompt, nextStarter));
      setError(undefined);
      pendingHomeAutoStartRef.current = { prompt, starterId: nextStarter };
      clearPendingHomeAiIntent();
      setOpen(true);
    };
    const handleProjectDialog = () => {
      pendingHomeAutoStartRef.current = undefined;
      pendingHomeStarterOverrideRef.current = undefined;
      setCodeCatalogOpen(false);
      setCreationPath('traditional');
      setStarterId('markdown');
      setName(defaultProjectName('markdown'));
      setError(undefined);
      setOpen(true);
    };
    window.addEventListener(HOME_AI_BUILD_REQUEST_EVENT, handleHomeBuild);
    window.addEventListener(HOME_PROJECT_DIALOG_REQUEST_EVENT, handleProjectDialog);
    return () => {
      window.removeEventListener(HOME_AI_BUILD_REQUEST_EVENT, handleHomeBuild);
      window.removeEventListener(HOME_PROJECT_DIALOG_REQUEST_EVENT, handleProjectDialog);
    };
  }, [setOpen]);

  const validateName = (raw: string): string => {
    const value = normalizeProjectSlug(raw, { fallback: 'project' });
    const result = WsPath.safeFromParts(value, '');
    if (!result.ok) throw new Error(result.validationError?.reason || 'Choose a valid project name.');
    return value;
  };

  const attachLocalProjectMetadata = async (
    workspaceName: string,
    displayName: string,
    profile?: ProjectProfile,
    aiBuildRequest?: string,
  ) => {
    await core.workspaceOps.updateWorkspaceMetadata(workspaceName, (metadata) => ({
      ...metadata,
      projectDisplayName: displayName,
      ...(profile ? { projectProfile: profile, projectModeId: projectModeForProfile(profile)?.id } : {}),
      ...(aiBuildRequest ? { aiBuildRequest: { id: Date.now(), text: aiBuildRequest } } : {}),
    }));
  };

  const openWorkspace = async (workspaceName: string, profile?: ProjectProfile) => {
    await core.workspaceState.refreshWorkspacesNow();
    core.fileSystem.refreshFileTree();
    const entry = profile?.entry;
    if (entry) core.navigation.goWsFile(WsPath.fromParts(workspaceName, entry).wsPath);
    else core.navigation.goWorkspace(workspaceName);
    setOpen(false);
  };

  const createStarter = async (aiBuildRequest?: string) => {
    if (!selected) return;
    const prompt = aiBuildRequest?.trim();
    const inferredStarterId = prompt ? (pendingHomeStarterOverrideRef.current ?? starterIdForAiPrompt(prompt, selected.id)) : selected.id;
    const starter = PROJECT_STARTERS.find((item) => item.id === inferredStarterId) ?? selected;
    const displayName = (name || defaultProjectName(starter.id)).trim() || defaultProjectName(starter.id);
    const workspaceName = validateName(displayName);
    setBusy(true); setError(undefined);
    try {
      if (prompt) {
        const auth = await getAuthState();
        if (!auth.authenticated) throw new Error('Build with AI requires sign in. Your normal local project creation remains available without AI.');
        if (!auth.entitlement.pro && auth.user.role !== 'admin') {
          setAiUpgradeOpen(true);
          return;
        }
        const readiness = core.projectAi.agentReadiness();
        if (!readiness.ready) {
          pendingAiBuildRef.current = prompt;
          setError(readiness.reason ?? 'Configure an Agent-capable AI provider before using Build with AI.');
          openAiSettingsDialog();
          return;
        }
        pendingAiBuildRef.current = undefined;
      }
      const type = supportsOpfsProjectStorage() ? WORKSPACE_STORAGE_TYPE.BrowserOPFS : WORKSPACE_STORAGE_TYPE.Browser;
      await core.workspaceOps.createWorkspaceInfo({
        name: workspaceName,
        type,
        metadata: {
          ...(projectModeForProfile(starter.profile)?.id === 'latex' ? { project: createDefaultLearnitiveProjectConfig() } : {}),
          projectProfile: starter.profile,
          projectModeId: projectModeForProfile(starter.profile)?.id,
          product: 'learnitive',
          projectDisplayName: displayName,
        },
      });
      const provider = await core.projectStorage.getProvider(workspaceName);
      const encoder = new TextEncoder();
      for (const [path, content] of Object.entries(starter.files)) {
        await provider.writeFile(projectFilePath(path), encoder.encode(content));
      }
      await requestPersistentBrowserStorage();
      await attachLocalProjectMetadata(workspaceName, displayName, starter.profile, prompt);
      await finalizeCreatedBrowserProject(workspaceName, core);
      pendingHomeStarterOverrideRef.current = undefined;
      await openWorkspace(workspaceName, starter.profile);
    } catch (reason) {
      setError(reason instanceof Error ? reason.message : String(reason));
    } finally { setBusy(false); }
  };

  createStarterRef.current = createStarter;

  React.useEffect(() => {
    const pending = pendingHomeAutoStartRef.current;
    if (!pending || !open || creationPath !== 'ai' || busy) return;
    if (aiPrompt.trim() !== pending.prompt || starterId !== pending.starterId) return;
    pendingHomeAutoStartRef.current = undefined;
    void createStarterRef.current(pending.prompt);
  }, [aiPrompt, busy, creationPath, open, starterId]);

  React.useEffect(() => {
    const handleSaved = () => {
      const pendingPrompt = pendingAiBuildRef.current;
      if (!open || creationPath !== 'ai' || !pendingPrompt) return;
      const readiness = core.projectAi.agentReadiness();
      if (!readiness.ready) {
        setError(readiness.reason ?? 'AI setup is still incomplete.');
        return;
      }
      pendingAiBuildRef.current = undefined;
      setError(undefined);
      void createStarterRef.current(pendingPrompt);
    };
    const handleClosed = () => {
      if (!core.projectAi.agentReadiness().ready) pendingAiBuildRef.current = undefined;
    };
    window.addEventListener(AI_SETTINGS_SAVED_EVENT, handleSaved);
    window.addEventListener(AI_SETTINGS_CLOSED_EVENT, handleClosed);
    return () => {
      window.removeEventListener(AI_SETTINGS_SAVED_EVENT, handleSaved);
      window.removeEventListener(AI_SETTINGS_CLOSED_EVENT, handleClosed);
    };
  }, [core.projectAi, creationPath, open]);

  const importZip = async (file: File) => {
    setBusy(true); setError(undefined);
    try {
      const displayName = (name || file.name.replace(/\.zip$/iu, '') || 'Imported Project').trim() || 'Imported Project';
      const workspaceName = validateName(displayName);
      const type = supportsOpfsProjectStorage() ? WORKSPACE_STORAGE_TYPE.BrowserOPFS : WORKSPACE_STORAGE_TYPE.Browser;
      await core.workspaceOps.createWorkspaceInfo({ name: workspaceName, type, metadata: { product: 'learnitive', projectDisplayName: displayName } });
      await core.projectStorage.importZipBlob(workspaceName, file);
      const targets = await core.projectStorage.detectProjectTargets(workspaceName);
      const profile = targets[0]?.profile;
      if (profile) await core.projectStorage.updateProjectProfile(workspaceName, profile);
      await requestPersistentBrowserStorage();
      await attachLocalProjectMetadata(workspaceName, displayName, profile);
      await finalizeCreatedBrowserProject(workspaceName, core);
      await openWorkspace(workspaceName, profile);
    } catch (reason) {
      setError(reason instanceof Error ? reason.message : String(reason));
    } finally { setBusy(false); }
  };

  return <>
    <input ref={importRef} type="file" className="sr-only" accept=".zip,application/zip" onChange={(event) => { const file = event.currentTarget.files?.[0]; event.currentTarget.value = ''; if (file) void importZip(file); }} />
    <Dialog open={open} onOpenChange={(value) => !busy && setOpen(value)}>
      <DialogContent className="max-h-[90vh] overflow-y-auto sm:max-w-6xl" data-testid="learnitive-new-project-dialog">
        <DialogHeader>
          <DialogTitle>{creationPath === 'ai' ? 'Write with AI' : 'Create a project'}</DialogTitle>
          <DialogDescription>{creationPath === 'ai' ? 'Describe the document you want to create. Learnitive starts a local-first Markdown or LaTeX project, then AI works with the real files in that project.' : 'Start with Markdown or LaTeX for writing. Code stays tucked away until you need a language or framework.'}</DialogDescription>
        </DialogHeader>
        {error ? <div role="alert" className="rounded-md border border-destructive/40 bg-destructive/5 px-3 py-2 text-sm text-destructive">{error}</div> : null}

        <div className="grid gap-2 sm:grid-cols-2" role="tablist" aria-label="Project creation method">
          <button type="button" role="tab" aria-selected={creationPath === 'traditional'} className={`rounded-lg border p-3 text-left ${creationPath === 'traditional' ? 'border-primary bg-primary/10 ring-1 ring-primary/30' : 'bg-background hover:bg-muted/40'}`} onClick={() => { pendingHomeStarterOverrideRef.current = undefined; setCreationPath('traditional'); setError(undefined); }}>
            <span className="block text-sm font-semibold">New document</span>
            <span className="mt-1 block text-xs text-muted-foreground">Choose Markdown or LaTeX and start writing immediately.</span>
          </button>
          <button type="button" role="tab" aria-selected={creationPath === 'ai'} className={`rounded-lg border p-3 text-left ${creationPath === 'ai' ? 'border-primary bg-primary/10 ring-1 ring-primary/30' : 'bg-background hover:bg-muted/40'}`} onClick={() => { pendingHomeStarterOverrideRef.current = undefined; setCreationPath('ai'); setError(undefined); }}>
            <span className="block text-sm font-semibold">Write with AI</span>
            <span className="mt-1 block text-xs text-muted-foreground">Create a real writing project, then let AI draft and refine the document with you.</span>
          </button>
        </div>

        {creationPath === 'ai' ? (
          <div className="space-y-2 rounded-lg border bg-muted/10 p-3">
            <div className="flex items-center justify-between gap-3">
              <Label htmlFor="learnitive-ai-build-prompt">What do you want to write?</Label>
              <Button type="button" size="sm" variant="ghost" onClick={() => openAiSettingsDialog()} aria-label="AI Settings" title="AI Settings">
                <Settings2 className="mr-1 size-4" />AI Settings
              </Button>
            </div>
            <textarea
              id="learnitive-ai-build-prompt"
              className="min-h-28 w-full resize-y rounded-md border bg-background px-3 py-2 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring"
              value={aiPrompt}
              maxLength={8000}
              placeholder="Draft a research brief on renewable energy policy with an executive summary, cited sections and a concise conclusion."
              onChange={(event) => setAiPrompt(event.currentTarget.value)}
            />
            <p className="text-xs text-muted-foreground">Learnitive creates a normal local-first Markdown or LaTeX writing project from your request. Homepage format choices are preserved when present. Sign-in is required for server-backed AI Agent workflows.</p>
          </div>
        ) : null}

        <div className="space-y-2">
          <Label htmlFor="learnitive-project-name">Project name</Label>
          <Input id="learnitive-project-name" value={name} placeholder={`${projectModeForProfile(selected?.profile)?.namingPrefix ?? 'project'}-orbit`} onChange={(event) => setName(event.currentTarget.value)} />
          <p className="text-xs text-muted-foreground">Selecting a project type generates a fresh project name. You can customise it before creating the project.</p>
        </div>

        {creationPath === 'traditional' ? (
          <div className="space-y-2">
            <div>
              <Label>Project type</Label>
              <p className="mt-1 text-xs text-muted-foreground">Markdown is the default for writing. LaTeX is ideal for academic publishing. Choose Code only when you need a programming language or framework.</p>
            </div>
            <div className="grid grid-cols-1 gap-3 sm:grid-cols-3" aria-label="Project types" data-testid="project-type-grid">
              {visibleDocumentModes.map((mode) => {
                const active = starterId === mode.starterId;
                const detail = mode.id === 'markdown'
                  ? 'Visual + source Markdown for notes, articles, books and general writing'
                  : 'Academic and technical writing with bibliography, mathematics and PDF preview';
                const badge = mode.id === 'markdown' ? 'MD' : 'TeX';
                return <button key={mode.id} type="button" aria-pressed={active} aria-label={mode.label} className={`group flex min-h-28 items-center gap-3 rounded-lg border px-4 py-4 text-left transition-colors ${active ? 'border-primary bg-primary/10 ring-1 ring-primary/30' : 'bg-background hover:border-primary/50 hover:bg-muted/40'}`} onClick={() => { setCodeCatalogOpen(false); chooseStarter(mode.starterId); }}>
                  <span aria-hidden="true" className={`flex size-11 shrink-0 items-center justify-center rounded-md border bg-muted/30 font-mono text-[10px] font-bold ${active ? 'border-primary/40 text-primary' : 'text-foreground/80'}`}>{badge}</span>
                  <span><span className="block text-sm font-semibold">{mode.label}</span><span className="mt-1 block text-xs leading-snug text-muted-foreground">{detail}</span></span>
                </button>;
              })}
              {LEARNITIVE_CAPABILITIES.codingProjectCreation ? <button type="button" aria-expanded={codeCatalogOpen} aria-controls="learnitive-code-project-catalog" className={`group flex min-h-28 items-center gap-3 rounded-lg border px-4 py-4 text-left transition-colors ${selectedIsCode || codeCatalogOpen ? 'border-primary bg-primary/10 ring-1 ring-primary/30' : 'bg-background hover:border-primary/50 hover:bg-muted/40'}`} onClick={() => {
                if (!codeCatalogOpen || !selectedIsCode) chooseStarter('python');
                setCodeCatalogOpen(true);
                setError(undefined);
              }}>
                <span aria-hidden="true" className={`flex size-11 shrink-0 items-center justify-center rounded-md border bg-muted/30 font-mono text-[10px] font-bold ${selectedIsCode || codeCatalogOpen ? 'border-primary/40 text-primary' : 'text-foreground/80'}`}>&lt;/&gt;</span>
                <span><span className="block text-sm font-semibold">Code</span><span className="mt-1 block text-xs leading-snug text-muted-foreground">Languages and frameworks are available on demand without taking over the writing-first workspace.</span></span>
              </button> : null}
            </div>

            {LEARNITIVE_CAPABILITIES.codingCatalog && codeCatalogOpen ? (
              <div id="learnitive-code-project-catalog" className="space-y-4 rounded-lg border bg-muted/10 p-4" data-testid="code-project-catalog">
                <div>
                  <h3 className="text-sm font-semibold">Languages</h3>
                  <p className="mt-1 text-xs text-muted-foreground">Start a focused code project with the runtime and starter files already configured.</p>
                  <div className="mt-3 grid grid-cols-2 gap-2 sm:grid-cols-3 lg:grid-cols-4">
                    {codingLanguageModes.map((mode) => {
                      const active = starterId === mode.starterId;
                      return <button key={mode.id} type="button" aria-pressed={active} className={`rounded-md border px-3 py-2 text-left text-sm transition-colors ${active ? 'border-primary bg-primary/10 text-primary' : 'bg-background hover:border-primary/50 hover:bg-muted/40'}`} onClick={() => chooseStarter(mode.starterId)}>
                        <span className="block font-medium">{mode.catalogLabel ?? mode.label}</span>
                        <span className="mt-0.5 block text-[11px] text-muted-foreground">{mode.primaryLanguage ?? mode.primaryLanguageId}</span>
                      </button>;
                    })}
                  </div>
                </div>

                {LEARNITIVE_CAPABILITIES.frameworkCatalog ? <div>
                  <h3 className="text-sm font-semibold">Frameworks</h3>
                  <p className="mt-1 text-xs text-muted-foreground">Choose a web or application starter when you want a framework-specific project.</p>
                  <div className="mt-3 grid grid-cols-1 gap-2 sm:grid-cols-2 lg:grid-cols-3">
                    {codingFrameworkModes.map((mode) => {
                      const active = starterId === mode.starterId;
                      return <button key={mode.id} type="button" aria-pressed={active} className={`rounded-md border px-3 py-2 text-left text-sm transition-colors ${active ? 'border-primary bg-primary/10 text-primary' : 'bg-background hover:border-primary/50 hover:bg-muted/40'}`} onClick={() => chooseStarter(mode.starterId)}>
                        <span className="block font-medium">{mode.catalogLabel ?? mode.label}</span>
                        <span className="mt-0.5 block text-[11px] text-muted-foreground">{mode.framework ?? mode.primaryLanguage ?? mode.primaryLanguageId}</span>
                      </button>;
                    })}
                  </div>
                </div> : null}
              </div>
            ) : null}
          </div>
        ) : null}

        {LEARNITIVE_CAPABILITIES.advancedProjectImport ? (
          <details className="rounded-lg border bg-muted/10 p-3">
            <summary className="cursor-pointer text-sm font-medium">Import an existing project</summary>
            <div className="mt-3 flex flex-wrap gap-2">
              <Button type="button" variant="outline" disabled={busy} onClick={() => importRef.current?.click()}>Import ZIP</Button>
              <Button type="button" variant="outline" disabled={busy} onClick={() => { setOpen(false); setCloneOpen(true); }}>Clone Git</Button>
            </div>
          </details>
        ) : null}

        <DialogFooter><Button type="button" disabled={busy || !selected || (creationPath === 'ai' && !aiPrompt.trim())} onClick={() => void createStarter(creationPath === 'ai' ? aiPrompt : undefined)}>{busy ? (creationPath === 'ai' ? 'Starting AI…' : 'Creating…') : creationPath === 'ai' ? 'Write with AI' : 'Create project'}</Button></DialogFooter>
      </DialogContent>
    </Dialog>
    <CloneGitRepositoryDialog open={cloneOpen} onOpenChange={setCloneOpen} />
    <Dialog open={aiUpgradeOpen} onOpenChange={setAiUpgradeOpen}>
      <DialogContent className="sm:max-w-md" data-testid="create-project-ai-pro-upgrade-dialog">
        <DialogHeader>
          <DialogTitle>AI writing requires Pro</DialogTitle>
          <DialogDescription>Server-backed AI writing is not enabled for your current Free plan.</DialogDescription>
        </DialogHeader>
        <DialogFooter>
          <Button type="button" variant="outline" onClick={() => setAiUpgradeOpen(false)}>Not now</Button>
          <a className="interactive-button interactive-button-primary" href="/pricing">Buy Pro</a>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  </>;
}
