# Overview

"إنفايتنا" (Invatna) - A multi-tenant SaaS wedding/event invitation management system with WooCommerce integration and multi-account WhatsApp support. Built with React (frontend) and Express (backend), using the Baileys library (`@whiskeysockets/baileys`) for WhatsApp. The app is fully Arabic with RTL layout, branded in purple (#6C28FF).

Key features:
- **Multi-tenant architecture**: Users purchase message packages, receive 8-character access codes, complete data isolation
- **Message quota system**: Each user has a message quota that decrements per send, blocks when depleted. Unlimited quota stored as -1. messagesRemaining = messageQuota === -1 ? -1 : messageQuota - messagesSent
- **WooCommerce integration**: Webhook endpoint auto-creates users and sends welcome WhatsApp messages; resets messagesSent to 0 on renewal
- **Multi-account WhatsApp support**: Each user can connect multiple WhatsApp numbers
- **Message templates**: 4 predefined invitation message styles (formal, friendly, short, traditional) + custom template option. All messages append event details block + optional "إنفايتنا 💌" promo footer (toggleable via `promo_footer_disabled` setting)
- **Guest management**: Bulk import/send, WhatsApp vCard contact import, guest search by name/phone, inline guest name editing via PATCH /api/guests/:id/name
- **RSVP tracking**: Via simplified invite links (/i/:id) with countdown timer showing days/hours/minutes/seconds to event
- **Media uploads**: Invitation card images/videos stored in PostgreSQL (bytea, 15MB limit), served via `/api/media/file/{userId}/{type}`, auto-deleted after all guests receive invites or 2 days after event date
- **Admin panel**: User CRUD, stats dashboard, WordPress integration instructions, hall accounts management with subscription expiry and hall password support
- **Hall accounts (tier 2)**: role='hall', sits between admin and regular user. Admin creates halls with locked venue_name, total quota, hall password, and subscription expiry date. Hall dashboard at /hall — hall creates client accounts with QR option per client; quota deducted from hall pool. Hall can suspend/resume/delete clients. Admin can suspend/resume/delete halls. Suspended accounts blocked at login. Hall can set own password.
- **Hall analytics**: `/api/hall/stats` returns totalGuests and sentGuests across all hall clients
- **Subscription timer**: halls have `subscriptionExpiresAt` column; displayed as countdown card in hall dashboard; shown in admin halls table with color-coded badge (green/amber/orange/red)
- **Subscription reminder system**: Scheduled hourly job — reminds admin via WhatsApp 3 days before hall expiry, warns hall 2 days after expiry, auto-suspends hall after 5 days overdue. Admin confirms payment via button → extends subscription 1 month + clears warnings + unsuspends. Alerts card at top of admin halls page shows halls needing attention. Schema: `subscriptionStartedAt`, `paymentWarningAt`, `hallNotifiedAt` columns on users table.
- **MyFatoorah payment integration (Task #41)**: Admin configures MyFatoorah API token + country + monthly amount in admin panel ("بوابة الدفع" tab). When configured, halls see a "تجديد الاشتراك" card (14 days before expiry) and a subscribe button in SettingsTab. Payment flow: POST /api/hall/payment/initiate → MyFatoorah ExecutePayment → redirect to PaymentURL → GET /api/hall/payment/callback verifies via GetPaymentStatus → extends subscriptionExpiresAt +1 month + sets billingStatus='active'. Hall can cancel via DELETE /api/hall/subscription (notifies admin). Schema additions: `billingStatus varchar`, `nextBillingAt timestamp`, `myfatoorahToken varchar` on users table.
- **Admin two-step login**: admin login requires code + "AmerFamily" password (constant). Admin quota auto-set to -1 on login. If 2FA is enabled, a TOTP step follows password.
- **Multi-admin + Co-Admin support (Task #74)**: `isCoAdmin boolean` column on users table. Three login tiers: (1) Admin (full access, /admin), (2) Co-Admin (limited: add halls + regen user codes with WhatsApp notification, /co-admin), (3) Hall/User. Co-Admins use same admin password + 2FA flow as admins. Admin panel "الأدمن والمساعدون" tab manages both extra-admins (POST/DELETE /api/admin/extra-admins) and co-admins (POST/DELETE /api/admin/co-admins). POST /api/admin/users/:id/regen-code accessible by admin and co-admin. requireAdminOrCoAdmin middleware added. Login/auth/me responses include `isCoAdmin`.
- **Security hardening (CITC/NCA)**: Brute-force protection: in-memory `loginAttempts` Map (5 attempts/15min → auto-ban in `ip_bans` DB table). `getClientIp()` reads `x-forwarded-for` first. Audit logging to `audit_logs` DB table. Security HTTP headers (Helmet + CSP). Admin TOTP 2FA via `otplib` (setup QR → verify → stored in settings as `admin_totp_secret`/`admin_totp_enabled`). Admin panel "الأمان" tab: IP ban management, audit log viewer, 2FA setup/disable. Login page shows password show/hide toggle, remaining-attempts warning, IP-banned alert, TOTP step UI. Copyright "جميع الحقوق محفوظة لإنفايتنا" on login page.
- **One-time WhatsApp 2FA**: `phoneVerified boolean` on users table. ALL non-admin, non-scanner users must verify phone via 6-digit OTP on first login (B2C, hall accounts, hall clients). OTP sent via sendViaAnySystem, stored in settings (otp_code + otp_expires_at, 5-min TTL). POST /api/auth/verify-otp and POST /api/auth/resend-otp endpoints. Admin/scanner exempt. New accounts created by admin/hall/WooCommerce webhook start with phoneVerified=false and must pass OTP on first login.
- **Privacy policy versioning**: Key changed to `privacy_accepted_v2` to force re-acceptance after policy updates (e.g., adding hall promotional content clause).
- **Media reminder logic**: Reminder dialog shown when user tries to bulk-send without media (replaces separate noMedia confirm), or when returning after 1+ hour without media. Not shown on first page load.
- **Anti-ban features (Task #50)**: 3 features to reduce WhatsApp ban risk: (1) Message variation — invisible Unicode chars inserted at random word positions + event detail lines shuffled in 3 random orderings per message; (2) Sender/occasion fields — `event_sender` and `event_occasion` added to EventDetailsCard (required before bulk-send), shown in message footer as `✍ *{sender}*`, custom templates support `{sender}` and `{occasion}` placeholders; (3) Warmup mode — personal accounts < 14 days old show orange warning + are limited to 10 messages/day (tracked via `warmup_sent_date` and `warmup_sent_count` settings); mandatory field validation returns 422 if any of 5 required fields missing; message preview dialog shows formatted preview before bulk-send.
- **Automatic reminder**: Scheduled job runs every hour; sends reminder WhatsApp to all guests who received invitations N days before event. Custom reminder support. Tracked via reminder_sent to prevent duplicates.
- **Automatic cleanup**: Event-date-based cleanup (2 days after event), deletes all user data including scanner accounts and WhatsApp sessions
- **QR check-in**: Optional QR code on invitations with scanner account. Atomic check-in using `UPDATE WHERE checked_in = false RETURNING *` prevents race conditions. Scanner plays Web Audio API beep on success/failure.
- **Public WhatsApp connect page**: `/connect` route allows anyone to view/scan QR code and reconnect system WhatsApp without login

The `auth_info_baileys/` directory contains WhatsApp session authentication data, organized by account (auth_info_baileys/account_{id}/).

# User Preferences

Preferred communication style: Simple, everyday language.

# System Architecture

## Directory Structure
- **`client/`** - React frontend application (Vite-powered)
- **`server/`** - Express.js backend API server
- **`shared/`** - Shared code between frontend and backend (includes `schema.ts` for Drizzle ORM models, `routes.ts` for API route definitions)
- **`migrations/`** - Database migration files generated by Drizzle Kit
- **`auth_info_baileys/`** - WhatsApp session credentials and encryption keys (used by Baileys library)

## Authentication & Multi-tenancy
- **Auth method**: Code-based login (8-character access codes) with WhatsApp recovery
- **Session management**: express-session with PostgreSQL store (connect-pg-simple)
- **Middleware**: `requireAuth` for user routes, `requireAdmin` for admin routes
- **Data isolation**: All queries (guests, settings, WhatsApp accounts) are scoped by userId
- **Admin seeding**: First admin is auto-created on startup, code logged to console

## Frontend Architecture
- **Framework**: React with TypeScript
- **Build Tool**: Vite with `@vitejs/plugin-react`
- **UI Library**: shadcn/ui (new-york style) with Radix UI primitives
- **Styling**: Tailwind CSS with CSS variables for theming, custom color system with border variants
- **State Management / Data Fetching**: TanStack React Query (`@tanstack/react-query`)
- **Forms**: React Hook Form with `@hookform/resolvers` (Zod validation)
- **Routing**: wouter with protected route wrapper
- **Path Aliases**: `@/` maps to `client/src/`, `@shared/` maps to `shared/`, `@assets/` maps to `attached_assets/`

## Frontend Pages
- **`/login`** - Access code login page with WhatsApp recovery option
- **`/dashboard`** - User dashboard (protected) with guest management, WhatsApp accounts, media upload
- **`/admin`** - Admin panel (protected, admin-only) with user management and WooCommerce integration
- **`/i/:id`** - Public invite/RSVP page
- **`/connect`** - Public WhatsApp connect page (no login required, shows QR code for system WhatsApp)

## Backend Architecture
- **Runtime**: Node.js with TypeScript (executed via `tsx`)
- **Framework**: Express.js
- **Entry Point**: `server/index.ts`
- **Key modules**: `server/routes.ts` (API routes), `server/storage.ts` (DB operations), `server/whatsapp.ts` (WhatsApp manager), `server/cleanup.ts` (scheduled cleanup + reminder jobs), `server/message-utils.ts` (shared message templates + buildMessage function)
- **Build Process**: Custom build script at `script/build.ts`, outputs to `dist/` directory
- **Production**: Compiled to `dist/index.cjs` and served with `node`

## Database
- **ORM**: Drizzle ORM with PostgreSQL dialect
- **Schema Location**: `shared/schema.ts` (shared between client and server)
- **Tables**: `users` (with access_code, message_quota), `guests` (user-scoped), `settings` (user-scoped key-value), `whatsapp_accounts` (user-scoped), `whatsapp_auth_data` (auth state per account), `session` (express sessions)
- **Connection**: Uses `DATABASE_URL` environment variable
- **Migrations**: Managed via `drizzle-kit push` command (`npm run db:push`)

## WhatsApp Integration
- **Library**: `@whiskeysockets/baileys` - unofficial WhatsApp Web API
- **Session Storage**: PostgreSQL-based authentication via `usePostgresAuthState` function (stored in `whatsapp_auth_data` table), persists across deployments
- **Multi-account**: WhatsAppManager class manages multiple sessions, tracked by userId
- **QR Code**: `qrcode.react` for rendering QR codes in browser

## WooCommerce Integration
- **Webhook endpoint**: `POST /api/webhook/woocommerce` - receives order data, creates/updates user accounts
- **Auto-provisioning**: On purchase, creates user with access code and sends welcome WhatsApp message
- **Integration page**: Admin panel shows webhook URLs, step-by-step instructions, PHP code for WordPress

## Key Design Decisions
1. **Monorepo with shared schema**: Schema definitions in `shared/` are used by both frontend and backend
2. **Database-based WhatsApp auth**: Baileys session data stored in PostgreSQL (whatsapp_auth_data table) for deployment persistence
3. **Vite dev server with Express**: In development, Vite handles HMR while proxying API to Express
4. **Code-based auth**: 8-character access codes instead of passwords for simplicity
5. **Message quota system**: Quota tracked per user, enforced on send operations
6. **Aggressive cleanup**: Media files deleted after all guests receive invitations, weekly cleanup of old uploads

## Environment Variables Required
- `DATABASE_URL` - PostgreSQL connection string (required, validated at startup)
- `SESSION_SECRET` - Express session secret key
- `WOOCOMMERCE_WEBHOOK_SECRET` - Optional, for webhook verification
- `ADMIN_PASSWORD` - Admin panel password (default: "AmerFamily")
