#!/usr/bin/env python3
"""Patch App.jsx Spec 037 — multi-conta CF + BYO."""
from pathlib import Path

APP = Path("/opt/ligbox-wizard/frontend/src/App.jsx")
text = APP.read_text(encoding="utf-8")

if "chooseByoDns" in text and "dnsResolve" in text:
    print("App.jsx already patched")
    raise SystemExit(0)

text = text.replace(
    "  choosePortalDns: false,\n  chooseExternalDns: false,",
    "  choosePortalDns: false,\n  chooseByoDns: false,\n  chooseExternalDns: false,",
)

text = text.replace(
    "  const [showAdvancedDns, setShowAdvancedDns] = useState(false)",
    "  const [showAdvancedDns, setShowAdvancedDns] = useState(false)\n  const [dnsResolve, setDnsResolve] = useState(null)\n  const [byoToken, setByoToken] = useState('')",
)

OLD_CHOOSE_PORTAL = """  async function choosePortalDns() {
    setDnsChoice('portal')
    setError(null)
    startBusy('dns_zone')
    try {
      const guide = await api('/onboarding/dns/cloudflare/provision-zone', {
        method: 'POST',
        body: JSON.stringify({ domain }),
      })
      setPortalGuide(guide)
      const cf = guide.status || (await refreshCfStatus())
      setCfStatus(cf)
      markActionDone('choosePortalDns')
      if (guide.verification) {
        setVerification(guide.verification)
        setResult({ type: 'dns', data: { verification: guide.verification } })
        markActionDone('verifyZone')
        markActionDone('applyPortalDns')
      } else if (cf?.zone_in_account && cf?.can_apply_mail_records) {
        markActionDone('verifyZone')
        const data = await api('/onboarding/dns/cloudflare/apply', {
          method: 'POST',
          body: JSON.stringify({
            domain,
            mail_aliases: sanitizeMailAliases(mailAliasInputs, domain),
          }),
        })
        setVerification(data.verification)
        setResult({ type: 'dns', data })
        markActionDone('applyPortalDns')
      }
    } catch (e) {
      setError(e.message)
      setDnsChoice(null)
      setActionsDone((prev) => ({ ...prev, choosePortalDns: false }))
    } finally {
      stopBusy()
    }
  }"""

NEW_CHOOSE_PORTAL = """  async function choosePortalDns() {
    setDnsChoice('portal')
    setError(null)
    startBusy('dns_zone')
    try {
      const resolved = dnsResolve || (await api(`/onboarding/dns/resolve/${domain}`))
      setDnsResolve(resolved)
      if (!resolved.matched) {
        throw new Error(
          resolved.message ||
            'Domínio não está nas contas Ligbox (ligit, itecnologys, ibytera).',
        )
      }
      const cf = await refreshCfStatus()
      setCfStatus(cf)
      markActionDone('choosePortalDns')
      markActionDone('verifyZone')
      const data = await api('/onboarding/dns/cloudflare/apply', {
        method: 'POST',
        body: JSON.stringify({
          domain,
          zone_id: resolved.zone_id,
          mail_aliases: sanitizeMailAliases(mailAliasInputs, domain),
        }),
      })
      setPortalGuide({
        message: resolved.message,
        nameservers: cf?.nameservers || [],
        status: cf,
        ligbox_account_id: resolved.account_id,
      })
      setVerification(data.verification)
      setResult({ type: 'dns', data })
      markActionDone('applyPortalDns')
    } catch (e) {
      setError(e.message)
      setDnsChoice(null)
      setActionsDone((prev) => ({ ...prev, choosePortalDns: false }))
    } finally {
      stopBusy()
    }
  }

  async function chooseByoDns() {
    setDnsChoice('byo')
    setError(null)
    markActionDone('chooseByoDns')
    setShowAdvancedDns(true)
  }

  async function connectByoAndApply() {
    const token = byoToken.trim()
    if (!token) {
      setError('Cole o API Token da sua conta Cloudflare (DNS Edit na zona).')
      return
    }
    setError(null)
    startBusy('dns_byo')
    try {
      const conn = await api('/onboarding/dns/cloudflare/connect-custom', {
        method: 'POST',
        body: JSON.stringify({ domain, api_token: token }),
      })
      setDnsResolve({ ...conn, matched: true, dns_mode: 'byo_cloudflare' })
      markActionDone('chooseByoDns')
      const data = await api('/onboarding/dns/cloudflare/apply', {
        method: 'POST',
        body: JSON.stringify({
          domain,
          zone_id: conn.zone_id,
          mail_aliases: sanitizeMailAliases(mailAliasInputs, domain),
        }),
      })
      setVerification(data.verification)
      setResult({ type: 'dns', data })
      markActionDone('applyPortalDns')
    } catch (e) {
      setError(e.message)
      setActionsDone((prev) => ({ ...prev, chooseByoDns: false, applyPortalDns: false }))
    } finally {
      stopBusy()
    }
  }"""

text = text.replace(OLD_CHOOSE_PORTAL, NEW_CHOOSE_PORTAL)

text = text.replace(
    """  const DNS_ACTION_KEYS = {
    choosePortalDns: false,
    chooseExternalDns: false,""",
    """  const DNS_ACTION_KEYS = {
    choosePortalDns: false,
    chooseByoDns: false,
    chooseExternalDns: false,""",
)

text = text.replace(
    "    if (dnsChoice === 'portal') markActionDone('choosePortalDns')\n    if (dnsChoice === 'external') markActionDone('chooseExternalDns')",
    "    if (dnsChoice === 'portal') markActionDone('choosePortalDns')\n    if (dnsChoice === 'byo') markActionDone('chooseByoDns')\n    if (dnsChoice === 'external') markActionDone('chooseExternalDns')",
)

text = text.replace(
    "      const data = await api(`/onboarding/dns/instructions/${dom}`)\n      setInstructions(data)\n      setCfStatus(data.cloudflare)",
    "      const data = await api(`/onboarding/dns/instructions/${dom}`)\n      setInstructions(data)\n      setCfStatus(data.cloudflare)\n      setDnsResolve(data.resolve || null)",
)

text = text.replace(
    "    if (step !== 1 || !instructions || showAdvancedDns || dnsChoice === 'external' || asmMode) return",
    "    if (step !== 1 || !instructions || showAdvancedDns || dnsChoice === 'external' || dnsChoice === 'byo' || asmMode) return",
)

text = text.replace(
    "    if (portalDnsApplied || loading || autoDnsAttempted.current) return\n    autoDnsAttempted.current = true",
    "    if (portalDnsApplied || loading || autoDnsAttempted.current) return\n    const resolve = instructions?.resolve || dnsResolve\n    if (resolve && !resolve.matched) return\n    autoDnsAttempted.current = true",
)

text = text.replace(
    "          dns_mode: dnsChoice === 'portal' ? 'Cloudflare Ligbox' : 'Provedor externo',",
    "          dns_mode:\n            dnsChoice === 'portal'\n              ? dnsResolve?.dns_mode || cfStatus?.dns_mode || 'ligbox_cf'\n              : dnsChoice === 'byo'\n                ? 'byo_cloudflare'\n                : 'external_registrar',",
)

# Advanced mode choice grid — add BYO button and update portal label
OLD_GRID = """                      <ActionDoneButton
                        block
                        done={actionsDone.choosePortalDns}
                        label="Trazer DNS para o portal"
                        hint="Zona DNS Ligbox + apontamentos de email."
                        disabled={loading || actionsDone.chooseExternalDns}
                        busy={loading && !actionsDone.choosePortalDns}
                        onClick={choosePortalDns}
                        attentionId="choosePortalDns"
                      />
                      <ActionDoneButton
                        block
                        secondary
                        done={actionsDone.chooseExternalDns}
                        label="Manter no provedor atual"
                        hint="Apontamentos manuais no provedor atual."
                        disabled={loading || actionsDone.choosePortalDns}
                        busy={loading && !actionsDone.chooseExternalDns}
                        onClick={chooseExternalDns}
                        attentionId="chooseExternalDns"
                      />"""

NEW_GRID = """                      <ActionDoneButton
                        block
                        done={actionsDone.choosePortalDns}
                        label={
                          dnsResolve?.matched
                            ? `Cloudflare Ligbox (${dnsResolve.account_id})`
                            : 'Cloudflare Ligbox (indisponível)'
                        }
                        hint={
                          dnsResolve?.matched
                            ? dnsResolve.message
                            : 'Domínio não está nas contas ligit / itecnologys / ibytera.'
                        }
                        disabled={
                          loading ||
                          actionsDone.chooseExternalDns ||
                          actionsDone.chooseByoDns ||
                          !dnsResolve?.matched
                        }
                        busy={loading && !actionsDone.choosePortalDns}
                        onClick={choosePortalDns}
                        attentionId="choosePortalDns"
                      />
                      <ActionDoneButton
                        block
                        secondary
                        done={actionsDone.chooseByoDns}
                        label="Minha conta Cloudflare"
                        hint="API Token com DNS Edit na zona do domínio."
                        disabled={loading || actionsDone.choosePortalDns || actionsDone.chooseExternalDns}
                        busy={loading && !actionsDone.chooseByoDns}
                        onClick={chooseByoDns}
                        attentionId="chooseByoDns"
                      />
                      <ActionDoneButton
                        block
                        secondary
                        done={actionsDone.chooseExternalDns}
                        label="Registrador / DNS externo"
                        hint="Apontamentos manuais (domínio a registar ou NS noutro sítio)."
                        disabled={loading || actionsDone.choosePortalDns || actionsDone.chooseByoDns}
                        busy={loading && !actionsDone.chooseExternalDns}
                        onClick={chooseExternalDns}
                        attentionId="chooseExternalDns"
                      />"""

text = text.replace(OLD_GRID, NEW_GRID)

BYO_PANEL = """
              {dnsChoice === 'byo' && showAdvancedDns && (
                <div className="message" style={{ background: '#f4f0ff', color: '#3d2d6b' }}>
                  <strong>Sua conta Cloudflare (BYO)</strong>
                  <p className="sub" style={{ margin: '0.35rem 0 0' }}>
                    Crie um API Token com permissão <strong>Zone DNS Edit</strong> apenas na zona{' '}
                    <code>{domain}</code>.
                  </p>
                  <label className="sub" style={{ display: 'block', marginTop: '0.75rem' }}>
                    API Token Cloudflare
                    <input
                      type="password"
                      className="input"
                      style={{ marginTop: '0.35rem', width: '100%' }}
                      value={byoToken}
                      onChange={(e) => setByoToken(e.target.value)}
                      autoComplete="off"
                    />
                  </label>
                  <div className="actions" style={{ marginTop: '0.75rem' }}>
                    <ActionDoneButton
                      done={portalDnsApplied}
                      label="Validar token e aplicar apontamentos"
                      disabled={loading || portalDnsApplied || !byoToken.trim()}
                      busy={loading && !portalDnsApplied}
                      onClick={connectByoAndApply}
                      attentionId="applyPortalDns"
                    />
                  </div>
                </div>
              )}

"""

if "dnsChoice === 'byo'" not in text:
    text = text.replace(
        "              {dnsChoice === 'external' && showAdvancedDns && (",
        BYO_PANEL + "              {dnsChoice === 'external' && showAdvancedDns && (",
    )

# Simple mode message when not matched
SIMPLE_MSG = """
                  {!dnsResolve?.matched && !portalDnsApplied && (
                    <WizardStatusPanel variant="warn" icon={ShieldCheck} title="Escolha como apontar o DNS">
                      <p>
                        Este domínio não está nas contas Cloudflare Ligbox. Use{' '}
                        <strong>Minha conta Cloudflare</strong> ou{' '}
                        <strong>Registrador / DNS externo</strong> (botão técnico abaixo).
                      </p>
                    </WizardStatusPanel>
                  )}

"""

if "não está nas contas Cloudflare Ligbox" not in text:
    text = text.replace(
        "                  {portalDnsApplied && (",
        SIMPLE_MSG + "                  {portalDnsApplied && (",
    )

APP.write_text(text, encoding="utf-8")
print("App.jsx patched OK")
