'use client'

import { useEffect, useState, useCallback, useRef } from 'react'
import {
  Wallet,
  List,
  Tags,
  BarChart3,
  Loader2,
  Search,
  Plus,
  X,
  Pencil,
  Trash2,
  CheckCircle,
  XCircle,
  Eye,
  Filter,
  TrendingUp,
  Clock,
  DollarSign,
  ToggleLeft,
  ToggleRight,
} from 'lucide-react'
import toast from 'react-hot-toast'
import Pagination, { PaginationData } from '@/components/Pagination'
import { EXPENSE_STATUSES, EXPENSE_PAYMENT_METHODS } from '@/lib/constants'
import { useAuthStore } from '@/store/auth-store'
import { useFeatureGuard } from '@/hooks/useFeatureGuard'

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

interface Store {
  id: string
  name: string
}

interface ExpenseCategory {
  id: string
  name: string
  icon: string | null
  isActive: boolean
  sortOrder: number
  _count: { expenses: number }
}

interface Expense {
  id: string
  amount: number
  description: string
  date: string
  status: string
  paymentMethod: string | null
  vendor: string | null
  receiptNumber: string | null
  notes: string | null
  rejectReason: string | null
  categoryId: string
  storeId: string
  createdAt: string
  category: { id: string; name: string } | null
  store: { id: string; name: string } | null
  createdBy: { id: string; name: string } | null
}

interface ExpenseStats {
  totalAmount: number
  pendingCount: number
  pendingAmount: number
}

interface SummaryByCategory {
  categoryId: string
  categoryName: string
  total: number
  count: number
}

interface SummaryByMonth {
  month: string
  total: number
  count: number
}

interface ExpenseSummary {
  byCategory: SummaryByCategory[]
  byMonth: SummaryByMonth[]
  grandTotal: number
  totalCount: number
}

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

const tabs = [
  { id: 'list' as const, label: 'Daftar Pengeluaran', icon: List },
  { id: 'categories' as const, label: 'Kategori', icon: Tags },
  { id: 'reports' as const, label: 'Laporan', icon: BarChart3 },
]

type TabType = 'list' | 'categories' | 'reports'

const REPORT_PERIODS = [
  { id: 'this_month', label: 'Bulan Ini' },
  { id: 'last_month', label: 'Bulan Lalu' },
  { id: '3_months', label: '3 Bulan Terakhir' },
  { id: '6_months', label: '6 Bulan Terakhir' },
  { id: 'custom', label: 'Kustom' },
]

const CHART_COLORS = [
  'bg-blue-500',
  'bg-green-500',
  'bg-yellow-500',
  'bg-red-500',
  'bg-purple-500',
  'bg-pink-500',
  'bg-indigo-500',
  'bg-orange-500',
  'bg-teal-500',
  'bg-cyan-500',
  'bg-lime-500',
  'bg-amber-500',
  'bg-rose-500',
  'bg-emerald-500',
]

const CHART_COLORS_HEX = [
  '#3b82f6',
  '#22c55e',
  '#eab308',
  '#ef4444',
  '#a855f7',
  '#ec4899',
  '#6366f1',
  '#f97316',
  '#14b8a6',
  '#06b6d4',
  '#84cc16',
  '#f59e0b',
  '#f43f5e',
  '#10b981',
]

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

function todayStr() {
  return new Date().toISOString().slice(0, 10)
}

function formatCurrency(amount: number) {
  return 'Rp ' + new Intl.NumberFormat('id-ID').format(amount)
}

function formatDate(dateStr: string) {
  const d = dateStr.slice(0, 10)
  return new Date(d + 'T00:00:00').toLocaleDateString('id-ID', {
    day: '2-digit',
    month: 'short',
    year: 'numeric',
  })
}

function firstDayOfMonth(date: Date) {
  return new Date(date.getFullYear(), date.getMonth(), 1).toISOString().slice(0, 10)
}

function lastDayOfMonth(date: Date) {
  return new Date(date.getFullYear(), date.getMonth() + 1, 0).toISOString().slice(0, 10)
}

function getReportDateRange(periodId: string): { dateFrom: string; dateTo: string } {
  const now = new Date()
  switch (periodId) {
    case 'this_month':
      return { dateFrom: firstDayOfMonth(now), dateTo: todayStr() }
    case 'last_month': {
      const lastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1)
      return { dateFrom: firstDayOfMonth(lastMonth), dateTo: lastDayOfMonth(lastMonth) }
    }
    case '3_months': {
      const threeAgo = new Date(now.getFullYear(), now.getMonth() - 2, 1)
      return { dateFrom: firstDayOfMonth(threeAgo), dateTo: todayStr() }
    }
    case '6_months': {
      const sixAgo = new Date(now.getFullYear(), now.getMonth() - 5, 1)
      return { dateFrom: firstDayOfMonth(sixAgo), dateTo: todayStr() }
    }
    default:
      return { dateFrom: firstDayOfMonth(now), dateTo: todayStr() }
  }
}

function monthLabel(monthStr: string) {
  // monthStr is "YYYY-MM"
  const months = ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agu', 'Sep', 'Okt', 'Nov', 'Des']
  const parts = monthStr.split('-')
  const mIdx = parseInt(parts[1], 10) - 1
  return months[mIdx] || monthStr
}

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

export default function ExpensesPage() {
  const { user } = useAuthStore()
  const { allowed, loading: featureLoading, planName } = useFeatureGuard('expenses')

  const [activeTab, setActiveTab] = useState<TabType>('list')

  // ---- Store selector state ------------------------------------------------
  const [stores, setStores] = useState<Store[]>([])
  const [selectedStore, setSelectedStore] = useState('')
  const [storesLoading, setStoresLoading] = useState(true)

  // ---- Categories state (shared) -------------------------------------------
  const [categories, setCategories] = useState<ExpenseCategory[]>([])
  const [categoriesLoading, setCategoriesLoading] = useState(false)

  // ---- List tab state ------------------------------------------------------
  const [expenses, setExpenses] = useState<Expense[]>([])
  const [expensesLoading, setExpensesLoading] = useState(false)
  const [expenseStats, setExpenseStats] = useState<ExpenseStats>({ totalAmount: 0, pendingCount: 0, pendingAmount: 0 })
  const [expensePagination, setExpensePagination] = useState<PaginationData>({
    page: 1,
    limit: 20,
    total: 0,
    totalPages: 0,
  })
  const [filterDateFrom, setFilterDateFrom] = useState(() => firstDayOfMonth(new Date()))
  const [filterDateTo, setFilterDateTo] = useState(() => todayStr())
  const [filterCategory, setFilterCategory] = useState('')
  const [filterStatus, setFilterStatus] = useState('')
  const [filterSearch, setFilterSearch] = useState('')

  // ---- Create / Edit modal state -------------------------------------------
  const [showExpenseModal, setShowExpenseModal] = useState(false)
  const [editingExpense, setEditingExpense] = useState<Expense | null>(null)
  const [expenseForm, setExpenseForm] = useState({
    date: todayStr(),
    categoryId: '',
    amount: '',
    description: '',
    paymentMethod: 'cash',
    vendor: '',
    receiptNumber: '',
    notes: '',
  })
  const [formSaving, setFormSaving] = useState(false)

  // ---- Detail modal state --------------------------------------------------
  const [detailExpense, setDetailExpense] = useState<Expense | null>(null)

  // ---- Approve / Reject modal state ----------------------------------------
  const [approveRejectExpense, setApproveRejectExpense] = useState<Expense | null>(null)
  const [rejectReason, setRejectReason] = useState('')
  const [showRejectInput, setShowRejectInput] = useState(false)
  const [statusUpdating, setStatusUpdating] = useState(false)

  // ---- Delete confirm state ------------------------------------------------
  const [deletingExpenseId, setDeletingExpenseId] = useState<string | null>(null)
  const [deleteLoading, setDeleteLoading] = useState(false)

  // ---- Categories tab state ------------------------------------------------
  const [showCategoryModal, setShowCategoryModal] = useState(false)
  const [editingCategory, setEditingCategory] = useState<ExpenseCategory | null>(null)
  const [categoryForm, setCategoryForm] = useState({ name: '' })
  const [categorySaving, setCategorySaving] = useState(false)

  // ---- Reports tab state ---------------------------------------------------
  const [reportPeriod, setReportPeriod] = useState('this_month')
  const [reportDateFrom, setReportDateFrom] = useState(() => firstDayOfMonth(new Date()))
  const [reportDateTo, setReportDateTo] = useState(() => todayStr())
  const [reportStore, setReportStore] = useState('')
  const [reportData, setReportData] = useState<ExpenseSummary | null>(null)
  const [reportLoading, setReportLoading] = useState(false)

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

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

  const fetchStores = useCallback(async () => {
    setStoresLoading(true)
    try {
      const res = await fetch('/api/stores')
      if (!res.ok) throw new Error('Gagal memuat daftar toko')
      const data = await res.json()
      const storeList: Store[] = data.stores || []
      setStores(storeList)

      if (storeList.length > 0) {
        const userStoreId = user?.storeId
        if (userStoreId && storeList.find((s) => s.id === userStoreId)) {
          setSelectedStore(userStoreId)
        } else {
          setSelectedStore(storeList[0].id)
        }
      }
    } catch (err: any) {
      toast.error(err.message || 'Gagal memuat daftar toko')
    } finally {
      setStoresLoading(false)
    }
  }, [user?.storeId])

  const fetchCategories = useCallback(async () => {
    setCategoriesLoading(true)
    try {
      const res = await fetch('/api/expense-categories')
      if (!res.ok) throw new Error('Gagal memuat kategori')
      const data = await res.json()
      setCategories(data.categories || [])
    } catch (err: any) {
      toast.error(err.message || 'Gagal memuat kategori')
    } finally {
      setCategoriesLoading(false)
    }
  }, [])

  const fetchExpenses = useCallback(
    async (
      storeId: string,
      dateFrom: string,
      dateTo: string,
      categoryId: string,
      status: string,
      search: string,
      page = 1
    ) => {
      if (!storeId) return
      setExpensesLoading(true)
      try {
        const params = new URLSearchParams()
        params.set('storeId', storeId)
        params.set('page', String(page))
        params.set('limit', '20')
        if (dateFrom) params.set('dateFrom', dateFrom)
        if (dateTo) params.set('dateTo', dateTo)
        if (categoryId) params.set('categoryId', categoryId)
        if (status) params.set('status', status)
        if (search) params.set('search', search)

        const res = await fetch(`/api/expenses?${params}`)
        if (!res.ok) throw new Error('Gagal memuat data pengeluaran')
        const data = await res.json()
        setExpenses(data.expenses || [])
        if (data.pagination) setExpensePagination(data.pagination)
        if (data.stats) setExpenseStats(data.stats)
      } catch (err: any) {
        toast.error(err.message || 'Gagal memuat data pengeluaran')
      } finally {
        setExpensesLoading(false)
      }
    },
    []
  )

  const fetchReport = useCallback(async (storeId: string, dateFrom: string, dateTo: string) => {
    setReportLoading(true)
    try {
      const params = new URLSearchParams()
      if (storeId) params.set('storeId', storeId)
      if (dateFrom) params.set('dateFrom', dateFrom)
      if (dateTo) params.set('dateTo', dateTo)

      const res = await fetch(`/api/expenses/summary?${params}`)
      if (!res.ok) throw new Error('Gagal memuat laporan')
      const data = await res.json()
      setReportData(data)
    } catch (err: any) {
      toast.error(err.message || 'Gagal memuat laporan')
    } finally {
      setReportLoading(false)
    }
  }, [])

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

  // Load stores on mount
  useEffect(() => {
    fetchStores()
  }, [fetchStores])

  // Load categories on mount
  useEffect(() => {
    fetchCategories()
  }, [fetchCategories])

  // Load expenses when list tab is active and filters change
  useEffect(() => {
    if (activeTab === 'list' && selectedStore) {
      fetchExpenses(selectedStore, filterDateFrom, filterDateTo, filterCategory, filterStatus, filterSearch, 1)
    }
  }, [activeTab, selectedStore, filterDateFrom, filterDateTo, filterCategory, filterStatus]) // eslint-disable-line react-hooks/exhaustive-deps

  // Debounced search for list tab
  useEffect(() => {
    if (activeTab !== 'list' || !selectedStore) return
    if (searchTimeout.current) clearTimeout(searchTimeout.current)
    searchTimeout.current = setTimeout(() => {
      fetchExpenses(selectedStore, filterDateFrom, filterDateTo, filterCategory, filterStatus, filterSearch, 1)
    }, 300)
    return () => {
      if (searchTimeout.current) clearTimeout(searchTimeout.current)
    }
  }, [filterSearch]) // eslint-disable-line react-hooks/exhaustive-deps

  // Reload categories when tab switches to categories
  useEffect(() => {
    if (activeTab === 'categories') {
      fetchCategories()
    }
  }, [activeTab, fetchCategories])

  // Load report when tab switches to reports
  useEffect(() => {
    if (activeTab === 'reports') {
      const storeId = reportStore || selectedStore
      fetchReport(storeId, reportDateFrom, reportDateTo)
    }
  }, [activeTab]) // eslint-disable-line react-hooks/exhaustive-deps

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

  const refreshExpenses = () => {
    if (selectedStore) {
      fetchExpenses(
        selectedStore,
        filterDateFrom,
        filterDateTo,
        filterCategory,
        filterStatus,
        filterSearch,
        expensePagination.page
      )
    }
  }

  // ---- Expense CRUD --------------------------------------------------------

  const openCreateModal = () => {
    setEditingExpense(null)
    setExpenseForm({
      date: todayStr(),
      categoryId: categories.filter((c) => c.isActive).length > 0 ? '' : '',
      amount: '',
      description: '',
      paymentMethod: 'cash',
      vendor: '',
      receiptNumber: '',
      notes: '',
    })
    setShowExpenseModal(true)
  }

  const openEditModal = (expense: Expense) => {
    if (expense.status !== 'pending') {
      toast.error('Hanya pengeluaran berstatus Menunggu yang dapat diedit')
      return
    }
    setEditingExpense(expense)
    setExpenseForm({
      date: expense.date.slice(0, 10),
      categoryId: expense.categoryId,
      amount: String(expense.amount),
      description: expense.description,
      paymentMethod: expense.paymentMethod || 'cash',
      vendor: expense.vendor || '',
      receiptNumber: expense.receiptNumber || '',
      notes: expense.notes || '',
    })
    setShowExpenseModal(true)
  }

  const closeExpenseModal = () => {
    setShowExpenseModal(false)
    setEditingExpense(null)
  }

  const handleExpenseSubmit = async (e: React.FormEvent) => {
    e.preventDefault()
    if (!expenseForm.categoryId) {
      toast.error('Pilih kategori')
      return
    }
    if (!expenseForm.amount || Number(expenseForm.amount) <= 0) {
      toast.error('Masukkan jumlah yang valid')
      return
    }
    if (!expenseForm.description.trim()) {
      toast.error('Deskripsi wajib diisi')
      return
    }

    setFormSaving(true)
    try {
      const payload: any = {
        storeId: selectedStore,
        categoryId: expenseForm.categoryId,
        amount: Number(expenseForm.amount),
        description: expenseForm.description.trim(),
        date: expenseForm.date,
        paymentMethod: expenseForm.paymentMethod || null,
        vendor: expenseForm.vendor.trim() || null,
        receiptNumber: expenseForm.receiptNumber.trim() || null,
        notes: expenseForm.notes.trim() || null,
      }

      let res: Response
      if (editingExpense) {
        res = await fetch(`/api/expenses/${editingExpense.id}`, {
          method: 'PUT',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(payload),
        })
      } else {
        res = await fetch('/api/expenses', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(payload),
        })
      }

      if (!res.ok) {
        const errData = await res.json().catch(() => ({}))
        throw new Error(errData.error || 'Gagal menyimpan pengeluaran')
      }

      toast.success(editingExpense ? 'Pengeluaran berhasil diperbarui' : 'Pengeluaran berhasil ditambahkan')
      closeExpenseModal()
      refreshExpenses()
    } catch (err: any) {
      toast.error(err.message || 'Gagal menyimpan pengeluaran')
    } finally {
      setFormSaving(false)
    }
  }

  const handleDeleteExpense = async (id: string) => {
    setDeleteLoading(true)
    try {
      const res = await fetch(`/api/expenses/${id}`, { method: 'DELETE' })
      if (!res.ok) {
        const errData = await res.json().catch(() => ({}))
        throw new Error(errData.error || 'Gagal menghapus pengeluaran')
      }
      toast.success('Pengeluaran berhasil dihapus')
      setDeletingExpenseId(null)
      refreshExpenses()
    } catch (err: any) {
      toast.error(err.message || 'Gagal menghapus pengeluaran')
    } finally {
      setDeleteLoading(false)
    }
  }

  // ---- Approve / Reject ----------------------------------------------------

  const openApproveRejectModal = (expense: Expense) => {
    setApproveRejectExpense(expense)
    setRejectReason('')
    setShowRejectInput(false)
  }

  const handleApprove = async () => {
    if (!approveRejectExpense) return
    setStatusUpdating(true)
    try {
      const res = await fetch(`/api/expenses/${approveRejectExpense.id}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ status: 'approved' }),
      })
      if (!res.ok) {
        const errData = await res.json().catch(() => ({}))
        throw new Error(errData.error || 'Gagal menyetujui pengeluaran')
      }
      toast.success('Pengeluaran berhasil disetujui')
      setApproveRejectExpense(null)
      refreshExpenses()
    } catch (err: any) {
      toast.error(err.message || 'Gagal menyetujui pengeluaran')
    } finally {
      setStatusUpdating(false)
    }
  }

  const handleReject = async () => {
    if (!approveRejectExpense) return
    if (!rejectReason.trim()) {
      toast.error('Masukkan alasan penolakan')
      return
    }
    setStatusUpdating(true)
    try {
      const res = await fetch(`/api/expenses/${approveRejectExpense.id}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ status: 'rejected', rejectReason: rejectReason.trim() }),
      })
      if (!res.ok) {
        const errData = await res.json().catch(() => ({}))
        throw new Error(errData.error || 'Gagal menolak pengeluaran')
      }
      toast.success('Pengeluaran berhasil ditolak')
      setApproveRejectExpense(null)
      setRejectReason('')
      setShowRejectInput(false)
      refreshExpenses()
    } catch (err: any) {
      toast.error(err.message || 'Gagal menolak pengeluaran')
    } finally {
      setStatusUpdating(false)
    }
  }

  // ---- Category CRUD -------------------------------------------------------

  const openCategoryCreate = () => {
    setEditingCategory(null)
    setCategoryForm({ name: '' })
    setShowCategoryModal(true)
  }

  const openCategoryEdit = (cat: ExpenseCategory) => {
    setEditingCategory(cat)
    setCategoryForm({ name: cat.name })
    setShowCategoryModal(true)
  }

  const closeCategoryModal = () => {
    setShowCategoryModal(false)
    setEditingCategory(null)
  }

  const handleCategorySubmit = async (e: React.FormEvent) => {
    e.preventDefault()
    if (!categoryForm.name.trim()) {
      toast.error('Nama kategori wajib diisi')
      return
    }

    setCategorySaving(true)
    try {
      let res: Response
      if (editingCategory) {
        res = await fetch(`/api/expense-categories/${editingCategory.id}`, {
          method: 'PUT',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ name: categoryForm.name.trim() }),
        })
      } else {
        res = await fetch('/api/expense-categories', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ name: categoryForm.name.trim() }),
        })
      }

      if (!res.ok) {
        const errData = await res.json().catch(() => ({}))
        throw new Error(errData.error || 'Gagal menyimpan kategori')
      }

      toast.success(editingCategory ? 'Kategori berhasil diperbarui' : 'Kategori berhasil ditambahkan')
      closeCategoryModal()
      fetchCategories()
    } catch (err: any) {
      toast.error(err.message || 'Gagal menyimpan kategori')
    } finally {
      setCategorySaving(false)
    }
  }

  const handleToggleCategoryActive = async (cat: ExpenseCategory) => {
    try {
      const res = await fetch(`/api/expense-categories/${cat.id}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ isActive: !cat.isActive }),
      })
      if (!res.ok) {
        const errData = await res.json().catch(() => ({}))
        throw new Error(errData.error || 'Gagal mengubah status kategori')
      }
      toast.success(cat.isActive ? 'Kategori dinonaktifkan' : 'Kategori diaktifkan')
      fetchCategories()
    } catch (err: any) {
      toast.error(err.message || 'Gagal mengubah status kategori')
    }
  }

  // ---- Report period change ------------------------------------------------

  const handleReportPeriodChange = (periodId: string) => {
    setReportPeriod(periodId)
    if (periodId !== 'custom') {
      const { dateFrom, dateTo } = getReportDateRange(periodId)
      setReportDateFrom(dateFrom)
      setReportDateTo(dateTo)
      const storeId = reportStore || selectedStore
      fetchReport(storeId, dateFrom, dateTo)
    }
  }

  const handleReportCustomApply = () => {
    const storeId = reportStore || selectedStore
    fetchReport(storeId, reportDateFrom, reportDateTo)
  }

  const handleReportStoreChange = (storeId: string) => {
    setReportStore(storeId)
    fetchReport(storeId, reportDateFrom, reportDateTo)
  }

  // =========================================================================
  // Computed helpers
  // =========================================================================

  const isOwnerOrAdmin = user?.role === 'owner' || user?.role === 'admin'
  const activeCategories = categories.filter((c) => c.isActive)

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

  const renderStatusBadge = (status: string) => {
    const info = EXPENSE_STATUSES[status] || {
      label: status,
      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>
    )
  }

  const renderPaymentMethod = (method: string | null) => {
    if (!method) return '-'
    return EXPENSE_PAYMENT_METHODS[method]?.label || method
  }

  // =========================================================================
  // Feature guard
  // =========================================================================

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

  if (!allowed) {
    return (
      <div className="flex flex-col items-center justify-center h-64 gap-4">
        <Wallet className="w-16 h-16 text-gray-300 dark:text-gray-600" />
        <h2 className="text-xl font-semibold text-gray-900 dark:text-white">
          Fitur Pengeluaran Tidak Tersedia
        </h2>
        <p className="text-gray-500 dark:text-gray-400 text-center max-w-md">
          Paket <span className="font-semibold">{planName}</span> Anda tidak mencakup fitur Manajemen Pengeluaran.
          Silakan upgrade paket untuk menggunakan fitur ini.
        </p>
      </div>
    )
  }

  // =========================================================================
  // Tab: Daftar Pengeluaran
  // =========================================================================

  const renderListTab = () => {
    return (
      <div className="mt-6 space-y-6">
        {/* Filter bar */}
        <div className="card p-4">
          <div className="flex items-center gap-2 mb-3 text-sm font-medium text-gray-700 dark:text-gray-200">
            <Filter className="w-4 h-4" />
            Filter
          </div>
          <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-5 gap-3">
            <div>
              <label className="block text-xs text-gray-500 dark:text-gray-400 mb-1">Dari Tanggal</label>
              <input
                type="date"
                className="input-field text-sm"
                value={filterDateFrom}
                onChange={(e) => setFilterDateFrom(e.target.value)}
              />
            </div>
            <div>
              <label className="block text-xs text-gray-500 dark:text-gray-400 mb-1">Sampai Tanggal</label>
              <input
                type="date"
                className="input-field text-sm"
                value={filterDateTo}
                onChange={(e) => setFilterDateTo(e.target.value)}
              />
            </div>
            <div>
              <label className="block text-xs text-gray-500 dark:text-gray-400 mb-1">Kategori</label>
              <select
                className="input-field text-sm"
                value={filterCategory}
                onChange={(e) => setFilterCategory(e.target.value)}
              >
                <option value="">Semua Kategori</option>
                {activeCategories.map((c) => (
                  <option key={c.id} value={c.id}>
                    {c.name}
                  </option>
                ))}
              </select>
            </div>
            <div>
              <label className="block text-xs text-gray-500 dark:text-gray-400 mb-1">Status</label>
              <select
                className="input-field text-sm"
                value={filterStatus}
                onChange={(e) => setFilterStatus(e.target.value)}
              >
                <option value="">Semua Status</option>
                {Object.entries(EXPENSE_STATUSES).map(([key, val]) => (
                  <option key={key} value={key}>
                    {val.label}
                  </option>
                ))}
              </select>
            </div>
            <div>
              <label className="block text-xs text-gray-500 dark:text-gray-400 mb-1">Cari</label>
              <div className="relative">
                <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" />
                <input
                  type="text"
                  className="input-field text-sm pl-9"
                  placeholder="Cari deskripsi, vendor..."
                  value={filterSearch}
                  onChange={(e) => setFilterSearch(e.target.value)}
                />
              </div>
            </div>
          </div>
        </div>

        {/* Summary cards */}
        <div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
          <div className="card p-4">
            <div className="flex items-center gap-3">
              <div className="w-10 h-10 rounded-lg bg-blue-100 dark:bg-blue-900/30 flex items-center justify-center">
                <DollarSign className="w-5 h-5 text-blue-600 dark:text-blue-400" />
              </div>
              <div>
                <p className="text-xs text-gray-500 dark:text-gray-400">Total Pengeluaran</p>
                <p className="text-lg font-bold text-gray-900 dark:text-white">
                  {formatCurrency(expenseStats.totalAmount)}
                </p>
              </div>
            </div>
          </div>
          <div className="card p-4">
            <div className="flex items-center gap-3">
              <div className="w-10 h-10 rounded-lg bg-yellow-100 dark:bg-yellow-900/30 flex items-center justify-center">
                <Clock className="w-5 h-5 text-yellow-600 dark:text-yellow-400" />
              </div>
              <div>
                <p className="text-xs text-gray-500 dark:text-gray-400">Menunggu Approval</p>
                <p className="text-lg font-bold text-gray-900 dark:text-white">
                  {expenseStats.pendingCount}
                </p>
              </div>
            </div>
          </div>
          <div className="card p-4">
            <div className="flex items-center gap-3">
              <div className="w-10 h-10 rounded-lg bg-orange-100 dark:bg-orange-900/30 flex items-center justify-center">
                <TrendingUp className="w-5 h-5 text-orange-600 dark:text-orange-400" />
              </div>
              <div>
                <p className="text-xs text-gray-500 dark:text-gray-400">Jumlah Pending</p>
                <p className="text-lg font-bold text-gray-900 dark:text-white">
                  {formatCurrency(expenseStats.pendingAmount)}
                </p>
              </div>
            </div>
          </div>
        </div>

        {/* Add button */}
        <div className="flex justify-end">
          <button onClick={openCreateModal} className="btn-primary text-sm flex items-center gap-2">
            <Plus className="w-4 h-4" />
            Tambah Pengeluaran
          </button>
        </div>

        {/* Data table */}
        {expensesLoading ? (
          <div className="flex items-center justify-center h-32">
            <Loader2 className="w-6 h-6 animate-spin text-gray-400" />
          </div>
        ) : expenses.length === 0 ? (
          <div className="card p-8 text-center">
            <Wallet className="w-12 h-12 text-gray-300 dark:text-gray-600 mx-auto mb-3" />
            <p className="text-gray-500 dark:text-gray-400">Belum ada data pengeluaran.</p>
            <p className="text-sm text-gray-400 dark:text-gray-500 mt-1">
              Klik tombol &quot;Tambah Pengeluaran&quot; untuk menambahkan data baru.
            </p>
          </div>
        ) : (
          <div className="card overflow-hidden">
            <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-800/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">Kategori</th>
                    <th className="text-left py-3 px-4 font-medium text-gray-600 dark:text-gray-300">Deskripsi</th>
                    <th className="text-left py-3 px-4 font-medium text-gray-600 dark:text-gray-300">Vendor</th>
                    <th className="text-right py-3 px-4 font-medium text-gray-600 dark:text-gray-300">Jumlah (Rp)</th>
                    <th className="text-left py-3 px-4 font-medium text-gray-600 dark:text-gray-300">Pembuat</th>
                    <th className="text-center py-3 px-4 font-medium text-gray-600 dark:text-gray-300">Status</th>
                    <th className="text-center py-3 px-4 font-medium text-gray-600 dark:text-gray-300">Aksi</th>
                  </tr>
                </thead>
                <tbody>
                  {expenses.map((exp) => (
                    <tr
                      key={exp.id}
                      className="border-b border-gray-100 dark:border-gray-700/50 hover:bg-gray-50 dark:hover:bg-gray-800/30 cursor-pointer transition-colors"
                      onClick={() => setDetailExpense(exp)}
                    >
                      <td className="py-3 px-4 text-gray-900 dark:text-white whitespace-nowrap">
                        {formatDate(exp.date)}
                      </td>
                      <td className="py-3 px-4 text-gray-700 dark:text-gray-300">
                        {exp.category?.name || '-'}
                      </td>
                      <td className="py-3 px-4 text-gray-700 dark:text-gray-300 max-w-[200px] truncate">
                        {exp.description}
                      </td>
                      <td className="py-3 px-4 text-gray-700 dark:text-gray-300">
                        {exp.vendor || '-'}
                      </td>
                      <td className="py-3 px-4 text-right font-medium text-gray-900 dark:text-white whitespace-nowrap">
                        {formatCurrency(exp.amount)}
                      </td>
                      <td className="py-3 px-4 text-gray-700 dark:text-gray-300">
                        {exp.createdBy?.name || '-'}
                      </td>
                      <td className="py-3 px-4 text-center">
                        {renderStatusBadge(exp.status)}
                      </td>
                      <td className="py-3 px-4">
                        <div className="flex items-center justify-center gap-1" onClick={(e) => e.stopPropagation()}>
                          {exp.status === 'pending' && isOwnerOrAdmin && (
                            <>
                              <button
                                onClick={() => openApproveRejectModal(exp)}
                                className="text-xs px-2 py-1 rounded-lg font-medium bg-green-100 text-green-700 hover:bg-green-200 dark:bg-green-900/30 dark:text-green-300 dark:hover:bg-green-900/50 transition-colors"
                                title="Setujui"
                              >
                                <CheckCircle className="w-3.5 h-3.5 inline mr-0.5" />
                                Setujui
                              </button>
                              <button
                                onClick={() => {
                                  openApproveRejectModal(exp)
                                  // Immediately show reject input
                                  setTimeout(() => setShowRejectInput(true), 0)
                                }}
                                className="text-xs px-2 py-1 rounded-lg font-medium bg-red-100 text-red-700 hover:bg-red-200 dark:bg-red-900/30 dark:text-red-300 dark:hover:bg-red-900/50 transition-colors"
                                title="Tolak"
                              >
                                <XCircle className="w-3.5 h-3.5 inline mr-0.5" />
                                Tolak
                              </button>
                            </>
                          )}
                          {exp.status === 'pending' && (
                            <>
                              <button
                                onClick={() => openEditModal(exp)}
                                className="p-1.5 rounded-lg text-gray-500 hover:text-blue-600 hover:bg-blue-50 dark:hover:text-blue-400 dark:hover:bg-blue-900/20 transition-colors"
                                title="Edit"
                              >
                                <Pencil className="w-3.5 h-3.5" />
                              </button>
                              <button
                                onClick={() => setDeletingExpenseId(exp.id)}
                                className="p-1.5 rounded-lg text-gray-500 hover:text-red-600 hover:bg-red-50 dark:hover:text-red-400 dark:hover:bg-red-900/20 transition-colors"
                                title="Hapus"
                              >
                                <Trash2 className="w-3.5 h-3.5" />
                              </button>
                            </>
                          )}
                          <button
                            onClick={() => setDetailExpense(exp)}
                            className="p-1.5 rounded-lg text-gray-500 hover:text-gray-700 hover:bg-gray-100 dark:hover:text-gray-300 dark:hover:bg-gray-700 transition-colors"
                            title="Detail"
                          >
                            <Eye className="w-3.5 h-3.5" />
                          </button>
                        </div>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>

            {/* Pagination */}
            <div className="px-4 pb-2">
              <Pagination
                pagination={expensePagination}
                onPageChange={(page) =>
                  fetchExpenses(selectedStore, filterDateFrom, filterDateTo, filterCategory, filterStatus, filterSearch, page)
                }
                itemLabel="pengeluaran"
              />
            </div>
          </div>
        )}
      </div>
    )
  }

  // =========================================================================
  // Tab: Kategori
  // =========================================================================

  const renderCategoriesTab = () => {
    return (
      <div className="mt-6 space-y-4">
        <div className="flex items-center justify-between">
          <p className="text-sm text-gray-500 dark:text-gray-400">
            Kelola kategori pengeluaran. Kategori yang dinonaktifkan tidak akan muncul saat membuat pengeluaran baru.
          </p>
          <button onClick={openCategoryCreate} className="btn-primary text-sm flex items-center gap-2">
            <Plus className="w-4 h-4" />
            Tambah Kategori
          </button>
        </div>

        {categoriesLoading ? (
          <div className="flex items-center justify-center h-32">
            <Loader2 className="w-6 h-6 animate-spin text-gray-400" />
          </div>
        ) : categories.length === 0 ? (
          <div className="card p-8 text-center">
            <Tags className="w-12 h-12 text-gray-300 dark:text-gray-600 mx-auto mb-3" />
            <p className="text-gray-500 dark:text-gray-400">Belum ada kategori pengeluaran.</p>
            <p className="text-sm text-gray-400 dark:text-gray-500 mt-1">
              Kategori default akan otomatis dibuat saat pertama kali memuat.
            </p>
          </div>
        ) : (
          <div className="card overflow-hidden">
            <table className="w-full text-sm">
              <thead>
                <tr className="border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/50">
                  <th className="text-left py-3 px-4 font-medium text-gray-600 dark:text-gray-300">Nama Kategori</th>
                  <th className="text-center py-3 px-4 font-medium text-gray-600 dark:text-gray-300">Jumlah Pengeluaran</th>
                  <th className="text-center py-3 px-4 font-medium text-gray-600 dark:text-gray-300">Status</th>
                  <th className="text-center py-3 px-4 font-medium text-gray-600 dark:text-gray-300">Aksi</th>
                </tr>
              </thead>
              <tbody>
                {categories.map((cat) => (
                  <tr
                    key={cat.id}
                    className="border-b border-gray-100 dark:border-gray-700/50 hover:bg-gray-50 dark:hover:bg-gray-800/30 transition-colors"
                  >
                    <td className="py-3 px-4">
                      <span className={`font-medium ${cat.isActive ? 'text-gray-900 dark:text-white' : 'text-gray-400 dark:text-gray-500 line-through'}`}>
                        {cat.name}
                      </span>
                    </td>
                    <td className="py-3 px-4 text-center text-gray-600 dark:text-gray-400">
                      {cat._count?.expenses || 0}
                    </td>
                    <td className="py-3 px-4 text-center">
                      <span className={`text-xs px-2 py-0.5 rounded-full font-medium ${cat.isActive ? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-300' : 'bg-gray-100 text-gray-500 dark:bg-gray-700 dark:text-gray-400'}`}>
                        {cat.isActive ? 'Aktif' : 'Nonaktif'}
                      </span>
                    </td>
                    <td className="py-3 px-4">
                      <div className="flex items-center justify-center gap-2">
                        <button
                          onClick={() => handleToggleCategoryActive(cat)}
                          className="p-1.5 rounded-lg text-gray-500 hover:text-blue-600 hover:bg-blue-50 dark:hover:text-blue-400 dark:hover:bg-blue-900/20 transition-colors"
                          title={cat.isActive ? 'Nonaktifkan' : 'Aktifkan'}
                        >
                          {cat.isActive ? (
                            <ToggleRight className="w-5 h-5 text-green-500" />
                          ) : (
                            <ToggleLeft className="w-5 h-5 text-gray-400" />
                          )}
                        </button>
                        <button
                          onClick={() => openCategoryEdit(cat)}
                          className="p-1.5 rounded-lg text-gray-500 hover:text-blue-600 hover:bg-blue-50 dark:hover:text-blue-400 dark:hover:bg-blue-900/20 transition-colors"
                          title="Edit"
                        >
                          <Pencil className="w-4 h-4" />
                        </button>
                      </div>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>
    )
  }

  // =========================================================================
  // Tab: Laporan
  // =========================================================================

  const renderReportsTab = () => {
    const maxMonthlyTotal = reportData?.byMonth
      ? Math.max(...reportData.byMonth.map((m) => m.total), 1)
      : 1

    return (
      <div className="mt-6 space-y-6">
        {/* Period and store selectors */}
        <div className="card p-4">
          <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-3">
            <div>
              <label className="block text-xs text-gray-500 dark:text-gray-400 mb-1">Periode</label>
              <select
                className="input-field text-sm"
                value={reportPeriod}
                onChange={(e) => handleReportPeriodChange(e.target.value)}
              >
                {REPORT_PERIODS.map((p) => (
                  <option key={p.id} value={p.id}>
                    {p.label}
                  </option>
                ))}
              </select>
            </div>
            {reportPeriod === 'custom' && (
              <>
                <div>
                  <label className="block text-xs text-gray-500 dark:text-gray-400 mb-1">Dari Tanggal</label>
                  <input
                    type="date"
                    className="input-field text-sm"
                    value={reportDateFrom}
                    onChange={(e) => setReportDateFrom(e.target.value)}
                  />
                </div>
                <div>
                  <label className="block text-xs text-gray-500 dark:text-gray-400 mb-1">Sampai Tanggal</label>
                  <input
                    type="date"
                    className="input-field text-sm"
                    value={reportDateTo}
                    onChange={(e) => setReportDateTo(e.target.value)}
                  />
                </div>
                <div className="flex items-end">
                  <button onClick={handleReportCustomApply} className="btn-primary text-sm">
                    Terapkan
                  </button>
                </div>
              </>
            )}
            {stores.length > 1 && (
              <div>
                <label className="block text-xs text-gray-500 dark:text-gray-400 mb-1">Toko</label>
                <select
                  className="input-field text-sm"
                  value={reportStore || selectedStore}
                  onChange={(e) => handleReportStoreChange(e.target.value)}
                >
                  {stores.map((s) => (
                    <option key={s.id} value={s.id}>
                      {s.name}
                    </option>
                  ))}
                </select>
              </div>
            )}
          </div>
        </div>

        {reportLoading ? (
          <div className="flex items-center justify-center h-32">
            <Loader2 className="w-6 h-6 animate-spin text-gray-400" />
          </div>
        ) : !reportData ? (
          <div className="card p-8 text-center">
            <BarChart3 className="w-12 h-12 text-gray-300 dark:text-gray-600 mx-auto mb-3" />
            <p className="text-gray-500 dark:text-gray-400">Belum ada data laporan.</p>
          </div>
        ) : (
          <>
            {/* Summary row */}
            <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
              <div className="card p-4">
                <div className="flex items-center gap-3">
                  <div className="w-10 h-10 rounded-lg bg-blue-100 dark:bg-blue-900/30 flex items-center justify-center">
                    <DollarSign className="w-5 h-5 text-blue-600 dark:text-blue-400" />
                  </div>
                  <div>
                    <p className="text-xs text-gray-500 dark:text-gray-400">Total Pengeluaran</p>
                    <p className="text-xl font-bold text-gray-900 dark:text-white">
                      {formatCurrency(reportData.grandTotal)}
                    </p>
                  </div>
                </div>
              </div>
              <div className="card p-4">
                <div className="flex items-center gap-3">
                  <div className="w-10 h-10 rounded-lg bg-green-100 dark:bg-green-900/30 flex items-center justify-center">
                    <List className="w-5 h-5 text-green-600 dark:text-green-400" />
                  </div>
                  <div>
                    <p className="text-xs text-gray-500 dark:text-gray-400">Jumlah Transaksi</p>
                    <p className="text-xl font-bold text-gray-900 dark:text-white">
                      {reportData.totalCount}
                    </p>
                  </div>
                </div>
              </div>
            </div>

            {/* Pie chart (div-based) - Per-category breakdown */}
            {reportData.byCategory && reportData.byCategory.length > 0 && (
              <div className="card p-6">
                <h3 className="text-base font-semibold text-gray-900 dark:text-white mb-4">
                  Pengeluaran per Kategori
                </h3>
                <div className="space-y-3">
                  {reportData.byCategory.map((cat, idx) => {
                    const pct = reportData.grandTotal > 0
                      ? ((cat.total / reportData.grandTotal) * 100).toFixed(1)
                      : '0.0'
                    const colorClass = CHART_COLORS[idx % CHART_COLORS.length]
                    return (
                      <div key={cat.categoryId || idx}>
                        <div className="flex items-center justify-between mb-1">
                          <div className="flex items-center gap-2">
                            <div className={`w-3 h-3 rounded-full ${colorClass}`} />
                            <span className="text-sm font-medium text-gray-700 dark:text-gray-200">
                              {cat.categoryName}
                            </span>
                          </div>
                          <div className="flex items-center gap-3">
                            <span className="text-sm text-gray-500 dark:text-gray-400">
                              {pct}%
                            </span>
                            <span className="text-sm font-semibold text-gray-900 dark:text-white min-w-[100px] text-right">
                              {formatCurrency(cat.total)}
                            </span>
                          </div>
                        </div>
                        <div className="w-full bg-gray-100 dark:bg-gray-700 rounded-full h-2.5">
                          <div
                            className={`h-2.5 rounded-full ${colorClass} transition-all duration-500`}
                            style={{ width: `${Math.max(Number(pct), 0.5)}%` }}
                          />
                        </div>
                      </div>
                    )
                  })}
                </div>
              </div>
            )}

            {/* Monthly trend (div-based bar chart) */}
            {reportData.byMonth && reportData.byMonth.length > 0 && (
              <div className="card p-6">
                <h3 className="text-base font-semibold text-gray-900 dark:text-white mb-4">
                  Tren Bulanan
                </h3>
                <div className="flex items-end gap-2 h-48">
                  {reportData.byMonth.map((m, idx) => {
                    const heightPct = maxMonthlyTotal > 0
                      ? (m.total / maxMonthlyTotal) * 100
                      : 0
                    return (
                      <div key={m.month || idx} className="flex-1 flex flex-col items-center justify-end h-full">
                        <div className="relative w-full flex justify-center mb-1 group">
                          {/* Tooltip */}
                          <div className="absolute bottom-full mb-2 hidden group-hover:block bg-gray-900 dark:bg-gray-700 text-white text-xs rounded-lg px-2 py-1 whitespace-nowrap z-10">
                            {formatCurrency(m.total)}
                            <br />
                            {m.count} transaksi
                          </div>
                          <div
                            className="w-full max-w-[48px] bg-blue-500 dark:bg-blue-400 rounded-t-md transition-all duration-500 hover:bg-blue-600 dark:hover:bg-blue-300"
                            style={{ height: `${Math.max(heightPct, 2)}%` }}
                          />
                        </div>
                        <span className="text-xs text-gray-500 dark:text-gray-400 mt-1">
                          {monthLabel(m.month)}
                        </span>
                      </div>
                    )
                  })}
                </div>
              </div>
            )}

            {/* Table summary */}
            {reportData.byCategory && reportData.byCategory.length > 0 && (
              <div className="card overflow-hidden">
                <table className="w-full text-sm">
                  <thead>
                    <tr className="border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/50">
                      <th className="text-left py-3 px-4 font-medium text-gray-600 dark:text-gray-300">Kategori</th>
                      <th className="text-center py-3 px-4 font-medium text-gray-600 dark:text-gray-300">Transaksi</th>
                      <th className="text-right py-3 px-4 font-medium text-gray-600 dark:text-gray-300">Total</th>
                      <th className="text-right py-3 px-4 font-medium text-gray-600 dark:text-gray-300">Persentase</th>
                    </tr>
                  </thead>
                  <tbody>
                    {reportData.byCategory.map((cat, idx) => {
                      const pct = reportData.grandTotal > 0
                        ? ((cat.total / reportData.grandTotal) * 100).toFixed(1)
                        : '0.0'
                      return (
                        <tr
                          key={cat.categoryId || idx}
                          className="border-b border-gray-100 dark:border-gray-700/50"
                        >
                          <td className="py-3 px-4">
                            <div className="flex items-center gap-2">
                              <div className={`w-3 h-3 rounded-full ${CHART_COLORS[idx % CHART_COLORS.length]}`} />
                              <span className="font-medium text-gray-900 dark:text-white">{cat.categoryName}</span>
                            </div>
                          </td>
                          <td className="py-3 px-4 text-center text-gray-600 dark:text-gray-400">
                            {cat.count}
                          </td>
                          <td className="py-3 px-4 text-right font-medium text-gray-900 dark:text-white">
                            {formatCurrency(cat.total)}
                          </td>
                          <td className="py-3 px-4 text-right text-gray-600 dark:text-gray-400">
                            {pct}%
                          </td>
                        </tr>
                      )
                    })}
                  </tbody>
                  <tfoot>
                    <tr className="bg-gray-50 dark:bg-gray-800/50 font-semibold">
                      <td className="py-3 px-4 text-gray-900 dark:text-white">Total</td>
                      <td className="py-3 px-4 text-center text-gray-900 dark:text-white">
                        {reportData.totalCount}
                      </td>
                      <td className="py-3 px-4 text-right text-gray-900 dark:text-white">
                        {formatCurrency(reportData.grandTotal)}
                      </td>
                      <td className="py-3 px-4 text-right text-gray-900 dark:text-white">100%</td>
                    </tr>
                  </tfoot>
                </table>
              </div>
            )}
          </>
        )}
      </div>
    )
  }

  // =========================================================================
  // Modal: Create / Edit Expense
  // =========================================================================

  const renderExpenseModal = () => {
    if (!showExpenseModal) return null
    return (
      <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-2xl shadow-xl w-full max-w-lg max-h-[90vh] overflow-y-auto">
          <div className="flex items-center justify-between p-4 border-b border-gray-200 dark:border-gray-700">
            <h3 className="text-lg font-semibold text-gray-900 dark:text-white">
              {editingExpense ? 'Edit Pengeluaran' : 'Tambah Pengeluaran'}
            </h3>
            <button
              onClick={closeExpenseModal}
              className="p-1 rounded-lg text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors"
            >
              <X className="w-5 h-5" />
            </button>
          </div>

          <form onSubmit={handleExpenseSubmit} className="p-4 space-y-4">
            {/* Date */}
            <div>
              <label className="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
                Tanggal <span className="text-red-500">*</span>
              </label>
              <input
                type="date"
                className="input-field"
                value={expenseForm.date}
                onChange={(e) => setExpenseForm({ ...expenseForm, date: e.target.value })}
                required
              />
            </div>

            {/* Category */}
            <div>
              <label className="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
                Kategori <span className="text-red-500">*</span>
              </label>
              <select
                className="input-field"
                value={expenseForm.categoryId}
                onChange={(e) => setExpenseForm({ ...expenseForm, categoryId: e.target.value })}
                required
              >
                <option value="">Pilih Kategori</option>
                {activeCategories.map((c) => (
                  <option key={c.id} value={c.id}>
                    {c.name}
                  </option>
                ))}
              </select>
            </div>

            {/* Amount */}
            <div>
              <label className="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
                Jumlah <span className="text-red-500">*</span>
              </label>
              <div className="relative">
                <span className="absolute left-3 top-1/2 -translate-y-1/2 text-sm text-gray-500 dark:text-gray-400">
                  Rp
                </span>
                <input
                  type="number"
                  className="input-field pl-10"
                  placeholder="0"
                  min="1"
                  value={expenseForm.amount}
                  onChange={(e) => setExpenseForm({ ...expenseForm, amount: e.target.value })}
                  required
                />
              </div>
            </div>

            {/* Description */}
            <div>
              <label className="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
                Deskripsi <span className="text-red-500">*</span>
              </label>
              <textarea
                className="input-field"
                rows={2}
                placeholder="Deskripsi pengeluaran..."
                value={expenseForm.description}
                onChange={(e) => setExpenseForm({ ...expenseForm, description: e.target.value })}
                required
              />
            </div>

            {/* Payment Method */}
            <div>
              <label className="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
                Metode Pembayaran
              </label>
              <select
                className="input-field"
                value={expenseForm.paymentMethod}
                onChange={(e) => setExpenseForm({ ...expenseForm, paymentMethod: e.target.value })}
              >
                {Object.entries(EXPENSE_PAYMENT_METHODS).map(([key, val]) => (
                  <option key={key} value={key}>
                    {val.label}
                  </option>
                ))}
              </select>
            </div>

            {/* Vendor */}
            <div>
              <label className="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
                Vendor
              </label>
              <input
                type="text"
                className="input-field"
                placeholder="Nama vendor/supplier"
                value={expenseForm.vendor}
                onChange={(e) => setExpenseForm({ ...expenseForm, vendor: e.target.value })}
              />
            </div>

            {/* Receipt Number */}
            <div>
              <label className="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
                No. Nota
              </label>
              <input
                type="text"
                className="input-field"
                placeholder="Nomor nota/kwitansi"
                value={expenseForm.receiptNumber}
                onChange={(e) => setExpenseForm({ ...expenseForm, receiptNumber: e.target.value })}
              />
            </div>

            {/* Notes */}
            <div>
              <label className="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
                Catatan
              </label>
              <textarea
                className="input-field"
                rows={2}
                placeholder="Catatan tambahan..."
                value={expenseForm.notes}
                onChange={(e) => setExpenseForm({ ...expenseForm, notes: e.target.value })}
              />
            </div>

            {/* Submit */}
            <div className="flex justify-end gap-2 pt-2">
              <button type="button" onClick={closeExpenseModal} className="btn-secondary text-sm">
                Batal
              </button>
              <button type="submit" disabled={formSaving} className="btn-primary text-sm flex items-center gap-2">
                {formSaving && <Loader2 className="w-4 h-4 animate-spin" />}
                {editingExpense ? 'Perbarui' : 'Simpan'}
              </button>
            </div>
          </form>
        </div>
      </div>
    )
  }

  // =========================================================================
  // Modal: Detail Expense
  // =========================================================================

  const renderDetailModal = () => {
    if (!detailExpense) return null
    const exp = detailExpense
    return (
      <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-2xl shadow-xl w-full max-w-md max-h-[90vh] overflow-y-auto p-6">
          <div className="flex items-center justify-between mb-4">
            <h3 className="text-lg font-semibold text-gray-900 dark:text-white">Detail Pengeluaran</h3>
            <button
              onClick={() => setDetailExpense(null)}
              className="p-1 rounded-lg text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors"
            >
              <X className="w-5 h-5" />
            </button>
          </div>

          <div className="space-y-3">
            <div className="flex items-center justify-between">
              <span className="text-sm text-gray-500 dark:text-gray-400">Status</span>
              {renderStatusBadge(exp.status)}
            </div>

            <hr className="border-gray-200 dark:border-gray-700" />

            <div className="flex items-center justify-between">
              <span className="text-sm text-gray-500 dark:text-gray-400">Tanggal</span>
              <span className="text-sm font-medium text-gray-900 dark:text-white">
                {formatDate(exp.date)}
              </span>
            </div>
            <div className="flex items-center justify-between">
              <span className="text-sm text-gray-500 dark:text-gray-400">Kategori</span>
              <span className="text-sm text-gray-900 dark:text-white">
                {exp.category?.name || '-'}
              </span>
            </div>
            <div className="flex items-center justify-between">
              <span className="text-sm text-gray-500 dark:text-gray-400">Jumlah</span>
              <span className="text-sm font-bold text-gray-900 dark:text-white">
                {formatCurrency(exp.amount)}
              </span>
            </div>

            <hr className="border-gray-200 dark:border-gray-700" />

            <div>
              <span className="text-sm text-gray-500 dark:text-gray-400">Deskripsi</span>
              <p className="text-sm text-gray-900 dark:text-white mt-1 bg-gray-50 dark:bg-gray-700/50 rounded-lg p-2">
                {exp.description}
              </p>
            </div>

            <div className="flex items-center justify-between">
              <span className="text-sm text-gray-500 dark:text-gray-400">Metode Pembayaran</span>
              <span className="text-sm text-gray-900 dark:text-white">
                {renderPaymentMethod(exp.paymentMethod)}
              </span>
            </div>
            <div className="flex items-center justify-between">
              <span className="text-sm text-gray-500 dark:text-gray-400">Vendor</span>
              <span className="text-sm text-gray-900 dark:text-white">{exp.vendor || '-'}</span>
            </div>
            <div className="flex items-center justify-between">
              <span className="text-sm text-gray-500 dark:text-gray-400">No. Nota</span>
              <span className="text-sm text-gray-900 dark:text-white">{exp.receiptNumber || '-'}</span>
            </div>
            <div className="flex items-center justify-between">
              <span className="text-sm text-gray-500 dark:text-gray-400">Pembuat</span>
              <span className="text-sm text-gray-900 dark:text-white">{exp.createdBy?.name || '-'}</span>
            </div>
            <div className="flex items-center justify-between">
              <span className="text-sm text-gray-500 dark:text-gray-400">Toko</span>
              <span className="text-sm text-gray-900 dark:text-white">{exp.store?.name || '-'}</span>
            </div>

            {exp.notes && (
              <div>
                <span className="text-sm text-gray-500 dark:text-gray-400">Catatan</span>
                <p className="text-sm text-gray-900 dark:text-white mt-1 bg-gray-50 dark:bg-gray-700/50 rounded-lg p-2">
                  {exp.notes}
                </p>
              </div>
            )}

            {exp.rejectReason && (
              <div>
                <span className="text-sm text-red-500 dark:text-red-400">Alasan Penolakan</span>
                <p className="text-sm text-gray-900 dark:text-white mt-1 bg-red-50 dark:bg-red-900/10 rounded-lg p-2">
                  {exp.rejectReason}
                </p>
              </div>
            )}
          </div>

          {/* Action buttons in detail */}
          {exp.status === 'pending' && (
            <div className="mt-4 pt-4 border-t border-gray-200 dark:border-gray-700">
              <div className="flex flex-wrap gap-2">
                {isOwnerOrAdmin && (
                  <>
                    <button
                      onClick={() => {
                        setDetailExpense(null)
                        openApproveRejectModal(exp)
                      }}
                      className="text-sm px-3 py-1.5 rounded-lg font-medium bg-green-100 text-green-700 hover:bg-green-200 dark:bg-green-900/30 dark:text-green-300 dark:hover:bg-green-900/50 transition-colors"
                    >
                      <CheckCircle className="w-4 h-4 inline mr-1" />
                      Setujui
                    </button>
                    <button
                      onClick={() => {
                        setDetailExpense(null)
                        openApproveRejectModal(exp)
                        setTimeout(() => setShowRejectInput(true), 0)
                      }}
                      className="text-sm px-3 py-1.5 rounded-lg font-medium bg-red-100 text-red-700 hover:bg-red-200 dark:bg-red-900/30 dark:text-red-300 dark:hover:bg-red-900/50 transition-colors"
                    >
                      <XCircle className="w-4 h-4 inline mr-1" />
                      Tolak
                    </button>
                  </>
                )}
                <button
                  onClick={() => {
                    setDetailExpense(null)
                    openEditModal(exp)
                  }}
                  className="text-sm px-3 py-1.5 rounded-lg font-medium bg-blue-100 text-blue-700 hover:bg-blue-200 dark:bg-blue-900/30 dark:text-blue-300 dark:hover:bg-blue-900/50 transition-colors"
                >
                  <Pencil className="w-4 h-4 inline mr-1" />
                  Edit
                </button>
                <button
                  onClick={() => {
                    setDetailExpense(null)
                    setDeletingExpenseId(exp.id)
                  }}
                  className="text-sm px-3 py-1.5 rounded-lg font-medium bg-red-100 text-red-700 hover:bg-red-200 dark:bg-red-900/30 dark:text-red-300 dark:hover:bg-red-900/50 transition-colors"
                >
                  <Trash2 className="w-4 h-4 inline mr-1" />
                  Hapus
                </button>
              </div>
            </div>
          )}
        </div>
      </div>
    )
  }

  // =========================================================================
  // Modal: Approve / Reject
  // =========================================================================

  const renderApproveRejectModal = () => {
    if (!approveRejectExpense) return null
    const exp = approveRejectExpense
    return (
      <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-2xl shadow-xl w-full max-w-md max-h-[90vh] overflow-y-auto p-6">
          <div className="flex items-center justify-between mb-4">
            <h3 className="text-lg font-semibold text-gray-900 dark:text-white">
              {showRejectInput ? 'Tolak Pengeluaran' : 'Setujui Pengeluaran'}
            </h3>
            <button
              onClick={() => {
                setApproveRejectExpense(null)
                setShowRejectInput(false)
                setRejectReason('')
              }}
              className="p-1 rounded-lg text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors"
            >
              <X className="w-5 h-5" />
            </button>
          </div>

          {/* Expense info summary */}
          <div className="space-y-2 mb-4">
            <div className="flex items-center justify-between">
              <span className="text-sm text-gray-500 dark:text-gray-400">Tanggal</span>
              <span className="text-sm text-gray-900 dark:text-white">{formatDate(exp.date)}</span>
            </div>
            <div className="flex items-center justify-between">
              <span className="text-sm text-gray-500 dark:text-gray-400">Kategori</span>
              <span className="text-sm text-gray-900 dark:text-white">{exp.category?.name || '-'}</span>
            </div>
            <div className="flex items-center justify-between">
              <span className="text-sm text-gray-500 dark:text-gray-400">Jumlah</span>
              <span className="text-sm font-bold text-gray-900 dark:text-white">{formatCurrency(exp.amount)}</span>
            </div>
            <div className="flex items-center justify-between">
              <span className="text-sm text-gray-500 dark:text-gray-400">Deskripsi</span>
              <span className="text-sm text-gray-900 dark:text-white max-w-[200px] text-right">{exp.description}</span>
            </div>
            <div className="flex items-center justify-between">
              <span className="text-sm text-gray-500 dark:text-gray-400">Vendor</span>
              <span className="text-sm text-gray-900 dark:text-white">{exp.vendor || '-'}</span>
            </div>
            <div className="flex items-center justify-between">
              <span className="text-sm text-gray-500 dark:text-gray-400">Pembuat</span>
              <span className="text-sm text-gray-900 dark:text-white">{exp.createdBy?.name || '-'}</span>
            </div>
          </div>

          <hr className="border-gray-200 dark:border-gray-700 mb-4" />

          {showRejectInput ? (
            <div className="space-y-3">
              <div>
                <label className="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
                  Alasan Penolakan <span className="text-red-500">*</span>
                </label>
                <textarea
                  className="input-field"
                  rows={3}
                  value={rejectReason}
                  onChange={(e) => setRejectReason(e.target.value)}
                  placeholder="Tulis alasan penolakan..."
                />
              </div>
              <div className="flex gap-2 justify-end">
                <button
                  onClick={() => {
                    setShowRejectInput(false)
                    setRejectReason('')
                  }}
                  className="btn-secondary text-sm"
                >
                  Kembali
                </button>
                <button
                  onClick={handleReject}
                  disabled={statusUpdating}
                  className="text-sm px-4 py-2 rounded-lg font-medium bg-red-600 text-white hover:bg-red-700 disabled:opacity-50 transition-colors flex items-center gap-2"
                >
                  {statusUpdating && <Loader2 className="w-4 h-4 animate-spin" />}
                  Konfirmasi Tolak
                </button>
              </div>
            </div>
          ) : (
            <div className="flex gap-2 justify-end">
              <button
                onClick={() => setShowRejectInput(true)}
                className="text-sm px-4 py-2 rounded-lg font-medium bg-red-100 text-red-700 hover:bg-red-200 dark:bg-red-900/30 dark:text-red-300 dark:hover:bg-red-900/50 transition-colors"
              >
                <XCircle className="w-4 h-4 inline mr-1" />
                Tolak
              </button>
              <button
                onClick={handleApprove}
                disabled={statusUpdating}
                className="text-sm px-4 py-2 rounded-lg font-medium bg-green-600 text-white hover:bg-green-700 disabled:opacity-50 transition-colors flex items-center gap-2"
              >
                {statusUpdating && <Loader2 className="w-4 h-4 animate-spin" />}
                <CheckCircle className="w-4 h-4" />
                Setujui
              </button>
            </div>
          )}
        </div>
      </div>
    )
  }

  // =========================================================================
  // Modal: Delete Confirm
  // =========================================================================

  const renderDeleteConfirm = () => {
    if (!deletingExpenseId) return null
    return (
      <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-2xl shadow-xl w-full max-w-sm p-6">
          <h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">Hapus Pengeluaran</h3>
          <p className="text-sm text-gray-500 dark:text-gray-400 mb-4">
            Apakah Anda yakin ingin menghapus pengeluaran ini? Tindakan ini tidak dapat dibatalkan.
          </p>
          <div className="flex gap-2 justify-end">
            <button
              onClick={() => setDeletingExpenseId(null)}
              className="btn-secondary text-sm"
              disabled={deleteLoading}
            >
              Batal
            </button>
            <button
              onClick={() => handleDeleteExpense(deletingExpenseId)}
              disabled={deleteLoading}
              className="text-sm px-4 py-2 rounded-lg font-medium bg-red-600 text-white hover:bg-red-700 disabled:opacity-50 transition-colors flex items-center gap-2"
            >
              {deleteLoading && <Loader2 className="w-4 h-4 animate-spin" />}
              Hapus
            </button>
          </div>
        </div>
      </div>
    )
  }

  // =========================================================================
  // Modal: Category Create / Edit
  // =========================================================================

  const renderCategoryModal = () => {
    if (!showCategoryModal) return null
    return (
      <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-2xl shadow-xl w-full max-w-sm p-6">
          <div className="flex items-center justify-between mb-4">
            <h3 className="text-lg font-semibold text-gray-900 dark:text-white">
              {editingCategory ? 'Edit Kategori' : 'Tambah Kategori'}
            </h3>
            <button
              onClick={closeCategoryModal}
              className="p-1 rounded-lg text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors"
            >
              <X className="w-5 h-5" />
            </button>
          </div>

          <form onSubmit={handleCategorySubmit} className="space-y-4">
            <div>
              <label className="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-1">
                Nama Kategori <span className="text-red-500">*</span>
              </label>
              <input
                type="text"
                className="input-field"
                placeholder="Nama kategori..."
                value={categoryForm.name}
                onChange={(e) => setCategoryForm({ ...categoryForm, name: e.target.value })}
                required
                autoFocus
              />
            </div>

            <div className="flex justify-end gap-2 pt-2">
              <button type="button" onClick={closeCategoryModal} className="btn-secondary text-sm">
                Batal
              </button>
              <button type="submit" disabled={categorySaving} className="btn-primary text-sm flex items-center gap-2">
                {categorySaving && <Loader2 className="w-4 h-4 animate-spin" />}
                {editingCategory ? 'Perbarui' : 'Simpan'}
              </button>
            </div>
          </form>
        </div>
      </div>
    )
  }

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

  return (
    <div>
      {/* Header */}
      <div className="mb-6">
        <h1 className="text-2xl font-bold text-gray-900 dark:text-white">Manajemen Pengeluaran</h1>
        <p className="text-gray-600 dark:text-gray-300 mt-1">
          Catat, kelola, dan analisis pengeluaran restoran Anda.
        </p>
      </div>

      {/* Store selector */}
      {stores.length > 1 && (
        <div className="mb-4">
          <select
            className="input-field max-w-xs"
            value={selectedStore}
            onChange={(e) => setSelectedStore(e.target.value)}
          >
            {stores.map((s) => (
              <option key={s.id} value={s.id}>
                {s.name}
              </option>
            ))}
          </select>
        </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 === 'list' && renderListTab()}
      {activeTab === 'categories' && renderCategoriesTab()}
      {activeTab === 'reports' && renderReportsTab()}

      {/* Modals */}
      {renderExpenseModal()}
      {renderDetailModal()}
      {renderApproveRejectModal()}
      {renderDeleteConfirm()}
      {renderCategoryModal()}
    </div>
  )
}
