# Analytics Service - Complete Usage Guide

## Table of Contents
1. [What We Can Do](#what-we-can-do)
2. [How It Works: Computed vs On-Demand](#how-it-works)
3. [Available Analytics](#available-analytics)
4. [Specific Use Cases](#specific-use-cases)

---

## What We Can Do

The Analytics Service provides comprehensive insights into your clinic operations:

### 📊 **Financial Intelligence**
- Track total revenue, average revenue per appointment
- Monitor payment status (paid, unpaid, refunded)
- Analyze costs per patient
- Revenue trends over time

### 👨‍⚕️ **Practitioner Performance**
- Appointment counts and completion rates
- Cancellation and no-show rates per doctor
- Time efficiency (booked vs actual time)
- Revenue generation per practitioner
- Patient retention rates

### 🏥 **Procedure Analytics**
- Most popular procedures
- Most profitable procedures
- Procedure performance by category/technology
- Product usage per procedure

### ⏱️ **Time Management**
- Booked time vs actual time spent
- Efficiency percentages
- Overrun/underutilization analysis
- Peak hours identification

### ❌ **Cancellation & No-Show Analysis**
- Rates by clinic, practitioner, patient, or procedure
- Cancellation reasons breakdown
- Average cancellation lead time
- Patterns and trends

### 👥 **Patient Insights**
- Patient lifetime value
- Retention rates
- Appointment frequency
- Cancellation patterns per patient

### 📦 **Product Usage**
- Products used per appointment
- Revenue contribution by product
- Usage by procedure
- Quantity and pricing trends

### 🏢 **Clinic Performance**
- Overall clinic metrics
- Practitioner comparisons
- Procedure popularity
- Efficiency metrics

---

## How It Works: Computed vs On-Demand

### 🔄 **Hybrid Architecture**

The service uses a **smart hybrid approach**:

```
┌─────────────────────────────────────────┐
│   Client Request                        │
└──────────────┬──────────────────────────┘
               │
               ▼
┌─────────────────────────────────────────┐
│   Check Stored Analytics?               │
└──────┬──────────────────────┬───────────┘
       │                      │
   YES │                      │ NO
       ▼                      ▼
┌──────────────┐    ┌─────────────────────┐
│ Data Fresh?  │    │ Calculate On-Demand │
│ (< 12 hours) │    │ (Query Appointments)│
└──┬───────┬───┘    └─────────────────────┘
   │       │
YES│       │NO
   │       │
   ▼       ▼
┌─────┐ ┌─────────────────────┐
│ ✅  │ │ Calculate On-Demand  │
│Fast │ │ (Query Appointments)│
└─────┘ └─────────────────────┘
```

### 📦 **Pre-Computed Analytics (Recommended)**

**How it works:**
1. **Cloud Function runs every 12 hours** (scheduled)
2. Computes analytics for all clinics
3. Stores results in Firestore: `clinics/{clinicBranchId}/analytics/`
4. Client reads cached data (1 document read = instant)

**Benefits:**
- ⚡ **Fast**: Instant response (single document read)
- 💰 **Cheap**: 1 read vs hundreds/thousands
- 📈 **Scalable**: Works with large datasets

**Example:**
```typescript
// Automatically uses cached data if available and fresh (< 12 hours)
const dashboard = await analyticsService.getDashboardData(
  { clinicBranchId: 'clinic-123' },
  { start: new Date('2024-01-01'), end: new Date('2024-12-31') }
);
// Returns instantly from cache! ⚡
```

### 🔄 **On-Demand Calculation (Fallback)**

**When it happens:**
- No cached data exists yet
- Cached data is stale (> 12 hours old)
- You explicitly disable cache: `{ useCache: false }`
- Custom date range that doesn't match pre-computed periods

**How it works:**
1. Queries all appointments matching filters
2. Calculates metrics in real-time
3. Returns results

**Example:**
```typescript
// Force on-demand calculation
const dashboard = await analyticsService.getDashboardData(
  { clinicBranchId: 'clinic-123' },
  { start: new Date('2024-01-01'), end: new Date('2024-12-31') },
  { useCache: false } // Force calculation
);
// Calculates from scratch (slower but always fresh)
```

### ⚙️ **Configuration**

**Change cache freshness:**
```typescript
// Use cache if data is less than 6 hours old
const dashboard = await analyticsService.getDashboardData(
  { clinicBranchId: 'clinic-123' },
  dateRange,
  { maxCacheAgeHours: 6 }
);
```

**Change Cloud Function schedule:**
Edit `Cloud/functions/src/analytics/computeAnalytics.ts`:
```typescript
schedule: "every 6 hours" // or "every 24 hours", etc.
```

---

## Available Analytics

### 1. **Practitioner Analytics** 👨‍⚕️

```typescript
const metrics = await analyticsService.getPractitionerAnalytics(
  'practitioner-id-123',
  { start: new Date('2024-01-01'), end: new Date('2024-12-31') }
);

// Returns:
{
  practitionerId: string;
  practitionerName: string;
  totalAppointments: number;
  completedAppointments: number;
  canceledAppointments: number;
  noShowAppointments: number;
  cancellationRate: number; // percentage
  noShowRate: number; // percentage
  averageBookedTime: number; // minutes
  averageActualTime: number; // minutes
  timeEfficiency: number; // percentage
  totalRevenue: number;
  averageRevenuePerAppointment: number;
  topProcedures: Array<{ procedureId, procedureName, count, revenue }>;
  patientRetentionRate: number;
  uniquePatients: number;
}
```

### 2. **Procedure Analytics** 🏥

```typescript
// Single procedure
const procedure = await analyticsService.getProcedureAnalytics(
  'procedure-id-123',
  dateRange
);

// All procedures
const allProcedures = await analyticsService.getProcedureAnalytics(
  undefined,
  dateRange
);

// Most popular
const popular = await analyticsService.getProcedurePopularity(dateRange, 10);

// Most profitable
const profitable = await analyticsService.getProcedureProfitability(dateRange, 10);
```

### 3. **Time Efficiency** ⏱️

```typescript
const timeMetrics = await analyticsService.getTimeEfficiencyMetrics(
  { clinicBranchId: 'clinic-123' },
  dateRange
);

// Returns:
{
  averageBookedDuration: number; // minutes
  averageActualDuration: number; // minutes
  averageEfficiency: number; // percentage
  averageOverrun: number; // minutes
  averageUnderutilization: number; // minutes
  efficiencyDistribution: Array<{ range: string, count: number }>;
}
```

### 4. **Cancellation Metrics** ❌

```typescript
// Grouped by clinic, practitioner, patient, or procedure
const cancellations = await analyticsService.getCancellationMetrics(
  'practitioner', // or 'clinic', 'patient', 'procedure'
  dateRange
);

// Returns array of:
{
  entityId: string;
  entityName: string;
  entityType: 'practitioner' | 'clinic' | 'patient' | 'procedure';
  totalAppointments: number;
  canceledAppointments: number;
  cancellationRate: number; // percentage
  canceledByPatient: number;
  canceledByClinic: number;
  averageCancellationLeadTime: number; // hours
  cancellationReasons: Array<{ reason: string, count: number }>;
}
```

### 5. **No-Show Metrics** 🚫

```typescript
const noShows = await analyticsService.getNoShowMetrics(
  'practitioner', // or 'clinic', 'patient', 'procedure'
  dateRange
);

// Returns array of:
{
  entityId: string;
  entityName: string;
  entityType: 'practitioner' | 'clinic' | 'patient' | 'procedure';
  totalAppointments: number;
  noShowAppointments: number;
  noShowRate: number; // percentage
}
```

### 6. **Revenue Metrics** 💰

```typescript
const revenue = await analyticsService.getRevenueMetrics(
  { clinicBranchId: 'clinic-123' },
  dateRange
);

// Returns:
{
  totalRevenue: number;
  averageRevenuePerAppointment: number;
  revenueByStatus: Record<AppointmentStatus, number>;
  revenueByPaymentStatus: Record<PaymentStatus, number>;
  unpaidRevenue: number;
  refundedRevenue: number;
}
```

### 7. **Product Usage** 📦

```typescript
// All products
const products = await analyticsService.getProductUsageMetrics(
  undefined,
  dateRange
);

// Specific product
const product = await analyticsService.getProductUsageMetrics(
  'product-id-123',
  dateRange
);
```

### 8. **Patient Analytics** 👥

```typescript
// Single patient
const patient = await analyticsService.getPatientAnalytics(
  'patient-id-123',
  dateRange
);

// All patients
const allPatients = await analyticsService.getPatientAnalytics(
  undefined,
  dateRange
);
```

### 9. **Dashboard Data** 📊

```typescript
const dashboard = await analyticsService.getDashboardData(
  { clinicBranchId: 'clinic-123' },
  dateRange
);

// Returns comprehensive dashboard with:
// - Overview metrics
// - Top practitioners
// - Top procedures
// - Cancellation/no-show metrics
// - Revenue trends
// - Time efficiency
// - Top products
// - Recent activity
```

---

## Specific Use Cases

### Use Case 1: Patient No-Show Per Doctor 👨‍⚕️

**Question**: "Which patients have the highest no-show rate for each doctor?"

**Solution**: Get no-show metrics grouped by practitioner, then filter by patient if needed.

```typescript
// Step 1: Get no-show metrics grouped by practitioner
const noShowByPractitioner = await analyticsService.getNoShowMetrics(
  'practitioner',
  { start: new Date('2024-01-01'), end: new Date('2024-12-31') }
);

// Returns array like:
// [
//   {
//     entityId: 'practitioner-123',
//     entityName: 'Dr. Smith',
//     entityType: 'practitioner',
//     totalAppointments: 100,
//     noShowAppointments: 15,
//     noShowRate: 15.0
//   },
//   ...
// ]

// Step 2: For a specific practitioner, get patient-level no-shows
// (You can filter appointments and calculate manually, or use patient analytics)

// Get all appointments for a specific practitioner
const practitionerAppointments = await analyticsService['fetchAppointments'](
  { practitionerId: 'practitioner-123' },
  dateRange
);

// Group no-shows by patient
const noShowByPatient = new Map<string, { name: string; noShows: number; total: number }>();

practitionerAppointments.forEach(appointment => {
  const patientId = appointment.patientId;
  const patientName = appointment.patientInfo?.fullName || 'Unknown';
  
  if (!noShowByPatient.has(patientId)) {
    noShowByPatient.set(patientId, { name: patientName, noShows: 0, total: 0 });
  }
  
  const patientData = noShowByPatient.get(patientId)!;
  patientData.total++;
  
  if (appointment.status === AppointmentStatus.NO_SHOW) {
    patientData.noShows++;
  }
});

// Calculate rates
const patientNoShowRates = Array.from(noShowByPatient.entries()).map(([patientId, data]) => ({
  patientId,
  patientName: data.name,
  totalAppointments: data.total,
  noShowCount: data.noShows,
  noShowRate: (data.noShows / data.total) * 100
})).sort((a, b) => b.noShowRate - a.noShowRate);

console.log('Patient no-show rates for this practitioner:');
patientNoShowRates.forEach(patient => {
  console.log(`${patient.patientName}: ${patient.noShowRate.toFixed(1)}% (${patient.noShowCount}/${patient.total})`);
});
```

### Use Case 2: Doctor Performance Comparison 📊

```typescript
// Get all practitioners for a clinic
const practitioners = await analyticsService.getCancellationMetrics(
  'practitioner',
  { start: new Date('2024-01-01'), end: new Date('2024-12-31') }
);

// Filter by clinic if needed (would need clinicBranchId in filters)
const clinicPractitioners = practitioners.filter(p => 
  // Filter logic based on your needs
);

// Compare metrics
practitioners.forEach(practitioner => {
  console.log(`${practitioner.entityName}:`);
  console.log(`  Cancellation Rate: ${practitioner.cancellationRate}%`);
  console.log(`  Total Appointments: ${practitioner.totalAppointments}`);
});
```

### Use Case 3: Procedure Profitability Analysis 💰

```typescript
// Get most profitable procedures
const profitable = await analyticsService.getProcedureProfitability(
  { start: new Date('2024-01-01'), end: new Date('2024-12-31') },
  10 // Top 10
);

profitable.forEach((procedure, index) => {
  console.log(`${index + 1}. ${procedure.procedureName}`);
  console.log(`   Revenue: ${procedure.totalRevenue} ${procedure.currency || 'CHF'}`);
  console.log(`   Appointments: ${procedure.appointmentCount}`);
  console.log(`   Avg Revenue: ${procedure.averageRevenue.toFixed(2)}`);
});
```

### Use Case 4: Time Efficiency by Doctor ⏱️

```typescript
// Get time efficiency for a specific practitioner
const practitionerMetrics = await analyticsService.getPractitionerAnalytics(
  'practitioner-id-123',
  dateRange
);

console.log(`Time Efficiency: ${practitionerMetrics.timeEfficiency}%`);
console.log(`Avg Booked Time: ${practitionerMetrics.averageBookedTime} min`);
console.log(`Avg Actual Time: ${practitionerMetrics.averageActualTime} min`);

// Or get overall time efficiency with filters
const timeMetrics = await analyticsService.getTimeEfficiencyMetrics(
  { practitionerId: 'practitioner-id-123' },
  dateRange
);
```

### Use Case 5: Product Cost Analysis 📦

```typescript
// Get product usage for a specific procedure
const procedureAnalytics = await analyticsService.getProcedureAnalytics(
  'procedure-id-123',
  dateRange
);

// Check product usage
procedureAnalytics.productUsage.forEach(product => {
  console.log(`${product.productName}:`);
  console.log(`  Total Quantity: ${product.totalQuantity}`);
  console.log(`  Total Revenue: ${product.totalRevenue}`);
  console.log(`  Used in ${product.usageCount} appointments`);
});
```

---

## Performance Tips

1. **Use pre-computed analytics** when possible (default behavior)
2. **Specify clinicBranchId** in filters to enable caching
3. **Use standard date ranges** (daily, weekly, monthly) for better cache hits
4. **Batch requests** when getting multiple practitioners/procedures
5. **Cache results** on the client side for frequently accessed dashboards

---

## Next Steps

1. **Deploy Cloud Function**: Deploy `computeAnalytics.ts` to start pre-computing
2. **Test with real data**: Verify analytics accuracy
3. **Monitor performance**: Check Cloud Function logs and Firestore usage
4. **Customize**: Adjust cache age and computation schedule as needed

