import { Button } from '../../../components/ui/button'
import { toast } from '../../../components/ui/toast'
import { usePaymentNavigation } from '../lib/navigation'
import React from 'react'
import { PaymentInstructions } from './PaymentInstructions'
import { postCharge } from '../../../services/api'
import { InlinePaymentStatus } from './InlinePaymentStatus'
import { LoadingOverlay } from '../../../components/LoadingOverlay'
import { Alert } from '../../../components/alert/Alert'
import { getErrorRecoveryAction, mapErrorToUserMessage } from '../../../lib/errorMessages'

type StoreKey = 'alfamart' | 'indomaret'

// Shared guards/tasks to prevent duplicate charges under StrictMode/HMR and double clicks
const attemptedCStoreKeys = new Set<string>()
const cstoreTasks = new Map<string, Promise<any>>()

export function CStorePanel({ orderId, amount, locked, onChargeInitiated, defaultStore }: { orderId: string; amount: number; locked?: boolean; onChargeInitiated?: () => void; defaultStore?: StoreKey }) {
  const nav = usePaymentNavigation()
  const [selected] = React.useState<StoreKey | null>(defaultStore ?? null)
  const [showGuide, setShowGuide] = React.useState(false)
  const [busy, setBusy] = React.useState(false)
  const [paymentCode, setPaymentCode] = React.useState('')
  const [storeFromRes, setStoreFromRes] = React.useState('')
  const [errorMessage, setErrorMessage] = React.useState('')
  const [recovery, setRecovery] = React.useState<'retry' | 'view-existing' | 'back'>('retry')

  React.useEffect(() => {
    let cancelled = false
    async function run() {
      // Only auto-charge when a store is selected, not locked, and code not yet generated
      if (!selected || locked || paymentCode) return
      const chargeKey = `${orderId}:${selected}`
      // If there's already an in-flight task, await it
      if (attemptedCStoreKeys.has(chargeKey) && cstoreTasks.has(chargeKey)) {
        setBusy(true)
        try {
          const res = await cstoreTasks.get(chargeKey)!
          if (!cancelled) {
            if (typeof res?.payment_code === 'string') setPaymentCode(res.payment_code)
            if (typeof res?.store === 'string') setStoreFromRes(res.store)
          }
        } catch (e) {
          if (!cancelled) {
            const msg = mapErrorToUserMessage(e)
            const act = getErrorRecoveryAction(e)
            setErrorMessage(msg)
            setRecovery(act)
            toast.error(msg)
          }
        } finally {
          if (!cancelled) setBusy(false)
          cstoreTasks.delete(chargeKey)
        }
        return
      }
      setBusy(true)
      onChargeInitiated?.()
      try {
        const payload: Record<string, any> = {
          payment_type: 'cstore',
          transaction_details: { order_id: orderId, gross_amount: amount },
          cstore: { store: selected, message: `Pembayaran untuk order ${orderId}` },
        }
        attemptedCStoreKeys.add(chargeKey)
        const task = postCharge(payload)
        cstoreTasks.set(chargeKey, task)
        const res = await task
        if (!cancelled) {
          if (typeof res?.payment_code === 'string') setPaymentCode(res.payment_code)
          if (typeof res?.store === 'string') setStoreFromRes(res.store)
        }
      } catch (e) {
        if (!cancelled) {
          const msg = mapErrorToUserMessage(e)
          const act = getErrorRecoveryAction(e)
          setErrorMessage(msg)
          setRecovery(act)
          toast.error(msg)
        }
        attemptedCStoreKeys.delete(chargeKey)
      } finally {
        if (!cancelled) setBusy(false)
        cstoreTasks.delete(chargeKey)
      }
    }
    run()
    return () => { cancelled = true }
  }, [selected, orderId, amount])

  function copy(text: string, label: string) {
    if (!text) return
    navigator.clipboard?.writeText(text)
    toast.success(`${label} disalin: ${text}`)
  }

  return (
    <>
      <LoadingOverlay isLoading={busy} message="Sedang membuat kode pembayaran..." />
      <div className="space-y-3">
        <div className="font-medium">Convenience Store</div>
        {errorMessage && (
          <Alert title="Informasi">
            {errorMessage}
            {recovery === 'view-existing' && (
              <div className="mt-2">
                <Button variant="outline" onClick={() => nav.toStatus(orderId, 'cstore')}>Lihat Kode Pembayaran</Button>
              </div>
            )}
          </Alert>
        )}
        {selected && (
          <div className="text-xs text-gray-600">Toko dipilih: <span className="font-medium text-gray-900">{selected.toUpperCase()}</span></div>
        )}
        <button
          type="button"
          onClick={() => setShowGuide((v) => !v)}
          className="text-xs text-brand-600 hover:underline"
          aria-expanded={showGuide}
        >
          Cara bayar
        </button>
        {showGuide && <PaymentInstructions method="cstore" />}
        {locked && (
          <div className="text-xs text-gray-600">Metode terkunci. Gunakan kode pembayaran di kasir {selected?.toUpperCase()}.</div>
        )}
        <div className="pt-2 space-y-2">
          <div className="rounded border border-gray-300 p-2 text-sm" aria-live="polite">
            <div className="font-medium">Kode Pembayaran</div>
            {!selected && (
              <div className="text-xs text-gray-600">Pilih toko terlebih dahulu di langkah sebelumnya.</div>
            )}
            {selected && busy && (
              <div className="inline-flex items-center gap-2 text-xs text-gray-600">
                <span className="h-4 w-4 animate-spin rounded-full border-2 border-gray-400 border-t-transparent" aria-hidden />
                Membuat kode…
              </div>
            )}
            {selected && !busy && (storeFromRes || paymentCode) && (
              <>
                {storeFromRes ? <div>Toko: {storeFromRes.toUpperCase()}</div> : null}
                {paymentCode ? <div>Kode: <span className="font-mono text-lg tracking-[0.06em] select-all">{paymentCode}</span></div> : null}
              </>
            )}
            <div className="mt-2"><Button variant="outline" className="w-full sm:w-auto" onClick={() => copy(paymentCode, 'Kode pembayaran')} disabled={!paymentCode || busy}>Copy Kode</Button></div>
          </div>
          <Button
            variant="outline"
            className="w-full"
            disabled={busy || (!locked && !paymentCode && recovery !== 'view-existing')}
            onClick={() => nav.toStatus(orderId, 'cstore')}
          >
            Buka halaman status
          </Button>
          <InlinePaymentStatus orderId={orderId} method="cstore" />
        </div>
      </div>
    </>
  )
}