'use client'

/**
 * DomainsSettingsPage — shared composer for /settings/domains (startsim-o7s).
 *
 * Renders the list of EmailDomainClaim rows for the active company, the
 * add-domain form, and the per-card verify-DNS / verify-email actions.
 * Admin gating is read off useMembership; only admins see Add + Revoke.
 */

import * as React from 'react'
import { useDomainClaims, useMembershipFromApi } from '@startsimpli/auth'
import type { DomainClaimRow } from '@startsimpli/auth'
import { DomainClaimCard } from '../DomainClaimCard'
import type { DomainClaimLite } from '../types'
import {
  DOMAINS_SETTINGS_PAGE_DEFAULTS,
  type DomainsSettingsPageClassNames,
} from './domains-settings-page-default-class-names'
import type { DomainsSettingsApi } from './types'

export interface DomainsSettingsPageProps {
  /** The @startsimpli/api client. */
  api: DomainsSettingsApi
  /** Per-slot className overrides. */
  classNames?: DomainsSettingsPageClassNames
  /**
   * Optional override for the company id. Defaults to the company resolved
   * by useMembership() on the current user.
   */
  companyId?: string
  /** Back link href. Defaults to '/'. */
  backHref?: string
  /** Back link text. Defaults to '← Back'. */
  backLabel?: string
  /** Title. Defaults to 'Email domains'. */
  title?: string
}

/** Loose domain pattern — backend is the canonical validator. */
const DOMAIN_RE = /^[a-z0-9.-]+\.[a-z]{2,}$/i

function toClaimLite(c: DomainClaimRow): DomainClaimLite {
  return {
    id: c.id,
    companyId: c.companyId,
    domain: c.domain,
    verified: c.verified,
    verificationMethod: c.verificationMethod,
    verificationToken: c.verificationToken,
    verifiedAt: c.verifiedAt,
    createdAt: c.createdAt,
  }
}

export function DomainsSettingsPage({
  api,
  classNames,
  companyId: companyIdProp,
  backHref = '/',
  backLabel = '← Back',
  title = 'Email domains',
}: DomainsSettingsPageProps) {
  const cls = { ...DOMAINS_SETTINGS_PAGE_DEFAULTS, ...(classNames ?? {}) }
  const membership = useMembershipFromApi(api)
  const { company, isAdmin, isLoading: membershipLoading } = membership
  const companyId = companyIdProp ?? company?.id

  const claims = useDomainClaims({
    fetchClaims: async () => {
      if (!companyId) return []
      const res = await api.domainClaims.list({ companyId })
      return res.results.map((c) => ({
        id: c.id,
        companyId: c.companyId,
        domain: c.domain,
        verified: c.verified,
        verificationMethod: c.verificationMethod,
        verificationToken: c.verificationToken,
        verifiedAt: c.verifiedAt,
        createdAt: c.createdAt,
      }))
    },
    createClaim: async ({ companyId: cid, domain }) => {
      const c = await api.domainClaims.create({ companyId: cid, domain })
      return {
        id: c.id,
        companyId: c.companyId,
        domain: c.domain,
        verified: c.verified,
        verificationMethod: c.verificationMethod,
        verificationToken: c.verificationToken,
        verifiedAt: c.verifiedAt,
        createdAt: c.createdAt,
      }
    },
    verifyDns: async (id) => {
      const c = await api.domainClaims.verifyDns(id)
      return {
        id: c.id,
        companyId: c.companyId,
        domain: c.domain,
        verified: c.verified,
        verificationMethod: c.verificationMethod,
        verificationToken: c.verificationToken,
        verifiedAt: c.verifiedAt,
        createdAt: c.createdAt,
      }
    },
    initiateEmailVerification: (id) => api.domainClaims.verifyEmailInitiate(id),
    submitEmailCode: async (id, code) => {
      const c = await api.domainClaims.verifyEmailCode(id, code)
      return {
        id: c.id,
        companyId: c.companyId,
        domain: c.domain,
        verified: c.verified,
        verificationMethod: c.verificationMethod,
        verificationToken: c.verificationToken,
        verifiedAt: c.verifiedAt,
        createdAt: c.createdAt,
      }
    },
    revokeClaim: (id) => api.domainClaims.revoke(id),
    autoFetch: !!companyId,
  })

  const [showAdd, setShowAdd] = React.useState(false)
  const [domain, setDomain] = React.useState('')
  const [addError, setAddError] = React.useState('')
  const [submitting, setSubmitting] = React.useState(false)

  async function handleAdd(e: React.FormEvent) {
    e.preventDefault()
    setAddError('')
    const clean = domain.trim().toLowerCase()
    if (!clean) {
      setAddError('Domain is required')
      return
    }
    if (!DOMAIN_RE.test(clean)) {
      setAddError('Enter a valid domain like "example.com"')
      return
    }
    if (!companyId) {
      setAddError('No company in scope')
      return
    }
    setSubmitting(true)
    try {
      await claims.create({ companyId, domain: clean })
      setDomain('')
      setShowAdd(false)
    } catch (err) {
      setAddError(err instanceof Error ? err.message : 'Could not add domain')
    } finally {
      setSubmitting(false)
    }
  }

  if (membershipLoading) {
    return <p className={cls.loadingText}>Loading…</p>
  }

  if (!companyId) {
    return (
      <div className={cls.root}>
        <a href={backHref} className={cls.backLink}>
          {backLabel}
        </a>
        <h1 className={cls.title}>{title}</h1>
        <p className={cls.subtitle}>
          You need a company to claim domains. Accept a team invitation first.
        </p>
      </div>
    )
  }

  return (
    <div className={cls.root}>
      <div className={cls.header}>
        <a href={backHref} className={cls.backLink}>
          {backLabel}
        </a>
        <div className={cls.titleRow}>
          <div>
            <h1 className={cls.title}>{title}</h1>
            <p className={cls.subtitle}>
              Verified domains auto-join new signups to your team. Add a domain
              you own.
            </p>
          </div>
          {isAdmin && !showAdd && (
            <button
              type="button"
              onClick={() => setShowAdd(true)}
              className={cls.primaryButton}
            >
              + Add domain
            </button>
          )}
        </div>
      </div>

      {showAdd && (
        <form onSubmit={handleAdd} className={cls.formCard}>
          <label htmlFor="domain" className={cls.label}>
            Domain
          </label>
          <input
            id="domain"
            type="text"
            value={domain}
            onChange={(e) => setDomain(e.target.value)}
            placeholder="acme.com"
            className={cls.input}
            disabled={submitting}
            autoFocus
          />
          {addError && <p className={cls.errorText}>{addError}</p>}
          <div className={cls.formActions}>
            <button type="submit" disabled={submitting} className={cls.primaryButton}>
              {submitting ? 'Adding…' : 'Add domain'}
            </button>
            <button
              type="button"
              onClick={() => {
                setShowAdd(false)
                setDomain('')
                setAddError('')
              }}
              className={cls.cancelButton}
            >
              Cancel
            </button>
          </div>
        </form>
      )}

      {claims.isLoading ? (
        <p className={cls.loadingText}>Loading domains…</p>
      ) : claims.error ? (
        <div className="space-y-2">
          <p className={cls.errorText}>Could not load domains.</p>
          <button
            type="button"
            onClick={() => void claims.refresh()}
            className={cls.retryButton}
          >
            Retry
          </button>
        </div>
      ) : claims.claims.length === 0 ? (
        <div className={cls.emptyState}>
          <p className={cls.emptyText}>
            No domains claimed yet. Add one to auto-join new signups from your
            team&apos;s email domain.
          </p>
        </div>
      ) : (
        <div className={cls.list}>
          {claims.claims.map((c) => (
            <DomainClaimCard
              key={c.id}
              claim={toClaimLite(c)}
              classNames={cls.claimCard}
              onVerifyDns={async () => {
                await claims.verifyDns(c.id)
              }}
              onInitiateEmail={async () => {
                await claims.initiateEmail(c.id)
              }}
              onVerifyEmail={async (_claim, code) => {
                await claims.verifyEmail(c.id, code)
              }}
              onRevoke={
                isAdmin
                  ? async () => {
                      await claims.revoke(c.id)
                    }
                  : undefined
              }
            />
          ))}
        </div>
      )}
    </div>
  )
}
