/**
 * CreateTenantPage — operator-facing SME tenant create form (issue
 * #828, parent epic #825 / Multi-domain Sovereign).
 *
 * The page extends the #804 SME tenant pipeline with operator choice
 * over which parent domain hosts the new SME's free subdomain. A
 * Sovereign at signup brings N parent domains; one is `role: primary`
 * (host of `console.<sovereign>`) and zero-or-more are `role:
 * sme-pool` (offered to SMEs). When the operator picks
 * domain_mode=free-subdomain they choose one sme-pool parent from the
 * dropdown; the resulting URL is `console.<tenant>.<chosen-parent>`.
 *
 * For domain_mode=byo the operator types the SME's own apex (e.g.
 * "acme.com") and the back end validates the CNAME points at any
 * parent in the pool.
 *
 * Per docs/INVIOLABLE-PRINCIPLES.md:
 *   #2 (never compromise on quality): the page paints partial state
 *      after submit, surfacing the orchestrator's per-step badges so
 *      the operator knows exactly which gate failed.
 *   #4 (never hardcode): every URL flows through apiUrl() in
 *      sme.api.ts; the parent-domain pool is wholly data-driven from
 *      the back end.
 */

import { useEffect, useState } from 'react'
import { Globe, ServerCog, Plus } from 'lucide-react'
import {
  createSMETenant,
  isParentDomainReady,
  listSovereignParentDomains,
  type SMETenant,
  type SMETenantDomainMode,
  type SovereignParentDomain,
} from './sme.api'

export interface CreateTenantPageProps {
  /** Test seam — supplies the parent-domain pool synchronously. */
  initialParentDomains?: SovereignParentDomain[]
  /** Test seam — disables the parent-domain fetch effect entirely. */
  disableFetch?: boolean
}

export function CreateTenantPage({
  initialParentDomains,
  disableFetch = false,
}: CreateTenantPageProps = {}) {
  const [pool, setPool] = useState<SovereignParentDomain[]>(
    initialParentDomains?.filter((p) => p.role === 'sme-pool') ?? [],
  )
  const [poolLoading, setPoolLoading] = useState<boolean>(
    !initialParentDomains && !disableFetch,
  )
  const [poolError, setPoolError] = useState<string | null>(null)

  const [subdomain, setSubdomain] = useState<string>('')
  const [companyName, setCompanyName] = useState<string>('')
  const [adminEmail, setAdminEmail] = useState<string>('')
  const [domainMode, setDomainMode] =
    useState<SMETenantDomainMode>('free-subdomain')
  const [parentDomain, setParentDomain] = useState<string>('')
  const [byoDomain, setByoDomain] = useState<string>('')

  const [submitting, setSubmitting] = useState<boolean>(false)
  const [submitError, setSubmitError] = useState<string | null>(null)
  const [created, setCreated] = useState<SMETenant | null>(null)

  useEffect(() => {
    if (disableFetch) return
    let cancelled = false
    setPoolLoading(true)
    listSovereignParentDomains('sme-pool')
      .then((items) => {
        if (cancelled) return
        // Filter to sme-pool entries only. The back end's
        // /sovereign/parent-domains endpoint accepts ?role= but also
        // surfaces the implicit primary; the SME create form is only
        // concerned with role=sme-pool entries.
        const smePool = items.filter((p) => p.role === 'sme-pool')
        setPool(smePool)
        // Default the parent-domain dropdown to the first NS-flip-ready
        // entry. Falls back to the first entry when none are ready (the
        // back end will return 503 Retry-After in that case).
        const firstReady =
          smePool.find((p) => isParentDomainReady(p)) ?? smePool[0]
        if (firstReady) setParentDomain(firstReady.name)
        setPoolError(null)
      })
      .catch((err: Error) => {
        if (!cancelled) setPoolError(err.message)
      })
      .finally(() => {
        if (!cancelled) setPoolLoading(false)
      })
    return () => {
      cancelled = true
    }
  }, [disableFetch])

  // Pre-select the first parent on initial render when initialParentDomains
  // is supplied (the test seam path).
  useEffect(() => {
    if (initialParentDomains && initialParentDomains.length > 0 && !parentDomain) {
      const smePool = initialParentDomains.filter((p) => p.role === 'sme-pool')
      const firstReady =
        smePool.find((p) => isParentDomainReady(p)) ?? smePool[0]
      if (firstReady) setParentDomain(firstReady.name)
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [initialParentDomains])

  const consolePreview =
    domainMode === 'free-subdomain'
      ? subdomain && parentDomain
        ? `console.${subdomain}.${parentDomain}`
        : ''
      : byoDomain
        ? `console.${byoDomain}`
        : ''

  async function onSubmit(e: React.FormEvent) {
    e.preventDefault()
    setSubmitError(null)
    setCreated(null)
    setSubmitting(true)
    try {
      const result = await createSMETenant({
        subdomain: subdomain.trim().toLowerCase(),
        admin_email: adminEmail.trim(),
        company_name: companyName.trim(),
        domain_mode: domainMode,
        parent_domain:
          domainMode === 'free-subdomain'
            ? parentDomain.trim().toLowerCase()
            : undefined,
        byo_domain:
          domainMode === 'byo' ? byoDomain.trim().toLowerCase() : undefined,
      })
      setCreated(result)
    } catch (err) {
      setSubmitError((err as Error).message)
    } finally {
      setSubmitting(false)
    }
  }

  return (
    <div data-testid="sme-create-tenant-page" className="px-6 py-4">
      <div className="mb-4 flex items-center justify-between">
        <div>
          <h1 className="text-xl font-semibold text-[var(--color-text-strong)]">
            Onboard SME Tenant
          </h1>
          <p className="text-sm text-[var(--color-text-dim)]">
            Provisions a per-SME vCluster, blueprint charts, DNS, certs,
            Keycloak realm, and tenant-registry entry. Choose a free
            subdomain under one of this Sovereign&apos;s parent domains
            or bring an SME-owned apex.
          </p>
        </div>
      </div>

      {poolError && (
        <div
          data-testid="sme-create-tenant-pool-error"
          className="mb-4 rounded-md border border-[var(--color-danger)] bg-[var(--color-danger-soft)] p-3 text-sm text-[var(--color-danger)]"
        >
          Failed to load parent-domain pool: {poolError}
        </div>
      )}

      <form
        data-testid="sme-create-tenant-form"
        onSubmit={onSubmit}
        className="grid max-w-2xl gap-4 rounded-md border border-[var(--color-border)] bg-[var(--color-surface)] p-5"
      >
        <label className="grid gap-1 text-sm">
          <span className="text-[var(--color-text-dim)]">SME tenant slug</span>
          <input
            data-testid="sme-create-tenant-subdomain"
            type="text"
            required
            pattern="[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?"
            value={subdomain}
            onChange={(e) => setSubdomain(e.target.value)}
            placeholder="acme"
            className="rounded-md border border-[var(--color-border)] bg-[var(--color-input)] px-3 py-2 text-sm"
          />
          <span className="text-xs text-[var(--color-text-dim)]">
            Used in resource names (vCluster, namespace) and the URL when
            the tenant picks free-subdomain mode.
          </span>
        </label>

        <label className="grid gap-1 text-sm">
          <span className="text-[var(--color-text-dim)]">Company name</span>
          <input
            data-testid="sme-create-tenant-company"
            type="text"
            value={companyName}
            onChange={(e) => setCompanyName(e.target.value)}
            placeholder="Acme Corp"
            className="rounded-md border border-[var(--color-border)] bg-[var(--color-input)] px-3 py-2 text-sm"
          />
        </label>

        <label className="grid gap-1 text-sm">
          <span className="text-[var(--color-text-dim)]">Admin email</span>
          <input
            data-testid="sme-create-tenant-email"
            type="email"
            required
            value={adminEmail}
            onChange={(e) => setAdminEmail(e.target.value)}
            placeholder="admin@acme.com"
            className="rounded-md border border-[var(--color-border)] bg-[var(--color-input)] px-3 py-2 text-sm"
          />
        </label>

        <fieldset className="grid gap-2">
          <legend className="text-sm text-[var(--color-text-dim)]">
            Domain mode
          </legend>
          <label
            className="flex cursor-pointer items-start gap-3 rounded-md border border-[var(--color-border)] p-3 hover:bg-[var(--color-surface-strong,_rgba(255,255,255,0.04))]"
            data-testid="sme-create-tenant-mode-free"
          >
            <input
              type="radio"
              name="domain-mode"
              value="free-subdomain"
              checked={domainMode === 'free-subdomain'}
              onChange={() => setDomainMode('free-subdomain')}
              className="mt-1"
            />
            <span className="grid gap-1">
              <span className="flex items-center gap-2 text-sm font-medium">
                <Globe className="h-4 w-4" />
                Free subdomain on a Sovereign parent
              </span>
              <span className="text-xs text-[var(--color-text-dim)]">
                Console URL becomes
                <code className="ml-1 rounded bg-[var(--color-input)] px-1">
                  console.&lt;slug&gt;.&lt;parent&gt;
                </code>
                . Pick the parent below.
              </span>
            </span>
          </label>

          <label
            className="flex cursor-pointer items-start gap-3 rounded-md border border-[var(--color-border)] p-3 hover:bg-[var(--color-surface-strong,_rgba(255,255,255,0.04))]"
            data-testid="sme-create-tenant-mode-byo"
          >
            <input
              type="radio"
              name="domain-mode"
              value="byo"
              checked={domainMode === 'byo'}
              onChange={() => setDomainMode('byo')}
              className="mt-1"
            />
            <span className="grid gap-1">
              <span className="flex items-center gap-2 text-sm font-medium">
                <ServerCog className="h-4 w-4" />
                Bring your own domain
              </span>
              <span className="text-xs text-[var(--color-text-dim)]">
                The SME owns an apex (e.g.
                <code className="mx-1 rounded bg-[var(--color-input)] px-1">
                  acme.com
                </code>
                ) and CNAMEs
                <code className="mx-1 rounded bg-[var(--color-input)] px-1">
                  console.acme.com
                </code>
                at any parent in this Sovereign&apos;s pool.
              </span>
            </span>
          </label>
        </fieldset>

        {domainMode === 'free-subdomain' && (
          <label className="grid gap-1 text-sm" data-testid="sme-create-tenant-parent-row">
            <span className="text-[var(--color-text-dim)]">Parent domain</span>
            <select
              data-testid="sme-create-tenant-parent-select"
              value={parentDomain}
              onChange={(e) => setParentDomain(e.target.value)}
              disabled={poolLoading || pool.length === 0}
              className="rounded-md border border-[var(--color-border)] bg-[var(--color-input)] px-3 py-2 text-sm"
              required
            >
              {poolLoading && <option value="">Loading…</option>}
              {!poolLoading && pool.length === 0 && (
                <option value="">
                  No sme-pool parents available — contact the Sovereign
                  operator
                </option>
              )}
              {pool.map((p) => {
                const ready = isParentDomainReady(p)
                return (
                  <option
                    key={p.name}
                    value={p.name}
                    disabled={!ready}
                    data-testid={`sme-create-tenant-parent-option-${p.name}`}
                  >
                    {p.name}
                    {ready ? '' : ` (${p.flipStatus.replace('-', ' ')})`}
                  </option>
                )
              })}
            </select>
          </label>
        )}

        {domainMode === 'byo' && (
          <label className="grid gap-1 text-sm">
            <span className="text-[var(--color-text-dim)]">SME apex domain</span>
            <input
              data-testid="sme-create-tenant-byo"
              type="text"
              required
              value={byoDomain}
              onChange={(e) => setByoDomain(e.target.value)}
              placeholder="acme.com"
              className="rounded-md border border-[var(--color-border)] bg-[var(--color-input)] px-3 py-2 text-sm"
            />
            <span className="text-xs text-[var(--color-text-dim)]">
              Ask the SME to add a CNAME from
              <code className="mx-1 rounded bg-[var(--color-input)] px-1">
                console.{byoDomain || '<their-domain>'}
              </code>
              to any of this Sovereign&apos;s parent domains in the pool
              before submitting; the orchestrator validates the CNAME
              and refuses to advance until it points here.
            </span>
          </label>
        )}

        <div className="rounded-md border border-dashed border-[var(--color-border)] bg-[var(--color-input)] p-3 text-sm">
          <span className="text-[var(--color-text-dim)]">Console URL preview: </span>
          <code data-testid="sme-create-tenant-url-preview" className="font-mono text-[var(--color-text-strong)]">
            {consolePreview || '—'}
          </code>
        </div>

        {submitError && (
          <div
            data-testid="sme-create-tenant-submit-error"
            className="rounded-md border border-[var(--color-danger)] bg-[var(--color-danger-soft)] p-3 text-sm text-[var(--color-danger)]"
          >
            {submitError}
          </div>
        )}

        <button
          type="submit"
          disabled={submitting}
          data-testid="sme-create-tenant-submit"
          className="inline-flex items-center justify-center gap-2 rounded-md bg-[var(--color-accent)] px-4 py-2 text-sm font-medium text-white disabled:opacity-50"
        >
          <Plus className="h-4 w-4" />
          {submitting ? 'Provisioning…' : 'Onboard tenant'}
        </button>
      </form>

      {created && (
        <div
          data-testid="sme-create-tenant-result"
          className="mt-6 max-w-2xl rounded-md border border-[var(--color-border)] bg-[var(--color-surface)] p-4"
        >
          <div className="mb-3 text-sm font-medium">
            Provisioning {created.subdomain}
          </div>
          <dl className="mb-3 grid grid-cols-2 gap-2 text-xs">
            <dt className="text-[var(--color-text-dim)]">Console URL</dt>
            <dd className="font-mono">
              <a
                data-testid="sme-create-tenant-result-console-href"
                href={`https://${created.console_host}`}
                target="_blank"
                rel="noopener noreferrer"
                className="text-[var(--color-accent)] hover:underline"
              >
                {created.console_host}
              </a>
            </dd>
            {created.parent_domain && (
              <>
                <dt className="text-[var(--color-text-dim)]">Parent domain</dt>
                <dd
                  className="font-mono"
                  data-testid="sme-create-tenant-result-parent"
                >
                  {created.parent_domain}
                </dd>
              </>
            )}
            <dt className="text-[var(--color-text-dim)]">Tenant ID</dt>
            <dd className="font-mono">{created.sme_tenant_id}</dd>
          </dl>
          <TenantSteps steps={created.steps} />
          {created.last_error && (
            <div className="mt-2 text-xs text-[var(--color-danger)]">
              {created.last_error}
            </div>
          )}
        </div>
      )}
    </div>
  )
}

function TenantSteps({
  steps,
}: {
  steps: SMETenant['steps']
}) {
  const items: { key: keyof SMETenant['steps']; label: string }[] = [
    { key: 'vcluster', label: 'vCluster' },
    { key: 'bp_charts', label: 'Charts' },
    { key: 'dns', label: 'DNS' },
    { key: 'certs', label: 'Certs' },
    { key: 'keycloak_clients', label: 'Keycloak' },
    { key: 'registry', label: 'Registry' },
  ]
  return (
    <div className="flex flex-wrap items-center gap-2">
      {items.map((s, i) => {
        const state = steps[s.key]
        const cls =
          state === 'done'
            ? 'bg-[var(--color-success,#16a34a)]'
            : state === 'failed'
              ? 'bg-[var(--color-danger,#dc2626)]'
              : 'bg-[var(--color-text-dim,#9ca3af)]'
        return (
          <span key={s.key} className="flex items-center gap-1 text-xs">
            <span
              className={`inline-block h-2 w-2 rounded-full ${cls}`}
              data-testid={`sme-create-tenant-step-${s.key}-${state}`}
              aria-label={`${s.label}: ${state}`}
            />
            <span>{s.label}</span>
            {i < items.length - 1 && (
              <span className="text-[var(--color-text-dim)]">→</span>
            )}
          </span>
        )
      })}
    </div>
  )
}
