import { useRef, useState } from 'react'
import { clsx } from 'clsx'
import {
  ArrowLeft,
  ArrowRight,
  Boxes,
  Check,
  FileCode2,
  FolderOpen,
  Globe2,
  Layers3,
  Package,
  Sparkles,
  X
} from 'lucide-react'
import { useCreateProject } from '../../hooks/useCreateProject'
import { useAppStore } from '../../stores/appStore'
import { getTypeLabel, PROJECT_TYPES } from './types/registry'
import { GenericSetup } from './types/GenericSetup'
import { WordpressSetup } from './types/WordpressSetup'
import type { TypeSetupHandle } from './types/shared'
import { isValidProjectName, slugifyProjectName } from './projectName'
import docksideIcon from '../../assets/dockside-icon.png'

type Step = 'site' | 'setup'

const fieldClass =
  'w-full rounded-lg border border-neutral-300 bg-white/80 px-3 py-2 text-sm shadow-sm transition placeholder:text-neutral-400 focus:border-cyan-400 dark:border-white/10 dark:bg-neutral-950/70 dark:placeholder:text-neutral-600'

const labelClass =
  'mb-1.5 block text-xs font-semibold uppercase tracking-wide text-neutral-500 dark:text-neutral-400'

const TYPE_ICONS: Record<string, typeof Globe2> = {
  '': Sparkles,
  php: FileCode2,
  wordpress: Globe2,
  drupal: Layers3,
  laravel: FileCode2,
  backdrop: Layers3,
  craftcms: Package,
  magento2: Package,
  shopware6: Package,
  symfony: Boxes,
  typo3: Layers3
}

export function CreateProjectModal({ onClose }: { onClose: () => void }): React.JSX.Element {
  const [step, setStep] = useState<Step>('site')
  const [directory, setDirectory] = useState<string | null>(null)
  const [projectName, setProjectName] = useState('')
  const [projectType, setProjectType] = useState('')
  const [docroot, setDocroot] = useState('')
  const [setupValid, setSetupValid] = useState(true)
  const [isSubmitting, setIsSubmitting] = useState(false)

  const createProject = useCreateProject()
  const selectProject = useAppStore((s) => s.selectProject)
  const setupRef = useRef<TypeSetupHandle>(null)

  const trimmedName = projectName.trim()
  const nameValid = trimmedName.length > 0 && isValidProjectName(trimmedName)
  const canContinue = directory !== null && nameValid
  const canSubmit = canContinue && setupValid && !isSubmitting

  async function handlePickDirectory(): Promise<void> {
    const picked = await window.api.create.pickDirectory()
    if (!picked) return
    setDirectory(picked)
    if (!projectName) {
      const name = picked.split('/').filter(Boolean).pop() ?? ''
      setProjectName(slugifyProjectName(name))
    }
  }

  async function handleSubmit(): Promise<void> {
    if (!directory || !canSubmit) return
    const name = projectName.trim()
    setIsSubmitting(true)
    try {
      await createProject.mutateAsync({ directory, projectName: name, projectType, docroot })
    } catch {
      setIsSubmitting(false)
      return
    }

    // Post-create (starting the project, downloading/installing WordPress,
    // etc.) can run long. Close the modal as soon as the quick `ddev
    // config` step succeeds instead of blocking the whole wizard on it —
    // the terminal panel already tracks and surfaces this operation's
    // progress and any failure independently of the modal.
    const runPostCreate = setupRef.current?.runPostCreate
    selectProject(name)
    onClose()
    runPostCreate?.({ directory, projectName: name }).catch(() => {})
  }

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-neutral-950/55 p-8 backdrop-blur-sm">
      <div className="grid max-h-[86vh] w-full max-w-4xl overflow-hidden rounded-2xl border border-white/70 bg-white shadow-[0_30px_100px_rgba(15,23,42,0.28)] dark:border-white/10 dark:bg-neutral-950 md:grid-cols-[0.82fr_1.18fr]">
        <aside className="relative hidden overflow-hidden bg-neutral-950 p-6 text-white md:block">
          <div className="absolute inset-0 bg-[linear-gradient(rgba(45,212,191,0.11)_1px,transparent_1px),linear-gradient(90deg,rgba(45,212,191,0.11)_1px,transparent_1px)] bg-[size:34px_34px]" />
          <div className="absolute inset-x-0 bottom-0 h-40 bg-gradient-to-t from-cyan-500/20 to-transparent" />
          <div className="relative flex h-full flex-col justify-between">
            <div>
              <img
                src={docksideIcon}
                alt=""
                className="mb-5 size-16 rounded-2xl shadow-lg shadow-cyan-950/30"
              />
              <p className="text-xs font-semibold uppercase tracking-wide text-cyan-200">
                Project launch
              </p>
              <h2 className="mt-3 text-3xl font-semibold leading-tight">
                Create a local site that feels ready to work.
              </h2>
            </div>

            <div className="grid gap-3">
              <div className="rounded-xl border border-white/10 bg-white/[0.08] p-4">
                <p className="text-xs font-medium uppercase tracking-wide text-neutral-400">
                  Destination
                </p>
                <p className="mt-1 truncate text-sm font-semibold">
                  {directory ? directory.split('/').filter(Boolean).pop() : 'Choose a folder'}
                </p>
              </div>
              <div className="rounded-xl border border-white/10 bg-white/[0.08] p-4">
                <p className="text-xs font-medium uppercase tracking-wide text-neutral-400">
                  Project
                </p>
                <p className="mt-1 truncate text-sm font-semibold">
                  {projectName.trim() || 'Name pending'}
                </p>
              </div>
            </div>
          </div>
        </aside>

        <div className="flex min-h-0 flex-col">
          <div className="flex items-center justify-between border-b border-neutral-200/80 px-5 py-4 dark:border-white/10">
            <div>
              <h2 className="text-base font-semibold">
                {step === 'site' ? 'New Project' : `Set up ${getTypeLabel(projectType)}`}
              </h2>
              <div className="mt-2 flex items-center gap-2">
                {(['site', 'setup'] as const).map((item, index) => (
                  <div
                    key={item}
                    className={clsx(
                      'flex items-center gap-2 rounded-full border px-2.5 py-1 text-xs font-medium',
                      step === item
                        ? 'border-cyan-200 bg-cyan-50 text-cyan-800 dark:border-cyan-400/25 dark:bg-cyan-400/10 dark:text-cyan-200'
                        : 'border-neutral-200 bg-neutral-50 text-neutral-500 dark:border-white/10 dark:bg-white/[0.04] dark:text-neutral-400'
                    )}
                  >
                    <span className="grid size-4 place-items-center rounded-full bg-current text-[10px]">
                      <span className="text-white dark:text-neutral-950">{index + 1}</span>
                    </span>
                    {item === 'site' ? 'Project' : 'Setup'}
                  </div>
                ))}
              </div>
            </div>
            <button
              type="button"
              onClick={onClose}
              className="rounded-lg p-1.5 text-neutral-400 transition hover:bg-neutral-100 hover:text-neutral-700 dark:hover:bg-white/10 dark:hover:text-neutral-200"
            >
              <X size={16} />
            </button>
          </div>

          <div className="flex min-h-0 flex-col gap-5 overflow-y-auto p-5">
            {step === 'site' ? (
              <>
                <div>
                  <label className={labelClass}>Project folder</label>
                  <button
                    type="button"
                    onClick={handlePickDirectory}
                    className={clsx(
                      'group flex w-full items-center gap-3 rounded-xl border border-dashed px-3 py-3 text-left text-sm transition',
                      directory
                        ? 'border-cyan-200 bg-cyan-50/60 text-neutral-900 dark:border-cyan-400/25 dark:bg-cyan-400/10 dark:text-neutral-100'
                        : 'border-neutral-300 bg-neutral-50/70 text-neutral-500 hover:border-cyan-200 hover:bg-cyan-50/50 dark:border-white/10 dark:bg-white/[0.04] dark:hover:border-cyan-400/25 dark:hover:bg-cyan-400/10'
                    )}
                  >
                    <span className="grid size-9 flex-shrink-0 place-items-center rounded-lg bg-white text-cyan-700 shadow-sm dark:bg-neutral-950/70 dark:text-cyan-300">
                      <FolderOpen size={17} />
                    </span>
                    <span className="min-w-0 flex-1">
                      <span className="block truncate font-medium">
                        {directory ?? 'Choose a folder…'}
                      </span>
                      <span className="mt-0.5 block text-xs text-neutral-500 dark:text-neutral-400">
                        This becomes the project root.
                      </span>
                    </span>
                    {directory && <Check size={16} className="text-cyan-700 dark:text-cyan-300" />}
                  </button>
                </div>

                <div>
                  <label className={labelClass}>Project name</label>
                  <input
                    type="text"
                    value={projectName}
                    onChange={(e) => setProjectName(e.target.value)}
                    placeholder="my-project"
                    className={fieldClass}
                  />
                  {trimmedName.length > 0 && !nameValid && (
                    <p className="mt-1.5 text-xs text-red-600 dark:text-red-400">
                      Use only letters, numbers, and hyphens — no spaces (e.g. &quot;
                      {slugifyProjectName(trimmedName) || 'my-project'}&quot;).
                    </p>
                  )}
                </div>

                <div>
                  <label className={labelClass}>Project type</label>
                  <div className="grid max-h-64 gap-2 overflow-y-auto pr-1 sm:grid-cols-2">
                    {PROJECT_TYPES.map((t) => {
                      const Icon = TYPE_ICONS[t.value] ?? Boxes
                      const isSelected = projectType === t.value

                      return (
                        <button
                          key={t.value}
                          type="button"
                          onClick={() => setProjectType(t.value)}
                          className={clsx(
                            'flex min-h-16 items-center gap-3 rounded-xl border px-3 py-3 text-left transition',
                            isSelected
                              ? 'border-cyan-300 bg-cyan-50 text-cyan-950 shadow-sm shadow-cyan-900/5 dark:border-cyan-400/30 dark:bg-cyan-400/10 dark:text-cyan-100'
                              : 'border-neutral-200 bg-white/70 hover:border-cyan-200 hover:bg-cyan-50/50 dark:border-white/10 dark:bg-white/[0.04] dark:hover:border-cyan-400/25 dark:hover:bg-cyan-400/10'
                          )}
                        >
                          <span
                            className={clsx(
                              'grid size-9 flex-shrink-0 place-items-center rounded-lg',
                              isSelected
                                ? 'bg-cyan-600 text-white dark:bg-cyan-300 dark:text-neutral-950'
                                : 'bg-neutral-100 text-neutral-500 dark:bg-neutral-950/70 dark:text-neutral-400'
                            )}
                          >
                            <Icon size={17} />
                          </span>
                          <span className="min-w-0 flex-1">
                            <span className="block truncate text-sm font-semibold">{t.label}</span>
                            <span className="mt-0.5 block text-xs text-neutral-500 dark:text-neutral-400">
                              {t.value ? 'Use DDEV type preset' : 'Let DDEV inspect it'}
                            </span>
                          </span>
                        </button>
                      )
                    })}
                  </div>
                </div>

                <div>
                  <label className={labelClass}>Docroot (optional)</label>
                  <input
                    type="text"
                    value={docroot}
                    onChange={(e) => setDocroot(e.target.value)}
                    placeholder="e.g. web, public — leave blank for project root"
                    className={fieldClass}
                  />
                </div>
              </>
            ) : projectType === 'wordpress' ? (
              <WordpressSetup
                ref={setupRef}
                projectName={projectName.trim()}
                onValidityChange={setSetupValid}
              />
            ) : (
              <GenericSetup
                ref={setupRef}
                projectName={projectName.trim()}
                onValidityChange={setSetupValid}
              />
            )}
          </div>

          <div className="flex items-center justify-between gap-3 border-t border-neutral-200/80 bg-neutral-50/80 p-4 dark:border-white/10 dark:bg-white/[0.03]">
            <button
              type="button"
              onClick={step === 'site' ? onClose : () => setStep('site')}
              className="inline-flex items-center gap-1.5 rounded-lg px-3 py-2 text-sm font-medium text-neutral-500 transition hover:bg-white hover:text-neutral-900 dark:hover:bg-white/10 dark:hover:text-neutral-100"
            >
              {step === 'site' ? null : <ArrowLeft size={14} />}
              {step === 'site' ? 'Cancel' : 'Go back'}
            </button>

            {step === 'site' ? (
              <button
                type="button"
                disabled={!canContinue}
                onClick={() => setStep('setup')}
                className="inline-flex items-center gap-1.5 rounded-lg bg-cyan-600 px-4 py-2 text-sm font-semibold text-white shadow-sm shadow-cyan-900/20 transition hover:bg-cyan-500 disabled:cursor-not-allowed disabled:opacity-40"
              >
                Continue
                <ArrowRight size={14} />
              </button>
            ) : (
              <button
                type="button"
                disabled={!canSubmit}
                onClick={handleSubmit}
                className="inline-flex items-center gap-1.5 rounded-lg bg-cyan-600 px-4 py-2 text-sm font-semibold text-white shadow-sm shadow-cyan-900/20 transition hover:bg-cyan-500 disabled:cursor-not-allowed disabled:opacity-40"
              >
                {isSubmitting ? 'Creating…' : 'Add Site'}
              </button>
            )}
          </div>
        </div>
      </div>
    </div>
  )
}
