'use client'
import { BASE } from '@/lib/basepath'

import { useEffect, useRef, useState } from 'react' // useRef kept for cardRef
import { fmt } from '@/lib/format'

// ── Minimal Square Web Payments SDK types ─────────────────────────────────────
declare global {
  interface Window {
    Square?: {
      payments(appId: string, locationId: string): Promise<SquarePayments>
    }
  }
}
interface SquarePayments {
  card(options?: object): Promise<SquareCard>
}
interface SquareCard {
  attach(selector: string): Promise<void>
  tokenize(): Promise<{
    status: string
    token?: string
    errors?: Array<{ message: string }>
  }>
  destroy(): Promise<void>
}
// ─────────────────────────────────────────────────────────────────────────────

export interface CheckoutPayload {
  lineItems: Array<{
    name:           string
    quantity:       number
    priceCents:     number
    catalogItemId?: string
    colors?:        string[]
    note?:          string
    modifiers?:     Array<{ catalogObjectId: string; name: string }>
  }>
  selectedColors:   string[]
  deliverySlotISO?: string
  driveMinutes?:    number
  deliveryAddress?: string
  deliveryTier?:    string
  deliveryNotes?:   string
  deliveryCents?:   number
  pickupSlotISO?:   string
  customerFirstName: string
  customerLastName:  string
  customerEmail:     string
  customerPhone:     string
  grandTotal:       number  // cents — shown on the button
  idempotencyKey?:  string  // stable per checkout attempt — prevents duplicate orders on retry
}

interface Props {
  payload:   CheckoutPayload
  onSuccess: (orderId: string, shortRef: string) => void
  onError?:  (message: string, status: number) => void
  active:    boolean   // true only when the payment step is visible
}

const SDK_URL =
  process.env.NEXT_PUBLIC_SQUARE_ENVIRONMENT === 'production'
    ? 'https://web.squarecdn.com/v1/square.js'
    : 'https://sandbox.web.squarecdn.com/v1/square.js'

function buildMailtoLink(payload: CheckoutPayload): string {
  const { fmt: fmtCents } = { fmt: (c: number) => `$${(c / 100).toFixed(2)}` }
  const items = payload.lineItems
    .map((li) => `  • ${li.quantity}× ${li.name} — ${fmtCents(li.priceCents * li.quantity)}${li.note ? ` (${li.note})` : ''}`)
    .join('\n')
  const fulfillment = payload.deliverySlotISO
    ? `Delivery: ${new Date(payload.deliverySlotISO).toLocaleString('en-US', { dateStyle: 'medium', timeStyle: 'short' })} to ${payload.deliveryAddress ?? ''}`
    : payload.pickupSlotISO
      ? `Pickup: ${new Date(payload.pickupSlotISO).toLocaleString('en-US', { dateStyle: 'medium', timeStyle: 'short' })}`
      : 'Fulfillment: not set'
  const body = [
    `Hi Beach Party Balloons,`,
    ``,
    `I tried to place an order online but ran into a payment error. Could you please send me an invoice?`,
    ``,
    `Name: ${payload.customerFirstName} ${payload.customerLastName}`,
    `Email: ${payload.customerEmail}`,
    `Phone: ${payload.customerPhone}`,
    ``,
    `Order:`,
    items,
    ``,
    fulfillment,
    `Total: ${fmtCents(payload.grandTotal)}`,
  ].join('\n')

  const addr = atob('aW5mb0BiZWFjaHBhcnR5YmFsbG9vbnMuY29t')
  return `mailto:${addr}?subject=${encodeURIComponent('Online Order — Invoice Request')}&body=${encodeURIComponent(body)}`
}

export default function PaymentForm({ payload, onSuccess, onError, active }: Props) {
  const appId      = process.env.NEXT_PUBLIC_SQUARE_APP_ID      ?? ''
  const locationId = process.env.NEXT_PUBLIC_SQUARE_LOCATION_ID ?? ''

  const [sdkReady,   setSdkReady]  = useState(false)
  const [cardReady,  setCardReady] = useState(false)
  const [submitting, setSubmitting] = useState(false)
  const [error,      setError]     = useState('')
  const cardRef = useRef<SquareCard | null>(null)

  // 1 — Load Square SDK script (idempotent)
  useEffect(() => {
    if (window.Square) { setSdkReady(true); return }
    const existing = document.querySelector(`script[src="${SDK_URL}"]`)
    if (existing) {
      existing.addEventListener('load', () => setSdkReady(true))
      return
    }
    const script = document.createElement('script')
    script.src = SDK_URL
    script.onload  = () => setSdkReady(true)
    script.onerror = () => setError('Failed to load payment processor. Please refresh and try again.')
    document.head.appendChild(script)
  }, [])

  // Clear any previous error when the booking slot changes
  useEffect(() => { setError('') }, [payload.deliverySlotISO, payload.pickupSlotISO])

  // 2 — Initialise card form once SDK is ready and the step is visible
  useEffect(() => {
    if (!active || !sdkReady || !window.Square || !appId || !locationId) return
    if (cardRef.current) return   // already initialised
    let mounted = true

    ;(async () => {
      try {
        // Double-rAF: wait for the browser to finish painting so #sq-card is in the DOM
        await new Promise<void>((resolve) =>
          requestAnimationFrame(() => requestAnimationFrame(() => resolve()))
        )
        if (!mounted) return
        if (!document.getElementById('sq-card')) {
          if (mounted) setError('Could not load payment form — please refresh and try again.')
          return
        }

        const payments = await window.Square!.payments(appId, locationId)
        const card     = await payments.card()
        await card.attach('#sq-card')
        if (mounted) {
          cardRef.current = card
          setCardReady(true)
        } else {
          card.destroy().catch(() => {})
        }
      } catch (e) {
        console.error('[PaymentForm] init:', e)
        if (mounted) setError('Could not load payment form — please refresh and try again.')
      }
    })()

    return () => {
      mounted = false
      cardRef.current?.destroy().catch(() => {})
      cardRef.current = null
      setCardReady(false)
    }
  }, [active, sdkReady, appId, locationId])

  const handlePay = async () => {
    if (!cardRef.current || submitting) return
    setSubmitting(true)
    setError('')

    try {
      const tokenResult = await cardRef.current.tokenize()

      if (tokenResult.status !== 'OK' || !tokenResult.token) {
        setError(
          tokenResult.errors?.map((e) => e.message).join(' ') ??
          'Could not read card. Please check your details and try again.'
        )
        return
      }

      const checkoutBody = JSON.stringify({ ...payload, sourceId: tokenResult.token })

      // Attempt the checkout request. On a network-level failure (fetch throws),
      // wait 2 seconds and retry once automatically — the idempotency key ensures
      // no double charge and will return success if the first attempt already
      // captured payment but the response was lost.
      const attemptCheckout = () => fetch(BASE + '/api/checkout', {
        method:  'POST',
        headers: { 'Content-Type': 'application/json' },
        body:    checkoutBody,
      })

      let res: Response
      try {
        res = await attemptCheckout()
      } catch {
        // Network failure on first attempt — pause and retry once
        await new Promise((r) => setTimeout(r, 2000))
        try {
          res = await attemptCheckout()
        } catch {
          // Both attempts failed — payment may or may not have gone through.
          // The idempotency key is preserved in localStorage, so clicking
          // "Place Order" again will safely resolve either way.
          setError(
            'Connection issue — your payment may have already been processed. ' +
            'Please tap "Place Order" again to confirm, or contact us if this persists.'
          )
          return
        }
      }

      const data = await res.json()

      if (!res.ok || !data.success) {
        const msg = data.error ?? 'Checkout failed — please try again or contact us.'
        if (res.status !== 409) console.error('[checkout] response:', data)
        if (res.status === 400 && onError) {
          onError(msg, res.status)
          return
        }
        setError(msg)
        return
      }

      onSuccess(data.orderId as string, data.shortRef as string)
    } finally {
      setSubmitting(false)
    }
  }

  if (!appId || !locationId) {
    return (
      <p style={{ fontSize: '0.85rem', color: '#cc3333' }}>
        Online payment is not configured.{' '}
        <a href="https://beachpartyballoons.com/contact/" style={{ color: '#cc3333', textDecoration: 'underline' }}>
          Contact us
        </a>{' '}
        to complete your booking.
      </p>
    )
  }

  return (
    <div>
      {/* Accepted card types */}
      <div style={{ display: 'flex', gap: '6px', marginBottom: '0.75rem', flexWrap: 'wrap' }}>
        {['Visa', 'Mastercard', 'Amex', 'Discover'].map((brand) => (
          <span key={brand} style={{
            fontSize: '0.68rem', fontWeight: 'bold', letterSpacing: '0.02em',
            padding: '2px 7px', borderRadius: '4px',
            border: '1px solid #d0d0d0', color: '#555', background: '#fafafa',
          }}>{brand}</span>
        ))}
      </div>

      {/* Square mounts the iframe card form here */}
      <div
        id="sq-card"
        style={{
          minHeight:  '160px',
          opacity:    cardReady ? 1 : 0.5,
          transition: 'opacity 0.25s',
        }}
      />

      {!cardReady && !error && (
        <p style={{ fontSize: '0.78rem', color: '#888', marginTop: '0.5rem' }}>
          Loading secure payment form…
        </p>
      )}

      {error && (
        <div style={{ marginTop: '0.6rem' }}>
          <p style={{ fontSize: '0.78rem', color: '#cc3333', lineHeight: 1.45 }}>
            {error}
          </p>
          <p style={{ fontSize: '0.75rem', color: '#555', marginTop: '0.5rem', lineHeight: 1.5 }}>
            If this keeps happening, you can{' '}
            <a
              href={buildMailtoLink(payload)}
              style={{ color: '#0d6e75', textDecoration: 'underline' }}
            >
              email us your order details
            </a>
            {' '}and we&apos;ll send you an invoice.
          </p>
        </div>
      )}

      <button
        className={`button is-info is-fullwidth${submitting ? ' is-loading' : ''}`}
        disabled={!cardReady || submitting}
        onClick={handlePay}
        style={{ marginTop: '1rem' }}
      >
        Place Order · {fmt(payload.grandTotal)}
      </button>

      <p style={{ fontSize: '0.72rem', color: '#888', textAlign: 'center', marginTop: '0.5rem', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: '5px' }}>
        <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" style={{ flexShrink: 0 }}>
          <rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>
        </svg>
        256-bit SSL · Powered by Square · Your card info never touches our servers
      </p>
    </div>
  )
}
