'use client' import { useState, useEffect, useCallback } from 'react' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Badge } from '@/components/ui/badge' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select' import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog' import { Label } from '@/components/ui/label' import { Textarea } from '@/components/ui/textarea' import { Search, Edit, RefreshCw, ChevronLeft, ChevronRight, Download, DollarSign, } from 'lucide-react' import { toast } from '@/hooks/use-toast' import { formatDistanceToNow } from 'date-fns' interface BillingRecord { _id: string user_email: string silicon_id: string service_type: string service_name: string amount: number tax_amount: number discount_applied: number payment_status: 'pending' | 'completed' | 'failed' | 'refunded' service_status: 'active' | 'inactive' | 'suspended' | 'cancelled' billing_cycle: string created_at: string updated_at: string } interface BillingSummary { totalAmount: number totalTax: number totalDiscount: number completedCount: number pendingCount: number failedCount: number } export default function BillingManagement() { const [billings, setBillings] = useState([]) const [summary, setSummary] = useState(null) const [loading, setLoading] = useState(false) const [search, setSearch] = useState('') const [serviceTypeFilter, setServiceTypeFilter] = useState('all') const [paymentStatusFilter, setPaymentStatusFilter] = useState('all') const [dateFrom, setDateFrom] = useState('') const [dateTo, setDateTo] = useState('') const [currentPage, setCurrentPage] = useState(1) const [totalPages, setTotalPages] = useState(1) const [editingBilling, setEditingBilling] = useState(null) const [editForm, setEditForm] = useState({ payment_status: 'pending' as 'pending' | 'completed' | 'failed' | 'refunded', service_status: 'active' as 'active' | 'inactive' | 'suspended' | 'cancelled', amount: 0, notes: '', }) const fetchBillings = useCallback(async () => { setLoading(true) try { const token = localStorage.getItem('token') || document.cookie .split('; ') .find((row) => row.startsWith('token=')) ?.split('=')[1] const params = new URLSearchParams({ page: currentPage.toString(), limit: '20', search, serviceType: serviceTypeFilter, paymentStatus: paymentStatusFilter, ...(dateFrom && { dateFrom }), ...(dateTo && { dateTo }), }) const response = await fetch(`/api/admin/billing?${params}`, { headers: { Authorization: `Bearer ${token}`, }, }) if (!response.ok) { throw new Error('Failed to fetch billing data') } const data = await response.json() setBillings(data.billings) setSummary(data.summary) setTotalPages(data.pagination.totalPages) } catch (error) { console.error('Billing fetch error:', error) toast({ title: 'Error', description: 'Failed to load billing data', variant: 'destructive', }) } finally { setLoading(false) } }, [search, serviceTypeFilter, paymentStatusFilter, dateFrom, dateTo, currentPage]) useEffect(() => { fetchBillings() }, [fetchBillings]) const handleEditBilling = (billing: BillingRecord) => { setEditingBilling(billing) setEditForm({ payment_status: billing.payment_status, service_status: billing.service_status, amount: billing.amount, notes: '', }) } const handleUpdateBilling = async () => { if (!editingBilling) return try { const token = localStorage.getItem('token') || document.cookie .split('; ') .find((row) => row.startsWith('token=')) ?.split('=')[1] const response = await fetch('/api/admin/billing', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, }, body: JSON.stringify({ action: 'update', billingId: editingBilling._id, data: editForm, }), }) if (!response.ok) { throw new Error('Failed to update billing record') } const data = await response.json() setBillings(billings.map((b) => (b._id === editingBilling._id ? data.billing : b))) setEditingBilling(null) toast({ title: 'Success', description: 'Billing record updated successfully', }) } catch (error) { console.error('Billing update error:', error) toast({ title: 'Error', description: 'Failed to update billing record', variant: 'destructive', }) } } const handleRefund = async (billingId: string) => { if (!confirm('Are you sure you want to process a refund for this billing record?')) return try { const token = localStorage.getItem('token') || document.cookie .split('; ') .find((row) => row.startsWith('token=')) ?.split('=')[1] const response = await fetch('/api/admin/billing', { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}`, }, body: JSON.stringify({ action: 'refund', billingId, data: { refundReason: 'Admin refund' }, }), }) if (!response.ok) { throw new Error('Failed to process refund') } const data = await response.json() setBillings(billings.map((b) => (b._id === billingId ? data.billing : b))) toast({ title: 'Success', description: data.message, }) } catch (error) { console.error('Refund error:', error) toast({ title: 'Error', description: 'Failed to process refund', variant: 'destructive', }) } } const formatCurrency = (amount: number) => { return new Intl.NumberFormat('en-IN', { style: 'currency', currency: 'INR', minimumFractionDigits: 0, maximumFractionDigits: 0, }).format(amount) } const getStatusBadgeColor = (status: string) => { switch (status) { case 'completed': case 'active': return 'bg-green-100 text-green-800' case 'pending': return 'bg-yellow-100 text-yellow-800' case 'failed': case 'cancelled': return 'bg-red-100 text-red-800' case 'refunded': return 'bg-purple-100 text-purple-800' case 'inactive': case 'suspended': return 'bg-gray-100 text-gray-800' default: return 'bg-gray-100 text-gray-800' } } return (
{/* Summary Cards */} {summary && (

Total Revenue

{formatCurrency(summary.totalAmount)}

Completed

{summary.completedCount}

Pending

{summary.pendingCount}

Failed

{summary.failedCount}

)} Billing Management {/* Filters */}
setSearch(e.target.value)} className="pl-10" />
setDateFrom(e.target.value)} /> setDateTo(e.target.value)} />
{/* Billing Table */}
{loading ? ( ) : billings.length === 0 ? ( ) : ( billings.map((billing) => ( )) )}
Customer Service Amount Payment Status Service Status Date Actions
Loading billing data...
No billing records found

{billing.user_email}

ID: {billing.silicon_id}

{billing.service_name}

{billing.service_type.replace('_', ' ')}

{formatCurrency(billing.amount)}

{billing.tax_amount > 0 && (

Tax: {formatCurrency(billing.tax_amount)}

)}
{billing.payment_status} {billing.service_status} {billing.created_at ? formatDistanceToNow(new Date(billing.created_at), { addSuffix: true }) : 'N/A'}
{billing.payment_status === 'completed' && ( )}
{/* Pagination */} {totalPages > 1 && (

Page {currentPage} of {totalPages}

)} {/* Edit Billing Dialog */} setEditingBilling(null)}> Edit Billing Record
setEditForm({ ...editForm, amount: parseFloat(e.target.value) || 0 }) } />