'use client'

import dynamic from 'next/dynamic'
import Link from 'next/link'
import { useState, useCallback, useEffect, useRef } from 'react'
import { starterNodes } from '@/lib/presets'
import { serializeState, deserializeState, saveToLocal, loadFromLocal, listSavedSpaces, deleteFromLocal } from '@/lib/state'
import type { FlowNode, SpaceConfig, IntegrationConfig } from '@/lib/types'
import {
  deployNodes,
  getFlow,
  syncNodesToBackend,
  deposit,
  listFlows,
  fromSmallestUnit,
  type BackendFlow,
  type DeployResult,
} from '@/lib/api/flows-client'

const FlowCanvas = dynamic(() => import('@/components/FlowCanvas'), {
  ssr: false,
  loading: () => (
    <div className="w-full h-full flex items-center justify-center bg-slate-50">
      <div className="flex items-center gap-3">
        <div className="w-8 h-8 border-4 border-blue-500 border-t-transparent rounded-full animate-spin" />
        <span className="text-slate-600">Loading flow editor...</span>
      </div>
    </div>
  ),
})

export default function SpacePage() {
  const [currentNodes, setCurrentNodes] = useState<FlowNode[]>(starterNodes)
  const [integrations, setIntegrations] = useState<IntegrationConfig | undefined>()
  const [spaceName, setSpaceName] = useState('')
  const [showSaveDialog, setShowSaveDialog] = useState(false)
  const [showLoadDialog, setShowLoadDialog] = useState(false)
  const [savedSpaces, setSavedSpaces] = useState<SpaceConfig[]>([])
  const [copied, setCopied] = useState(false)
  const [loaded, setLoaded] = useState(false)
  const nodesRef = useRef<FlowNode[]>(starterNodes)
  const integrationsRef = useRef<IntegrationConfig | undefined>()

  // Backend integration state
  const [deployedFlow, setDeployedFlow] = useState<BackendFlow | null>(null)
  const [idMap, setIdMap] = useState<Record<string, string>>({})
  const [showDeployDialog, setShowDeployDialog] = useState(false)
  const [showDepositDialog, setShowDepositDialog] = useState(false)
  const [showLoadFlowDialog, setShowLoadFlowDialog] = useState(false)
  const [deployName, setDeployName] = useState('')
  const [ownerAddress, setOwnerAddress] = useState('')
  const [deploying, setDeploying] = useState(false)
  const [syncing, setSyncing] = useState(false)
  const [depositFunnelId, setDepositFunnelId] = useState('')
  const [depositAmount, setDepositAmount] = useState('')
  const [depositing, setDepositing] = useState(false)
  const [backendFlows, setBackendFlows] = useState<BackendFlow[]>([])
  const [statusMessage, setStatusMessage] = useState<{ text: string; type: 'success' | 'error' } | null>(null)

  // Load saved owner address
  useEffect(() => {
    if (typeof window === 'undefined') return
    const saved = localStorage.getItem('rfunds-owner-address')
    if (saved) setOwnerAddress(saved)
  }, [])

  const showStatus = useCallback((text: string, type: 'success' | 'error') => {
    setStatusMessage({ text, type })
    setTimeout(() => setStatusMessage(null), 4000)
  }, [])

  const handleIntegrationsChange = useCallback((config: IntegrationConfig) => {
    setIntegrations(config)
    integrationsRef.current = config
  }, [])

  // Load from URL hash on mount
  useEffect(() => {
    if (typeof window === 'undefined') return
    const hash = window.location.hash.slice(1)
    if (hash.startsWith('s=')) {
      const compressed = hash.slice(2)
      const state = deserializeState(compressed)
      if (state) {
        setCurrentNodes(state.nodes)
        nodesRef.current = state.nodes
        if (state.integrations) {
          setIntegrations(state.integrations)
          integrationsRef.current = state.integrations
        }
      }
    }
    setLoaded(true)
  }, [])

  const handleNodesChange = useCallback((nodes: FlowNode[]) => {
    nodesRef.current = nodes
  }, [])

  const handleShare = useCallback(() => {
    const compressed = serializeState(nodesRef.current, integrationsRef.current)
    const url = `${window.location.origin}/space#s=${compressed}`
    navigator.clipboard.writeText(url).then(() => {
      setCopied(true)
      setTimeout(() => setCopied(false), 2000)
    })
  }, [])

  const handleSave = useCallback(() => {
    if (!spaceName.trim()) return
    saveToLocal(spaceName.trim(), nodesRef.current, integrationsRef.current)
    setShowSaveDialog(false)
    setSpaceName('')
  }, [spaceName])

  const handleLoadOpen = useCallback(() => {
    setSavedSpaces(listSavedSpaces())
    setShowLoadDialog(true)
  }, [])

  const handleLoadSpace = useCallback((config: SpaceConfig) => {
    setCurrentNodes(config.nodes)
    nodesRef.current = config.nodes
    if (config.integrations) {
      setIntegrations(config.integrations)
      integrationsRef.current = config.integrations
    }
    setShowLoadDialog(false)
  }, [])

  const handleDeleteSpace = useCallback((name: string) => {
    deleteFromLocal(name)
    setSavedSpaces(listSavedSpaces())
  }, [])

  const handleReset = useCallback(() => {
    if (confirm('Reset canvas to a single empty funnel? This cannot be undone.')) {
      setCurrentNodes([...starterNodes])
      nodesRef.current = [...starterNodes]
      setDeployedFlow(null)
      setIdMap({})
      window.history.replaceState(null, '', window.location.pathname)
    }
  }, [])

  // ─── Backend Integration Handlers ───────────────────────────

  const handleDeploy = useCallback(async () => {
    if (!deployName.trim() || !ownerAddress.trim()) return
    setDeploying(true)
    try {
      localStorage.setItem('rfunds-owner-address', ownerAddress.trim())
      const result: DeployResult = await deployNodes(
        deployName.trim(),
        ownerAddress.trim(),
        nodesRef.current
      )
      setDeployedFlow(result.flow)
      setIdMap(result.idMap)
      setShowDeployDialog(false)
      setDeployName('')
      showStatus(`Deployed "${result.flow.name}" (${result.flow.funnels.length} funnels, ${result.flow.outcomes.length} outcomes)`, 'success')
    } catch (err) {
      showStatus(`Deploy failed: ${err instanceof Error ? err.message : 'Unknown error'}`, 'error')
    } finally {
      setDeploying(false)
    }
  }, [deployName, ownerAddress, showStatus])

  const handleSync = useCallback(async () => {
    if (!deployedFlow) return
    setSyncing(true)
    try {
      const latest = await getFlow(deployedFlow.id)
      setDeployedFlow(latest)
      const updated = syncNodesToBackend(nodesRef.current, latest, idMap)
      setCurrentNodes(updated)
      nodesRef.current = updated
      showStatus('Synced live balances from backend', 'success')
    } catch (err) {
      showStatus(`Sync failed: ${err instanceof Error ? err.message : 'Unknown error'}`, 'error')
    } finally {
      setSyncing(false)
    }
  }, [deployedFlow, idMap, showStatus])

  const handleDeposit = useCallback(async () => {
    if (!deployedFlow || !depositFunnelId || !depositAmount) return
    setDepositing(true)
    try {
      const amount = parseFloat(depositAmount)
      if (isNaN(amount) || amount <= 0) throw new Error('Invalid amount')
      const tx = await deposit(deployedFlow.id, depositFunnelId, amount)
      showStatus(`Deposited $${amount} USDC (tx: ${tx.status})`, 'success')
      setShowDepositDialog(false)
      setDepositAmount('')
      // Auto-sync after deposit
      const latest = await getFlow(deployedFlow.id)
      setDeployedFlow(latest)
      const updated = syncNodesToBackend(nodesRef.current, latest, idMap)
      setCurrentNodes(updated)
      nodesRef.current = updated
    } catch (err) {
      showStatus(`Deposit failed: ${err instanceof Error ? err.message : 'Unknown error'}`, 'error')
    } finally {
      setDepositing(false)
    }
  }, [deployedFlow, depositFunnelId, depositAmount, idMap, showStatus])

  const handleLoadFlowOpen = useCallback(async () => {
    if (!ownerAddress.trim()) {
      showStatus('Set your wallet address first (via Deploy dialog)', 'error')
      return
    }
    try {
      const flows = await listFlows(ownerAddress.trim())
      setBackendFlows(flows)
      setShowLoadFlowDialog(true)
    } catch (err) {
      showStatus(`Failed to list flows: ${err instanceof Error ? err.message : 'Unknown error'}`, 'error')
    }
  }, [ownerAddress, showStatus])

  const handleLoadFlow = useCallback((flow: BackendFlow) => {
    setDeployedFlow(flow)
    // Build idMap from backend flow — map by index (best effort without original mapping)
    const newIdMap: Record<string, string> = {}
    const funnelNodes = nodesRef.current.filter(n => n.type === 'funnel')
    const outcomeNodes = nodesRef.current.filter(n => n.type === 'outcome')
    flow.funnels.forEach((f, i) => {
      if (funnelNodes[i]) newIdMap[funnelNodes[i].id] = f.id
    })
    flow.outcomes.forEach((o, i) => {
      if (outcomeNodes[i]) newIdMap[outcomeNodes[i].id] = o.id
    })
    setIdMap(newIdMap)
    setShowLoadFlowDialog(false)
    showStatus(`Loaded flow "${flow.name}" (${flow.status})`, 'success')
  }, [showStatus])

  if (!loaded) {
    return (
      <div className="h-screen w-screen flex items-center justify-center bg-slate-50">
        <div className="flex items-center gap-3">
          <div className="w-8 h-8 border-4 border-blue-500 border-t-transparent rounded-full animate-spin" />
          <span className="text-slate-600">Loading...</span>
        </div>
      </div>
    )
  }

  return (
    <main className="h-screen w-screen flex flex-col">
      {/* Status Toast */}
      {statusMessage && (
        <div className={`fixed top-16 left-1/2 -translate-x-1/2 z-[60] px-4 py-2 rounded-lg shadow-lg text-sm font-medium transition-all ${
          statusMessage.type === 'success' ? 'bg-emerald-600 text-white' : 'bg-red-600 text-white'
        }`}>
          {statusMessage.text}
        </div>
      )}

      {/* Toolbar */}
      <div className="bg-slate-800 text-white px-4 py-2 flex items-center justify-between text-sm flex-shrink-0">
        <div className="flex items-center gap-3">
          <Link href="/" className="flex items-center gap-2 hover:opacity-80 transition-opacity">
            <div className="w-6 h-6 bg-gradient-to-br from-amber-400 to-emerald-500 rounded flex items-center justify-center font-bold text-slate-900 text-[10px]">
              rF
            </div>
            <span className="font-medium">rFunds</span>
          </Link>
          <span className="text-slate-500">|</span>
          <span className="text-slate-300">Your Space</span>
          {deployedFlow && (
            <>
              <span className="text-slate-500">|</span>
              <span className={`text-xs px-2 py-0.5 rounded-full ${
                deployedFlow.status === 'active' ? 'bg-emerald-600/30 text-emerald-300' :
                deployedFlow.status === 'paused' ? 'bg-amber-600/30 text-amber-300' :
                'bg-slate-600/30 text-slate-400'
              }`}>
                {deployedFlow.status} &middot; {deployedFlow.name}
              </span>
            </>
          )}
        </div>

        <div className="flex items-center gap-2">
          {/* Local operations */}
          <button
            onClick={() => setShowSaveDialog(true)}
            className="px-3 py-1 bg-blue-600 hover:bg-blue-500 rounded text-xs font-medium transition-colors"
          >
            Save
          </button>
          <button
            onClick={handleLoadOpen}
            className="px-3 py-1 bg-slate-600 hover:bg-slate-500 rounded text-xs font-medium transition-colors"
          >
            Load
          </button>
          <button
            onClick={handleShare}
            className="px-3 py-1 bg-emerald-600 hover:bg-emerald-500 rounded text-xs font-medium transition-colors"
          >
            {copied ? 'Copied!' : 'Share'}
          </button>

          {/* Separator */}
          <div className="w-px h-5 bg-slate-600 mx-1" />

          {/* Backend operations */}
          <button
            onClick={() => setShowDeployDialog(true)}
            className="px-3 py-1 bg-violet-600 hover:bg-violet-500 rounded text-xs font-medium transition-colors"
          >
            Deploy
          </button>
          {deployedFlow && (
            <>
              <button
                onClick={handleSync}
                disabled={syncing}
                className="px-3 py-1 bg-cyan-600 hover:bg-cyan-500 rounded text-xs font-medium transition-colors disabled:opacity-50"
              >
                {syncing ? 'Syncing...' : 'Sync'}
              </button>
              <button
                onClick={() => {
                  if (deployedFlow.funnels.length > 0) {
                    setDepositFunnelId(deployedFlow.funnels[0].id)
                  }
                  setShowDepositDialog(true)
                }}
                className="px-3 py-1 bg-green-600 hover:bg-green-500 rounded text-xs font-medium transition-colors"
              >
                Deposit
              </button>
            </>
          )}
          <button
            onClick={handleLoadFlowOpen}
            className="px-3 py-1 bg-slate-600 hover:bg-slate-500 rounded text-xs font-medium transition-colors"
            title="Load a previously deployed flow"
          >
            Flows
          </button>

          {/* Separator */}
          <div className="w-px h-5 bg-slate-600 mx-1" />

          <button
            onClick={handleReset}
            className="px-3 py-1 bg-slate-700 hover:bg-red-600 rounded text-xs font-medium transition-colors"
          >
            Reset
          </button>
        </div>
      </div>

      {/* Canvas */}
      <div className="flex-1">
        <FlowCanvas
          key={JSON.stringify(currentNodes.map(n => n.id))}
          initialNodes={currentNodes}
          mode="space"
          onNodesChange={handleNodesChange}
          integrations={integrations}
          onIntegrationsChange={handleIntegrationsChange}
        />
      </div>

      {/* Save Dialog */}
      {showSaveDialog && (
        <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50" onClick={() => setShowSaveDialog(false)}>
          <div className="bg-white rounded-xl shadow-2xl p-6 w-80" onClick={e => e.stopPropagation()}>
            <h3 className="text-lg font-bold text-slate-800 mb-4">Save Space</h3>
            <input
              type="text"
              value={spaceName}
              onChange={e => setSpaceName(e.target.value)}
              placeholder="Space name..."
              className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mb-4 text-slate-800"
              autoFocus
              onKeyDown={e => e.key === 'Enter' && handleSave()}
            />
            <div className="flex gap-2">
              <button
                onClick={handleSave}
                disabled={!spaceName.trim()}
                className="flex-1 px-4 py-2 bg-blue-600 text-white rounded-lg text-sm font-medium hover:bg-blue-500 disabled:opacity-40 disabled:cursor-not-allowed transition-colors"
              >
                Save
              </button>
              <button
                onClick={() => setShowSaveDialog(false)}
                className="px-4 py-2 text-slate-600 hover:text-slate-800 text-sm"
              >
                Cancel
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Load Dialog */}
      {showLoadDialog && (
        <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50" onClick={() => setShowLoadDialog(false)}>
          <div className="bg-white rounded-xl shadow-2xl p-6 w-96 max-h-[60vh] overflow-y-auto" onClick={e => e.stopPropagation()}>
            <h3 className="text-lg font-bold text-slate-800 mb-4">Load Space</h3>
            {savedSpaces.length === 0 ? (
              <p className="text-sm text-slate-500 py-4 text-center">No saved spaces yet.</p>
            ) : (
              <div className="space-y-2">
                {savedSpaces.map((space) => (
                  <div
                    key={space.name}
                    className="flex items-center justify-between p-3 bg-slate-50 rounded-lg hover:bg-slate-100 transition-colors"
                  >
                    <button
                      onClick={() => handleLoadSpace(space)}
                      className="flex-1 text-left"
                    >
                      <div className="text-sm font-medium text-slate-800">{space.name}</div>
                      <div className="text-[10px] text-slate-500">
                        {space.nodes.filter(n => n.type === 'funnel').length} funnels &bull;{' '}
                        {space.nodes.filter(n => n.type === 'outcome').length} outcomes &bull;{' '}
                        {new Date(space.updatedAt).toLocaleDateString()}
                      </div>
                    </button>
                    <button
                      onClick={() => handleDeleteSpace(space.name)}
                      className="text-slate-400 hover:text-red-500 p-1 transition-colors"
                    >
                      <svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                        <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
                      </svg>
                    </button>
                  </div>
                ))}
              </div>
            )}
            <button
              onClick={() => setShowLoadDialog(false)}
              className="w-full mt-4 px-4 py-2 text-slate-600 hover:text-slate-800 text-sm border border-slate-200 rounded-lg"
            >
              Close
            </button>
          </div>
        </div>
      )}

      {/* Deploy Dialog */}
      {showDeployDialog && (
        <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50" onClick={() => setShowDeployDialog(false)}>
          <div className="bg-white rounded-xl shadow-2xl p-6 w-96" onClick={e => e.stopPropagation()}>
            <h3 className="text-lg font-bold text-slate-800 mb-1">Deploy to Backend</h3>
            <p className="text-xs text-slate-500 mb-4">
              Creates a live flow on the server with real threshold logic, overflow distribution, and fiat on-ramp support.
            </p>
            <input
              type="text"
              value={deployName}
              onChange={e => setDeployName(e.target.value)}
              placeholder="Flow name..."
              className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mb-3 text-slate-800"
              autoFocus
            />
            <input
              type="text"
              value={ownerAddress}
              onChange={e => setOwnerAddress(e.target.value)}
              placeholder="Owner wallet address (0x...)"
              className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mb-3 text-slate-800 font-mono text-xs"
            />
            <div className="text-[10px] text-slate-400 mb-4">
              {nodesRef.current.filter(n => n.type === 'funnel').length} funnels &bull;{' '}
              {nodesRef.current.filter(n => n.type === 'outcome').length} outcomes will be created on Base Sepolia (USDC)
            </div>
            <div className="flex gap-2">
              <button
                onClick={handleDeploy}
                disabled={!deployName.trim() || !ownerAddress.trim() || deploying}
                className="flex-1 px-4 py-2 bg-violet-600 text-white rounded-lg text-sm font-medium hover:bg-violet-500 disabled:opacity-40 disabled:cursor-not-allowed transition-colors"
              >
                {deploying ? 'Deploying...' : 'Deploy'}
              </button>
              <button
                onClick={() => setShowDeployDialog(false)}
                className="px-4 py-2 text-slate-600 hover:text-slate-800 text-sm"
              >
                Cancel
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Deposit Dialog */}
      {showDepositDialog && deployedFlow && (
        <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50" onClick={() => setShowDepositDialog(false)}>
          <div className="bg-white rounded-xl shadow-2xl p-6 w-96" onClick={e => e.stopPropagation()}>
            <h3 className="text-lg font-bold text-slate-800 mb-1">Deposit USDC</h3>
            <p className="text-xs text-slate-500 mb-4">
              Simulate a deposit into a funnel. If the deposit pushes the balance above MAX threshold, overflow will automatically distribute.
            </p>
            <select
              value={depositFunnelId}
              onChange={e => setDepositFunnelId(e.target.value)}
              className="w-full px-3 py-2 border border-slate-200 rounded-lg text-sm mb-3 text-slate-800"
            >
              {deployedFlow.funnels.map(f => (
                <option key={f.id} value={f.id}>
                  {f.name} (balance: ${fromSmallestUnit(f.balance).toLocaleString()})
                </option>
              ))}
            </select>
            <div className="relative mb-4">
              <span className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400 text-sm">$</span>
              <input
                type="number"
                value={depositAmount}
                onChange={e => setDepositAmount(e.target.value)}
                placeholder="Amount (USDC)"
                className="w-full pl-7 pr-3 py-2 border border-slate-200 rounded-lg text-sm text-slate-800"
                min="0"
                step="0.01"
              />
            </div>
            <div className="flex gap-2">
              <button
                onClick={handleDeposit}
                disabled={!depositAmount || depositing}
                className="flex-1 px-4 py-2 bg-green-600 text-white rounded-lg text-sm font-medium hover:bg-green-500 disabled:opacity-40 disabled:cursor-not-allowed transition-colors"
              >
                {depositing ? 'Depositing...' : 'Deposit'}
              </button>
              <button
                onClick={() => setShowDepositDialog(false)}
                className="px-4 py-2 text-slate-600 hover:text-slate-800 text-sm"
              >
                Cancel
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Load Backend Flow Dialog */}
      {showLoadFlowDialog && (
        <div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50" onClick={() => setShowLoadFlowDialog(false)}>
          <div className="bg-white rounded-xl shadow-2xl p-6 w-96 max-h-[60vh] overflow-y-auto" onClick={e => e.stopPropagation()}>
            <h3 className="text-lg font-bold text-slate-800 mb-4">Deployed Flows</h3>
            {backendFlows.length === 0 ? (
              <p className="text-sm text-slate-500 py-4 text-center">No deployed flows yet.</p>
            ) : (
              <div className="space-y-2">
                {backendFlows.map((flow) => (
                  <button
                    key={flow.id}
                    onClick={() => handleLoadFlow(flow)}
                    className="w-full text-left p-3 bg-slate-50 rounded-lg hover:bg-slate-100 transition-colors"
                  >
                    <div className="flex items-center justify-between">
                      <div className="text-sm font-medium text-slate-800">{flow.name}</div>
                      <span className={`text-[10px] px-1.5 py-0.5 rounded ${
                        flow.status === 'active' ? 'bg-emerald-100 text-emerald-700' :
                        flow.status === 'paused' ? 'bg-amber-100 text-amber-700' :
                        'bg-slate-100 text-slate-600'
                      }`}>
                        {flow.status}
                      </span>
                    </div>
                    <div className="text-[10px] text-slate-500 mt-1">
                      {flow.funnels.length} funnels &bull; {flow.outcomes.length} outcomes &bull;{' '}
                      {new Date(flow.updatedAt).toLocaleDateString()}
                    </div>
                  </button>
                ))}
              </div>
            )}
            <button
              onClick={() => setShowLoadFlowDialog(false)}
              className="w-full mt-4 px-4 py-2 text-slate-600 hover:text-slate-800 text-sm border border-slate-200 rounded-lg"
            >
              Close
            </button>
          </div>
        </div>
      )}
    </main>
  )
}
