import { useEffect, useState } from 'react'

// ---------------------------------------------------------------------------
// tiny fetch helper for the /license/api JSON endpoints — same shape as the
// installer's own api<T>() (resources/js/react/installer/InstallerApp.tsx),
// duplicated rather than imported because this is a separate Vite entry with
// no shared runtime with that bundle.
// ---------------------------------------------------------------------------
async function api<T = unknown>(path: string, opts?: { method?: string; body?: unknown }): Promise<T> {
  const res = await fetch('/license/api' + path, {
    method: opts?.method ?? 'GET',
    headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
    body: opts?.body ? JSON.stringify(opts.body) : undefined,
  })
  const json = await res.json().catch(() => ({}))
  if (!res.ok) throw new Error(errorMessage(json))
  return json.data as T
}

function errorMessage(json: unknown): string {
  const body = (json ?? {}) as { errors?: unknown; message?: unknown }
  const errors = body.errors

  if (Array.isArray(errors)) {
    const first = errors.find((e) => typeof (e as { message?: unknown })?.message === 'string')
    if (first) return (first as { message: string }).message
  }
  if (errors && typeof errors === 'object') {
    const lines = Object.values(errors as Record<string, unknown>)
      .flat()
      .filter((line): line is string => typeof line === 'string' && line.length > 0)
    if (lines.length) return lines.join(' ')
  }
  if (typeof body.message === 'string' && body.message) return body.message
  return 'That could not be verified. Please check it and try again.'
}

interface LicenseStatus {
  status: 'active' | 'invalid' | null
  license_source: 'envato' | 'dodo' | null
  purchase_code_masked: string | null
  dodo_license_key_masked: string | null
  domain: string | null
  license_type: string | null
  purchased_on: string | null
  supported_until: string | null
  last_verified_at: string | null
  /** Only present on GET /status (the public view), not on the activate response. */
  is_dev_host?: boolean
  product_url?: string | null
  dodo_store_url?: string | null
}

export function LicenseApp() {
  const [status, setStatus] = useState<LicenseStatus | null>(null)
  const [code, setCode] = useState('')
  const [email, setEmail] = useState('')
  const [consent, setConsent] = useState(false)
  const [busy, setBusy] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [activated, setActivated] = useState(false)

  useEffect(() => {
    api<LicenseStatus>('/status')
      .then(setStatus)
      .catch(() => void 0)
  }, [])

  const activate = async () => {
    setError(null)
    setBusy(true)
    try {
      const result = await api<LicenseStatus>('/activate', { method: 'POST', body: { license_code: code, email, consent } })
      setStatus(result)
      setActivated(true)
    } catch (e) {
      setError(e instanceof Error ? e.message : 'Something went wrong. Please try again.')
    } finally {
      setBusy(false)
    }
  }

  const activeMasked = status?.license_source === 'dodo' ? status.dodo_license_key_masked : status?.purchase_code_masked

  return (
    <div className="inst">
      <div className="inst-card">
        <div className="inst-head">
          <span className="inst-logo">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M4 7l2-4h12l2 4" /><path d="M4 7h16v13H4z" /><path d="M9 11h6" /></svg>
          </span>
          <span className="inst-title">MiniMart POS<small>License activation</small></span>
        </div>

        <div className="inst-body">
          {error && <div className="inst-alert err">{error}</div>}

          {activated && status?.status === 'active' ? (
            <>
              <h2>Licensed</h2>
              <p className="lede">This installation is now activated.{status.supported_until ? ` Support is active until ${new Date(status.supported_until).toLocaleDateString()}.` : ''}</p>
              <a className="btn btn-primary" href="/app">Go to your dashboard &rarr;</a>
            </>
          ) : (
            <>
              <h2>Activate your license</h2>
              <p className="lede">Enter the purchase code from your CodeCanyon order, or the license key Dodo Payments emailed you — either goes in the same field below.</p>

              <div className="inst-grid" style={{ marginBottom: 16 }}>
                <div className="inst-info">
                  <span className="label">
                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="10" /><path d="M2 12h20M12 2a15 15 0 0 1 0 20M12 2a15 15 0 0 0 0 20" /></svg>
                    Current domain
                  </span>
                  <span className="value">{status?.domain ?? window.location.hostname}</span>
                </div>
                {status?.product_url && (
                  <div className="inst-info">
                    <span className="label">
                      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M10 13a5 5 0 0 0 7 0l3-3a5 5 0 0 0-7-7l-1 1" /><path d="M14 11a5 5 0 0 0-7 0l-3 3a5 5 0 0 0 7 7l1-1" /></svg>
                      CodeCanyon listing
                    </span>
                    <a className="value" href={status.product_url} target="_blank" rel="noreferrer">{status.product_url}</a>
                  </div>
                )}
                {status?.dodo_store_url && (
                  <div className="inst-info">
                    <span className="label">
                      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M10 13a5 5 0 0 0 7 0l3-3a5 5 0 0 0-7-7l-1 1" /><path d="M14 11a5 5 0 0 0-7 0l-3 3a5 5 0 0 0 7 7l1-1" /></svg>
                      Dodo Payments store
                    </span>
                    <a className="value" href={status.dodo_store_url} target="_blank" rel="noreferrer">{status.dodo_store_url}</a>
                  </div>
                )}
              </div>

              {status?.is_dev_host && (
                <div className="inst-alert err">
                  This is a development host, where licensing is bypassed — activation isn&apos;t needed (and can&apos;t be validated here). Activate on your live domain.
                </div>
              )}

              {status?.status === 'active' && !activated && (
                <div className="inst-alert ok">Already licensed{activeMasked ? ` (${activeMasked})` : ''}. Enter a new code or key below to change it.</div>
              )}
              {status?.status === 'invalid' && (
                <div className="inst-alert warn">The last code or key entered could not be verified. Try again below.</div>
              )}

              <div className="inst-field">
                <label>Purchase code or license key</label>
                <input className="input" value={code} onChange={(e) => setCode(e.target.value)} placeholder="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or your Dodo license key" />
                <p className="inst-hint">Moving this install to a new domain? Re-enter the same code or key here — it won&apos;t use up another activation.</p>
              </div>
              <div className="inst-field">
                <label>Email</label>
                <input className="input" type="email" value={email} onChange={(e) => setEmail(e.target.value)} />
              </div>
              <label className="check">
                <input type="checkbox" checked={consent} onChange={(e) => setConsent(e.target.checked)} />
                <span className="box">
                  <svg viewBox="0 0 24 24"><path d="M5 12.5l4.5 4.5L19 7.5" /></svg>
                </span>
                <span className="cl">I confirm this code or key is mine and this server&apos;s address may be used to verify/activate it.</span>
              </label>
            </>
          )}
        </div>

        {!activated && (
          <div className="inst-foot" style={{ justifyContent: 'flex-end' }}>
            <button
              className="btn btn-primary"
              disabled={busy || !code || !email || !consent}
              onClick={activate}
            >
              {busy ? 'Verifying…' : 'Activate'}
            </button>
          </div>
        )}
      </div>
    </div>
  )
}
