/**
 * Memorio React App Example
 *
 * This example shows how to use Memorio state in a React application.
 *
 * Run: npx ts-node --esm examples/react-app.tsx
 * Or copy to your React project
 */

import React, { useState, useEffect } from 'react'
import 'memorio'

// ============================================
// 1. SETUP - Import once at app start
// ============================================

// In your main App.tsx or index.js:
// import 'memorio'

// ============================================
// 2. DEFINE YOUR STATE SHAPE
// ============================================

interface AppState {
  user: {
    name: string
    email: string
    avatar?: string
  } | null
  theme: 'light' | 'dark'
  notifications: Notification[]
  cart: CartItem[]
  isLoading: boolean
}

interface Notification {
  id: string
  message: string
  read: boolean
}

interface CartItem {
  id: number
  name: string
  price: number
  quantity: number
}

// ============================================
// 3. USE STATE IN COMPONENTS
// ============================================

// ------------------------------
// Header Component
// ------------------------------
function Header() {
  // Using useObserver to react to state changes
  const [theme, setTheme] = useState(state.theme)

  useObserver(() => {
    setTheme(state.theme)
  }, [state.theme])

  return (
    <header className={`header header--${theme}`}>
      <h1>My App</h1>
      <button onClick={() => {
        state.theme = state.theme === 'light' ? 'dark' : 'light'
      }}>
        Toggle Theme
      </button>
    </header>
  )
}

// ------------------------------
// User Profile Component
// ------------------------------
function UserProfile() {
  const [user, setUser] = useState(state.user)

  // Auto-discover all state changes
  useObserver(() => {
    setUser(state.user)
  })

  if (!user) {
    return <div>Please log in</div>
  }

  return (
    <div className="profile">
      <img src={user.avatar} alt={user.name} />
      <h2>{user.name}</h2>
      <p>{user.email}</p>
    </div>
  )
}

// ------------------------------
// Login Form Component
// ------------------------------
function LoginForm() {
  const [name, setName] = useState('')
  const [email, setEmail] = useState('')

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault()

    // Set user state
    state.user = {
      name,
      email,
      avatar: `https://api.dicebear.com/7.x/avataaars/svg?seed=${name}`
    }

    // Also persist to store
    store.set('lastUser', name)
  }

  return (
    <form onSubmit={handleSubmit}>
      <input
        value={name}
        onChange={e => setName(e.target.value)}
        placeholder="Name"
      />
      <input
        value={email}
        onChange={e => setEmail(e.target.value)}
        placeholder="Email"
      />
      <button type="submit">Login</button>
    </form>
  )
}

// ------------------------------
// Shopping Cart Component
// ------------------------------
function Cart() {
  const [items, setItems] = useState<CartItem[]>([])

  useObserver(() => {
    setItems(state.cart || [])
  }, [state.cart])

  const total = items.reduce((sum, item) => sum + item.price * item.quantity, 0)

  return (
    <div className="cart">
      <h2>Cart ({items.length})</h2>
      {items.map(item => (
        <div key={item.id}>
          {item.name} - ${item.price} x {item.quantity}
        </div>
      ))}
      <strong>Total: ${total}</strong>
      <div style={{ marginTop: '1rem' }}>
        <AddToCartButton
          product={{ id: 1, name: 'Sample Product', price: 9.99 }}
        />
      </div>
    </div>
  )
}

// ------------------------------
// Add to Cart Button
// ------------------------------
function AddToCartButton({ product }: { product: { id: number, name: string, price: number } }) {
  return (
    <button onClick={() => {
      // Initialize cart if not exists
      if (!state.cart) {
        state.cart = []
      }

      // Add item or increment quantity
      const existing = state.cart.find(item => item.id === product.id)
      if (existing) {
        existing.quantity++
      } else {
        state.cart.push({
          id: product.id,
          name: product.name,
          price: product.price,
          quantity: 1
        })
      }
    }}>
      Add to Cart
    </button>
  )
}

// ------------------------------
// Notifications Component
// ------------------------------
function Notifications() {
  const [notifications, setNotifications] = useState<Notification[]>([])

  useObserver(() => {
    setNotifications(state.notifications || [])
  }, [state.notifications])

  const unread = notifications.filter(n => !n.read).length

  return (
    <div className="notifications">
      <span>🔔 {unread} unread</span>
      {notifications.map(n => (
        <div key={n.id} className={n.read ? 'read' : 'unread'}>
          {n.message}
        </div>
      ))}
    </div>
  )
}

// ------------------------------
// Settings Component
// ------------------------------
function Settings() {
  const [theme] = useState(state.theme)
  const [savedSettings, setSavedSettings] = useState<any>(null)

  // Load saved settings from store
  useEffect(() => {
    const settings = store.get('appSettings')
    if (settings) {
      setSavedSettings(settings)
    }
  }, [])

  const saveSettings = () => {
    store.set('appSettings', { theme: state.theme })
    alert('Settings saved!')
  }

  return (
    <div className="settings">
      <h2>Settings</h2>

      <label>
        Theme:
        <select
          value={theme}
          onChange={e => state.theme = e.target.value as 'light' | 'dark'}
        >
          <option value="light">Light</option>
          <option value="dark">Dark</option>
        </select>
      </label>

      <button onClick={saveSettings}>Save Settings</button>

      {savedSettings && (
        <p>Saved: {savedSettings.theme}</p>
      )}
    </div>
  )
}

// ============================================
// 4. MAIN APP COMPONENT
// ============================================

function App() {
  // Initialize default state
  useEffect(() => {
    // Load theme from store
    const savedTheme = store.get('appSettings')?.theme
    if (savedTheme) {
      state.theme = savedTheme
    } else {
      state.theme = 'light'
    }

    // Initialize notifications
    state.notifications = [
      { id: '1', message: 'Welcome to Memorio!', read: false },
      { id: '2', message: 'Check out our new features', read: false }
    ]

    // Check for returning user
    const lastUser = store.get('lastUser')
    if (lastUser) {
      console.debug('Welcome back,', lastUser)
    }
  }, [])

  return (
    <div className={`app app--${state.theme}`}>
      <Header />
      <main>
        {state.user ? (
          <>
            <UserProfile />
            <Cart />
            <Notifications />
            <Settings />

            <button onClick={() => {
              // Logout - clear user but keep settings
              state.user = null
            }}>
              Logout
            </button>
          </>
        ) : (
          <LoginForm />
        )}
      </main>
    </div>
  )
}

export default App

// ============================================
// 5. USAGE SUMMARY
// ============================================

/*
MEMORIO REACT USAGE GUIDE:

1. IMPORT ONCE (index.js or App.tsx):
   import 'memorio'

2. SET STATE:
   state.user = { name: 'Mario', email: 'mario@example.com' }
   state.theme = 'dark'
   state.cart = []

3. READ STATE:
   const value = state.user.name
   const theme = state.theme

4. REACT TO CHANGES:
   useObserver(() => {
     console.debug('State changed!')
   }, [state.user])

5. AUTO-DISCOVERY (watch all):
   useObserver(() => {
     console.debug(state.user, state.theme)
   })

6. PERSIST DATA:
   store.set('settings', { theme: 'dark' })
   const settings = store.get('settings')

7. SESSION DATA (cleared on tab close):
   session.set('token', 'abc123')
   const token = session.get('token')

8. CLEAR DATA:
   state.removeAll()     // Clear all state
   store.removeAll()     // Clear all persisted
   session.removeAll()   // Clear all session
*/
