'use client'

import { useEffect, useState, useCallback, useRef } from 'react'
import {
  Settings,
  Users,
  History,
  Loader2,
  Save,
  Search,
  Info,
  X,
  Award,
  Star,
  Crown,
  Gem,
  TrendingUp,
  Minus,
  Plus,
} from 'lucide-react'
import toast from 'react-hot-toast'
import Pagination, { PaginationData } from '@/components/Pagination'
import { formatCurrency } from '@/lib/utils'

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

interface LoyaltySettings {
  loyalty_enabled: boolean
  loyalty_points_per_amount: number
  loyalty_amount_per_point: number
  loyalty_redemption_value: number
  loyalty_min_redemption: number
  loyalty_max_redemption: number
}

interface LoyaltyMember {
  id: string
  name: string
  phone: string
  loyaltyPoints: number
  lifetimePoints: number
  tier: string
  totalSpent: number
}

interface LoyaltyTransaction {
  id: string
  createdAt: string
  customerName: string
  type: 'earn' | 'redeem' | 'adjust'
  points: number
  balanceBefore: number
  balanceAfter: number
  description: string
  orderNumber?: string | null
}

// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------

const tabs = [
  { id: 'settings' as const, label: 'Pengaturan', icon: Settings },
  { id: 'members' as const, label: 'Anggota', icon: Users },
  { id: 'transactions' as const, label: 'Riwayat', icon: History },
]

type TabType = 'settings' | 'members' | 'transactions'

const TIER_CONFIG = [
  { name: 'Member', icon: Award, color: 'bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300', multiplier: '1x', requirement: 'Default' },
  { name: 'Silver', icon: Star, color: 'bg-slate-200 text-slate-700 dark:bg-slate-700 dark:text-slate-300', multiplier: '1.25x', requirement: '100 poin' },
  { name: 'Gold', icon: Crown, color: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300', multiplier: '1.5x', requirement: '500 poin' },
  { name: 'Platinum', icon: Gem, color: 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-300', multiplier: '2x', requirement: '1000 poin' },
]

const TIER_BADGE_COLORS: Record<string, string> = {
  member: 'bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300',
  silver: 'bg-slate-200 text-slate-700 dark:bg-slate-700 dark:text-slate-300',
  gold: 'bg-amber-100 text-amber-700 dark:bg-amber-900/30 dark:text-amber-300',
  platinum: 'bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-300',
}

const TYPE_BADGE_COLORS: Record<string, { label: string; color: string }> = {
  earn: { label: 'Earn', color: 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300' },
  redeem: { label: 'Redeem', color: 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-300' },
  adjust: { label: 'Adjust', color: 'bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300' },
}

const TRANSACTION_FILTERS = [
  { id: '', label: 'Semua' },
  { id: 'earn', label: 'Earn' },
  { id: 'redeem', label: 'Redeem' },
  { id: 'adjust', label: 'Adjust' },
]

const DEFAULT_SETTINGS: LoyaltySettings = {
  loyalty_enabled: false,
  loyalty_points_per_amount: 1,
  loyalty_amount_per_point: 10000,
  loyalty_redemption_value: 500,
  loyalty_min_redemption: 10,
  loyalty_max_redemption: 0,
}

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function formatDate(dateStr: string) {
  return new Date(dateStr).toLocaleDateString('id-ID', {
    day: '2-digit',
    month: 'short',
    year: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  })
}

// ---------------------------------------------------------------------------
// Component
// ---------------------------------------------------------------------------

export default function LoyaltyPage() {
  const [activeTab, setActiveTab] = useState<TabType>('settings')

  // ---- Settings state -----------------------------------------------------
  const [settings, setSettings] = useState<LoyaltySettings>({ ...DEFAULT_SETTINGS })
  const [settingsLoading, setSettingsLoading] = useState(true)
  const [settingsSaving, setSettingsSaving] = useState(false)

  // ---- Members state ------------------------------------------------------
  const [members, setMembers] = useState<LoyaltyMember[]>([])
  const [membersLoading, setMembersLoading] = useState(false)
  const [memberSearch, setMemberSearch] = useState('')
  const [memberPagination, setMemberPagination] = useState<PaginationData>({
    page: 1,
    limit: 20,
    total: 0,
    totalPages: 0,
  })

  // ---- Adjust modal state -------------------------------------------------
  const [adjustTarget, setAdjustTarget] = useState<LoyaltyMember | null>(null)
  const [adjustPoints, setAdjustPoints] = useState('')
  const [adjustReason, setAdjustReason] = useState('')
  const [adjustSaving, setAdjustSaving] = useState(false)

  // ---- Transactions state -------------------------------------------------
  const [transactions, setTransactions] = useState<LoyaltyTransaction[]>([])
  const [transactionsLoading, setTransactionsLoading] = useState(false)
  const [transactionFilter, setTransactionFilter] = useState('')
  const [transactionPagination, setTransactionPagination] = useState<PaginationData>({
    page: 1,
    limit: 20,
    total: 0,
    totalPages: 0,
  })

  // ---- Debounce ref -------------------------------------------------------
  const searchTimeout = useRef<ReturnType<typeof setTimeout> | null>(null)

  // =========================================================================
  // Data Fetching
  // =========================================================================

  const fetchSettings = useCallback(async () => {
    setSettingsLoading(true)
    try {
      const res = await fetch('/api/loyalty/settings')
      if (!res.ok) throw new Error('Gagal memuat pengaturan loyalti')
      const data = await res.json()
      if (data.settings) {
        setSettings({
          loyalty_enabled: data.settings.loyalty_enabled ?? false,
          loyalty_points_per_amount: data.settings.loyalty_points_per_amount ?? 1,
          loyalty_amount_per_point: data.settings.loyalty_amount_per_point ?? 10000,
          loyalty_redemption_value: data.settings.loyalty_redemption_value ?? 500,
          loyalty_min_redemption: data.settings.loyalty_min_redemption ?? 10,
          loyalty_max_redemption: data.settings.loyalty_max_redemption ?? 0,
        })
      }
    } catch (err: any) {
      toast.error(err.message || 'Gagal memuat pengaturan loyalti')
    } finally {
      setSettingsLoading(false)
    }
  }, [])

  const fetchMembers = useCallback(
    async (page = 1, searchQuery = memberSearch) => {
      setMembersLoading(true)
      try {
        const params = new URLSearchParams()
        params.set('page', String(page))
        params.set('limit', '20')
        if (searchQuery) params.set('search', searchQuery)

        const res = await fetch(`/api/loyalty/members?${params}`)
        if (!res.ok) throw new Error('Gagal memuat data anggota')
        const data = await res.json()

        setMembers(data.members || [])
        if (data.pagination) setMemberPagination(data.pagination)
      } catch (err: any) {
        toast.error(err.message || 'Gagal memuat data anggota')
      } finally {
        setMembersLoading(false)
      }
    },
    [memberSearch]
  )

  const fetchTransactions = useCallback(
    async (page = 1, typeFilter = transactionFilter) => {
      setTransactionsLoading(true)
      try {
        const params = new URLSearchParams()
        params.set('page', String(page))
        params.set('limit', '20')
        if (typeFilter) params.set('type', typeFilter)

        const res = await fetch(`/api/loyalty/transactions?${params}`)
        if (!res.ok) throw new Error('Gagal memuat riwayat transaksi')
        const data = await res.json()

        setTransactions(data.transactions || [])
        if (data.pagination) setTransactionPagination(data.pagination)
      } catch (err: any) {
        toast.error(err.message || 'Gagal memuat riwayat transaksi')
      } finally {
        setTransactionsLoading(false)
      }
    },
    [transactionFilter]
  )

  // =========================================================================
  // Effects
  // =========================================================================

  // Load settings on mount
  useEffect(() => {
    fetchSettings()
  }, [fetchSettings])

  // Load members when tab switches to members
  useEffect(() => {
    if (activeTab === 'members') {
      fetchMembers(1, memberSearch)
    }
  }, [activeTab]) // eslint-disable-line react-hooks/exhaustive-deps

  // Load transactions when tab switches to transactions
  useEffect(() => {
    if (activeTab === 'transactions') {
      fetchTransactions(1, transactionFilter)
    }
  }, [activeTab]) // eslint-disable-line react-hooks/exhaustive-deps

  // Debounced member search
  useEffect(() => {
    if (activeTab !== 'members') return
    if (searchTimeout.current) clearTimeout(searchTimeout.current)
    searchTimeout.current = setTimeout(() => {
      fetchMembers(1, memberSearch)
    }, 300)
    return () => {
      if (searchTimeout.current) clearTimeout(searchTimeout.current)
    }
  }, [memberSearch]) // eslint-disable-line react-hooks/exhaustive-deps

  // Refetch transactions when filter changes
  useEffect(() => {
    if (activeTab !== 'transactions') return
    fetchTransactions(1, transactionFilter)
  }, [transactionFilter]) // eslint-disable-line react-hooks/exhaustive-deps

  // =========================================================================
  // Handlers
  // =========================================================================

  const handleSaveSettings = async () => {
    setSettingsSaving(true)
    try {
      const res = await fetch('/api/loyalty/settings', {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(settings),
      })
      if (!res.ok) {
        const errData = await res.json().catch(() => ({}))
        throw new Error(errData.error || 'Gagal menyimpan pengaturan')
      }
      toast.success('Pengaturan loyalti berhasil disimpan')
    } catch (err: any) {
      toast.error(err.message || 'Gagal menyimpan pengaturan')
    } finally {
      setSettingsSaving(false)
    }
  }

  const handleToggleEnabled = () => {
    setSettings((s) => ({ ...s, loyalty_enabled: !s.loyalty_enabled }))
  }

  const handleSettingChange = (key: keyof LoyaltySettings, value: number) => {
    setSettings((s) => ({ ...s, [key]: value }))
  }

  const openAdjustModal = (member: LoyaltyMember) => {
    setAdjustTarget(member)
    setAdjustPoints('')
    setAdjustReason('')
  }

  const handleAdjustSubmit = async (e: React.FormEvent) => {
    e.preventDefault()
    if (!adjustTarget) return

    const points = parseInt(adjustPoints, 10)
    if (isNaN(points) || points === 0) {
      toast.error('Jumlah poin harus diisi dan tidak boleh 0')
      return
    }
    if (!adjustReason.trim()) {
      toast.error('Keterangan wajib diisi')
      return
    }

    setAdjustSaving(true)
    try {
      const res = await fetch(`/api/loyalty/members/${adjustTarget.id}/adjust`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          points,
          description: adjustReason.trim(),
        }),
      })
      if (!res.ok) {
        const errData = await res.json().catch(() => ({}))
        throw new Error(errData.error || 'Gagal menyesuaikan poin')
      }
      toast.success('Poin berhasil disesuaikan')
      setAdjustTarget(null)
      fetchMembers(memberPagination.page, memberSearch)
    } catch (err: any) {
      toast.error(err.message || 'Gagal menyesuaikan poin')
    } finally {
      setAdjustSaving(false)
    }
  }

  // =========================================================================
  // Computed values
  // =========================================================================

  const summaryPointsEarned = settings.loyalty_points_per_amount
  const summaryAmountSpent = settings.loyalty_amount_per_point
  const summaryRedemptionValue = settings.loyalty_points_per_amount * settings.loyalty_redemption_value

  // =========================================================================
  // Render helpers
  // =========================================================================

  const renderTierBadge = (tier: string) => {
    const key = tier.toLowerCase()
    const color = TIER_BADGE_COLORS[key] || TIER_BADGE_COLORS.member
    return (
      <span className={`text-xs px-2 py-0.5 rounded-full font-medium ${color}`}>
        {tier.charAt(0).toUpperCase() + tier.slice(1)}
      </span>
    )
  }

  const renderTypeBadge = (type: string) => {
    const info = TYPE_BADGE_COLORS[type] || { label: type, color: 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300' }
    return (
      <span className={`text-xs px-2 py-0.5 rounded-full font-medium ${info.color}`}>
        {info.label}
      </span>
    )
  }

  // =========================================================================
  // Tab: Pengaturan (Settings)
  // =========================================================================

  const renderSettingsTab = () => {
    if (settingsLoading) {
      return (
        <div className="flex items-center justify-center h-64">
          <Loader2 className="w-8 h-8 animate-spin text-gray-400" />
        </div>
      )
    }

    return (
      <div className="space-y-6 mt-6">
        {/* Toggle: Enable loyalty */}
        <div className="card">
          <div className="flex items-center justify-between">
            <div>
              <h3 className="text-base font-semibold text-gray-900 dark:text-white">
                Aktifkan Program Loyalti
              </h3>
              <p className="text-sm text-gray-500 dark:text-gray-400 mt-0.5">
                Pelanggan akan mendapatkan poin dari setiap transaksi.
              </p>
            </div>
            <button
              onClick={handleToggleEnabled}
              className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors flex-shrink-0 ${
                settings.loyalty_enabled
                  ? 'bg-primary-600'
                  : 'bg-gray-300 dark:bg-gray-600'
              }`}
            >
              <span
                className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
                  settings.loyalty_enabled ? 'translate-x-6' : 'translate-x-1'
                }`}
              />
            </button>
          </div>
        </div>

        {/* Points configuration */}
        <div className="card">
          <h3 className="text-base font-semibold text-gray-900 dark:text-white mb-4">
            Konfigurasi Poin
          </h3>
          <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
            {/* Points per amount */}
            <div>
              <label className="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
                Poin yang diberikan
              </label>
              <input
                type="number"
                min={1}
                className="input-field"
                value={settings.loyalty_points_per_amount}
                onChange={(e) =>
                  handleSettingChange(
                    'loyalty_points_per_amount',
                    parseInt(e.target.value, 10) || 1
                  )
                }
              />
              <p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
                Jumlah poin yang didapat per transaksi
              </p>
            </div>

            {/* Amount per point */}
            <div>
              <label className="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
                Per belanja Rp
              </label>
              <input
                type="number"
                min={1000}
                step={1000}
                className="input-field"
                value={settings.loyalty_amount_per_point}
                onChange={(e) =>
                  handleSettingChange(
                    'loyalty_amount_per_point',
                    parseInt(e.target.value, 10) || 10000
                  )
                }
              />
              <p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
                Jumlah belanja minimum untuk mendapat poin
              </p>
            </div>

            {/* Redemption value */}
            <div>
              <label className="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
                Nilai tukar per poin (Rp)
              </label>
              <input
                type="number"
                min={1}
                className="input-field"
                value={settings.loyalty_redemption_value}
                onChange={(e) =>
                  handleSettingChange(
                    'loyalty_redemption_value',
                    parseInt(e.target.value, 10) || 500
                  )
                }
              />
              <p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
                Nilai rupiah untuk setiap 1 poin yang ditukar
              </p>
            </div>

            {/* Min redemption */}
            <div>
              <label className="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
                Minimum poin untuk redeem
              </label>
              <input
                type="number"
                min={1}
                className="input-field"
                value={settings.loyalty_min_redemption}
                onChange={(e) =>
                  handleSettingChange(
                    'loyalty_min_redemption',
                    parseInt(e.target.value, 10) || 10
                  )
                }
              />
              <p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
                Poin minimum yang bisa ditukar
              </p>
            </div>

            {/* Max redemption */}
            <div className="sm:col-span-2">
              <label className="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
                Maksimum poin per order (0 = unlimited)
              </label>
              <input
                type="number"
                min={0}
                className="input-field"
                value={settings.loyalty_max_redemption}
                onChange={(e) =>
                  handleSettingChange(
                    'loyalty_max_redemption',
                    parseInt(e.target.value, 10) || 0
                  )
                }
              />
              <p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
                Batas maksimum poin yang dapat ditukar dalam satu pesanan. Isi 0 untuk tanpa batas.
              </p>
            </div>
          </div>
        </div>

        {/* Summary info card */}
        <div className="card border-l-4 border-l-primary-500 bg-primary-50/50 dark:bg-primary-900/10">
          <div className="flex gap-3">
            <Info className="w-5 h-5 text-primary-600 dark:text-primary-400 flex-shrink-0 mt-0.5" />
            <div>
              <h4 className="text-sm font-semibold text-gray-900 dark:text-white mb-1">
                Ringkasan Program
              </h4>
              <p className="text-sm text-gray-700 dark:text-gray-300">
                Pelanggan mendapat{' '}
                <span className="font-bold text-primary-600 dark:text-primary-400">
                  {summaryPointsEarned} poin
                </span>{' '}
                setiap belanja{' '}
                <span className="font-bold text-primary-600 dark:text-primary-400">
                  {formatCurrency(summaryAmountSpent)}
                </span>
                .{' '}
                <span className="font-bold text-primary-600 dark:text-primary-400">
                  {summaryPointsEarned} poin
                </span>{' '}
                dapat ditukar dengan diskon{' '}
                <span className="font-bold text-primary-600 dark:text-primary-400">
                  {formatCurrency(summaryRedemptionValue)}
                </span>
                .
              </p>
            </div>
          </div>
        </div>

        {/* Tier info card */}
        <div className="card">
          <div className="flex items-center gap-2 mb-4">
            <TrendingUp className="w-5 h-5 text-primary-600 dark:text-primary-400" />
            <h3 className="text-base font-semibold text-gray-900 dark:text-white">
              Tier & Multiplier
            </h3>
          </div>
          <div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
            {TIER_CONFIG.map((tier) => {
              const TierIcon = tier.icon
              return (
                <div
                  key={tier.name}
                  className="rounded-lg border border-gray-200 dark:border-gray-700 p-3 text-center"
                >
                  <div
                    className={`w-10 h-10 rounded-full ${tier.color} flex items-center justify-center mx-auto mb-2`}
                  >
                    <TierIcon className="w-5 h-5" />
                  </div>
                  <p className="text-sm font-semibold text-gray-900 dark:text-white">
                    {tier.name}
                  </p>
                  <p className="text-xs text-gray-500 dark:text-gray-400 mt-0.5">
                    {tier.requirement}
                  </p>
                  <p className="text-sm font-bold text-primary-600 dark:text-primary-400 mt-1">
                    {tier.multiplier}
                  </p>
                </div>
              )
            })}
          </div>
        </div>

        {/* Save button */}
        <div className="flex justify-end">
          <button
            onClick={handleSaveSettings}
            disabled={settingsSaving}
            className="btn-primary"
          >
            {settingsSaving ? (
              <Loader2 className="w-4 h-4 animate-spin inline mr-2" />
            ) : (
              <Save className="w-4 h-4 inline mr-2" />
            )}
            Simpan Pengaturan
          </button>
        </div>
      </div>
    )
  }

  // =========================================================================
  // Tab: Anggota (Members)
  // =========================================================================

  const renderMembersTab = () => {
    return (
      <div className="space-y-4 mt-6">
        {/* Search */}
        <div className="relative">
          <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-400 dark:text-gray-500" />
          <input
            type="text"
            placeholder="Cari nama atau no. HP..."
            className="input-field pl-10"
            value={memberSearch}
            onChange={(e) => setMemberSearch(e.target.value)}
          />
        </div>

        {/* Members table */}
        <div className="card overflow-hidden">
          {membersLoading ? (
            <div className="flex items-center justify-center py-16">
              <Loader2 className="w-8 h-8 animate-spin text-gray-400" />
            </div>
          ) : (
            <>
              <div className="overflow-x-auto">
                <table className="w-full text-sm">
                  <thead>
                    <tr className="border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-700/50">
                      <th className="text-left py-3 px-4 font-medium text-gray-600 dark:text-gray-300">
                        Nama
                      </th>
                      <th className="text-left py-3 px-4 font-medium text-gray-600 dark:text-gray-300">
                        Telepon
                      </th>
                      <th className="text-right py-3 px-4 font-medium text-gray-600 dark:text-gray-300">
                        Poin Saat Ini
                      </th>
                      <th className="text-right py-3 px-4 font-medium text-gray-600 dark:text-gray-300 hidden md:table-cell">
                        Lifetime Poin
                      </th>
                      <th className="text-left py-3 px-4 font-medium text-gray-600 dark:text-gray-300">
                        Tier
                      </th>
                      <th className="text-right py-3 px-4 font-medium text-gray-600 dark:text-gray-300 hidden lg:table-cell">
                        Total Belanja
                      </th>
                      <th className="text-right py-3 px-4 font-medium text-gray-600 dark:text-gray-300">
                        Aksi
                      </th>
                    </tr>
                  </thead>
                  <tbody>
                    {members.length > 0 ? (
                      members.map((member) => (
                        <tr
                          key={member.id}
                          className="border-b border-gray-100 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors"
                        >
                          <td className="py-3 px-4 font-medium text-gray-900 dark:text-white">
                            {member.name}
                          </td>
                          <td className="py-3 px-4 text-gray-600 dark:text-gray-300">
                            {member.phone}
                          </td>
                          <td className="py-3 px-4 text-right font-semibold text-gray-900 dark:text-white">
                            {member.loyaltyPoints.toLocaleString('id-ID')}
                          </td>
                          <td className="py-3 px-4 text-right text-gray-600 dark:text-gray-300 hidden md:table-cell">
                            {member.lifetimePoints.toLocaleString('id-ID')}
                          </td>
                          <td className="py-3 px-4">
                            {renderTierBadge(member.tier)}
                          </td>
                          <td className="py-3 px-4 text-right text-gray-900 dark:text-white hidden lg:table-cell">
                            {formatCurrency(member.totalSpent)}
                          </td>
                          <td className="py-3 px-4 text-right">
                            <button
                              onClick={() => openAdjustModal(member)}
                              className="btn-secondary text-xs px-3 py-1.5"
                            >
                              Sesuaikan Poin
                            </button>
                          </td>
                        </tr>
                      ))
                    ) : (
                      <tr>
                        <td colSpan={7} className="py-16 text-center">
                          <div className="flex flex-col items-center gap-2">
                            <Users className="w-10 h-10 text-gray-300 dark:text-gray-600" />
                            <p className="text-gray-500 dark:text-gray-400">
                              {memberSearch
                                ? 'Tidak ada anggota yang cocok dengan pencarian.'
                                : 'Belum ada anggota program loyalti.'}
                            </p>
                          </div>
                        </td>
                      </tr>
                    )}
                  </tbody>
                </table>
              </div>
              {members.length > 0 && (
                <Pagination
                  pagination={memberPagination}
                  onPageChange={(page) => fetchMembers(page, memberSearch)}
                  itemLabel="anggota"
                />
              )}
            </>
          )}
        </div>
      </div>
    )
  }

  // =========================================================================
  // Tab: Riwayat (Transactions)
  // =========================================================================

  const renderTransactionsTab = () => {
    return (
      <div className="space-y-4 mt-6">
        {/* Filter buttons */}
        <div className="flex flex-wrap gap-2">
          {TRANSACTION_FILTERS.map((filter) => (
            <button
              key={filter.id}
              onClick={() => setTransactionFilter(filter.id)}
              className={`px-4 py-2 text-sm font-medium rounded-lg transition-colors ${
                transactionFilter === filter.id
                  ? 'bg-primary-600 text-white'
                  : 'bg-gray-100 text-gray-700 hover:bg-gray-200 dark:bg-gray-700 dark:text-gray-300 dark:hover:bg-gray-600'
              }`}
            >
              {filter.label}
            </button>
          ))}
        </div>

        {/* Transactions table */}
        <div className="card overflow-hidden">
          {transactionsLoading ? (
            <div className="flex items-center justify-center py-16">
              <Loader2 className="w-8 h-8 animate-spin text-gray-400" />
            </div>
          ) : (
            <>
              <div className="overflow-x-auto">
                <table className="w-full text-sm">
                  <thead>
                    <tr className="border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-700/50">
                      <th className="text-left py-3 px-4 font-medium text-gray-600 dark:text-gray-300">
                        Tanggal
                      </th>
                      <th className="text-left py-3 px-4 font-medium text-gray-600 dark:text-gray-300">
                        Pelanggan
                      </th>
                      <th className="text-left py-3 px-4 font-medium text-gray-600 dark:text-gray-300">
                        Tipe
                      </th>
                      <th className="text-right py-3 px-4 font-medium text-gray-600 dark:text-gray-300">
                        Poin
                      </th>
                      <th className="text-right py-3 px-4 font-medium text-gray-600 dark:text-gray-300 hidden md:table-cell">
                        Saldo Sebelum
                      </th>
                      <th className="text-right py-3 px-4 font-medium text-gray-600 dark:text-gray-300 hidden md:table-cell">
                        Saldo Sesudah
                      </th>
                      <th className="text-left py-3 px-4 font-medium text-gray-600 dark:text-gray-300 hidden lg:table-cell">
                        Keterangan
                      </th>
                      <th className="text-left py-3 px-4 font-medium text-gray-600 dark:text-gray-300 hidden lg:table-cell">
                        Order#
                      </th>
                    </tr>
                  </thead>
                  <tbody>
                    {transactions.length > 0 ? (
                      transactions.map((tx) => (
                        <tr
                          key={tx.id}
                          className="border-b border-gray-100 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors"
                        >
                          <td className="py-3 px-4 text-gray-600 dark:text-gray-300 text-xs whitespace-nowrap">
                            {formatDate(tx.createdAt)}
                          </td>
                          <td className="py-3 px-4 font-medium text-gray-900 dark:text-white">
                            {tx.customerName}
                          </td>
                          <td className="py-3 px-4">
                            {renderTypeBadge(tx.type)}
                          </td>
                          <td className="py-3 px-4 text-right font-semibold">
                            <span
                              className={
                                tx.points > 0
                                  ? 'text-green-600 dark:text-green-400'
                                  : tx.points < 0
                                  ? 'text-red-600 dark:text-red-400'
                                  : 'text-gray-600 dark:text-gray-300'
                              }
                            >
                              {tx.points > 0 ? '+' : ''}
                              {tx.points.toLocaleString('id-ID')}
                            </span>
                          </td>
                          <td className="py-3 px-4 text-right text-gray-600 dark:text-gray-300 hidden md:table-cell">
                            {tx.balanceBefore.toLocaleString('id-ID')}
                          </td>
                          <td className="py-3 px-4 text-right text-gray-600 dark:text-gray-300 hidden md:table-cell">
                            {tx.balanceAfter.toLocaleString('id-ID')}
                          </td>
                          <td className="py-3 px-4 text-gray-600 dark:text-gray-300 text-xs hidden lg:table-cell max-w-[200px] truncate">
                            {tx.description || '-'}
                          </td>
                          <td className="py-3 px-4 text-gray-500 dark:text-gray-400 text-xs font-mono hidden lg:table-cell">
                            {tx.orderNumber || '-'}
                          </td>
                        </tr>
                      ))
                    ) : (
                      <tr>
                        <td colSpan={8} className="py-16 text-center">
                          <div className="flex flex-col items-center gap-2">
                            <History className="w-10 h-10 text-gray-300 dark:text-gray-600" />
                            <p className="text-gray-500 dark:text-gray-400">
                              {transactionFilter
                                ? 'Tidak ada transaksi dengan tipe ini.'
                                : 'Belum ada riwayat transaksi loyalti.'}
                            </p>
                          </div>
                        </td>
                      </tr>
                    )}
                  </tbody>
                </table>
              </div>
              {transactions.length > 0 && (
                <Pagination
                  pagination={transactionPagination}
                  onPageChange={(page) => fetchTransactions(page, transactionFilter)}
                  itemLabel="transaksi"
                />
              )}
            </>
          )}
        </div>
      </div>
    )
  }

  // =========================================================================
  // Main Render
  // =========================================================================

  return (
    <div>
      {/* Header */}
      <div className="mb-6">
        <h1 className="text-2xl font-bold text-gray-900 dark:text-white">
          Program Loyalti
        </h1>
        <p className="text-gray-600 dark:text-gray-300 mt-1">
          Kelola program poin loyalti untuk pelanggan setia Anda.
        </p>
      </div>

      {/* Tabs */}
      <div className="border-b border-gray-200 dark:border-gray-700">
        <nav className="flex gap-4 -mb-px overflow-x-auto">
          {tabs.map((tab) => {
            const TabIcon = tab.icon
            return (
              <button
                key={tab.id}
                onClick={() => setActiveTab(tab.id)}
                className={`py-3 px-1 text-sm font-medium border-b-2 transition-colors whitespace-nowrap flex items-center gap-2 ${
                  activeTab === tab.id
                    ? 'border-primary-500 text-primary-600 dark:text-primary-400'
                    : 'border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300'
                }`}
              >
                <TabIcon className="w-4 h-4" />
                {tab.label}
              </button>
            )
          })}
        </nav>
      </div>

      {/* Tab content */}
      {activeTab === 'settings' && renderSettingsTab()}
      {activeTab === 'members' && renderMembersTab()}
      {activeTab === 'transactions' && renderTransactionsTab()}

      {/* ------------------------------------------------------------------- */}
      {/* Adjust Points Modal                                                  */}
      {/* ------------------------------------------------------------------- */}
      {adjustTarget && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4">
          <div className="bg-white dark:bg-gray-800 rounded-xl w-full max-w-md p-6">
            {/* Modal header */}
            <div className="flex items-center justify-between mb-4">
              <h3 className="text-lg font-semibold dark:text-white">
                Sesuaikan Poin
              </h3>
              <button
                onClick={() => setAdjustTarget(null)}
                className="text-gray-400 hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-300"
              >
                <X className="w-5 h-5" />
              </button>
            </div>

            {/* Customer info */}
            <div className="bg-gray-50 dark:bg-gray-700/50 rounded-lg p-3 mb-4">
              <p className="text-sm text-gray-500 dark:text-gray-400">Pelanggan</p>
              <p className="text-base font-semibold text-gray-900 dark:text-white">
                {adjustTarget.name}
              </p>
              <p className="text-sm text-gray-600 dark:text-gray-300 mt-1">
                Poin saat ini:{' '}
                <span className="font-bold">
                  {adjustTarget.loyaltyPoints.toLocaleString('id-ID')}
                </span>
              </p>
            </div>

            {/* Form */}
            <form onSubmit={handleAdjustSubmit} className="space-y-4">
              {/* Points input */}
              <div>
                <label className="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
                  Jumlah Poin <span className="text-red-500">*</span>
                </label>
                <input
                  type="number"
                  className="input-field"
                  value={adjustPoints}
                  onChange={(e) => setAdjustPoints(e.target.value)}
                  placeholder="Contoh: 50 atau -20"
                  required
                />
                <p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
                  Gunakan angka negatif untuk mengurangi poin (misal: -50)
                </p>
              </div>

              {/* Reason input */}
              <div>
                <label className="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
                  Keterangan <span className="text-red-500">*</span>
                </label>
                <input
                  type="text"
                  className="input-field"
                  value={adjustReason}
                  onChange={(e) => setAdjustReason(e.target.value)}
                  placeholder="Alasan penyesuaian poin"
                  required
                />
              </div>

              {/* Preview */}
              {adjustPoints && !isNaN(parseInt(adjustPoints, 10)) && parseInt(adjustPoints, 10) !== 0 && (
                <div className="bg-gray-50 dark:bg-gray-700/50 rounded-lg p-3">
                  <div className="flex items-center justify-between text-sm">
                    <span className="text-gray-600 dark:text-gray-300">Saldo setelah penyesuaian:</span>
                    <span className="font-bold text-gray-900 dark:text-white">
                      {(adjustTarget.loyaltyPoints + parseInt(adjustPoints, 10)).toLocaleString('id-ID')} poin
                    </span>
                  </div>
                </div>
              )}

              {/* Actions */}
              <div className="flex gap-2 justify-end pt-2">
                <button
                  type="button"
                  onClick={() => setAdjustTarget(null)}
                  className="btn-secondary"
                >
                  Batal
                </button>
                <button type="submit" disabled={adjustSaving} className="btn-primary">
                  {adjustSaving ? (
                    <Loader2 className="w-4 h-4 animate-spin" />
                  ) : (
                    'Simpan'
                  )}
                </button>
              </div>
            </form>
          </div>
        </div>
      )}
    </div>
  )
}
