# Billing Service

Go-Microservice fuer Stripe-basiertes Subscription Management mit Task-basierter Abrechnung.

## Uebersicht

Der Billing Service verwaltet:
- Subscription Lifecycle (Trial, Active, Canceled)
- Task-basierte Kontingentierung (1 Task = 1 Einheit)
- Carryover-Logik (Tasks sammeln sich bis zu 5 Monate an)
- Stripe Integration (Checkout, Webhooks, Portal)
- Feature Gating und Entitlements

## Quick Start

### Voraussetzungen

- Go 1.21+
- PostgreSQL 14+
- Docker (optional)

### Lokale Entwicklung

```bash
# 1. Dependencies installieren
go mod download

# 2. Umgebungsvariablen setzen
export DATABASE_URL="postgres://user:pass@localhost:5432/breakpilot?sslmode=disable"
export JWT_SECRET="your-jwt-secret"
export STRIPE_SECRET_KEY="sk_test_..."
export STRIPE_WEBHOOK_SECRET="whsec_..."
export BILLING_SUCCESS_URL="http://localhost:3000/billing/success"
export BILLING_CANCEL_URL="http://localhost:3000/billing/cancel"
export INTERNAL_API_KEY="internal-api-key"
export TRIAL_PERIOD_DAYS="7"
export PORT="8083"

# 3. Service starten
go run cmd/server/main.go

# 4. Tests ausfuehren
go test -v ./...
```

### Mit Docker

```bash
# Service bauen und starten
docker compose up billing-service

# Nur bauen
docker build -t billing-service .
```

## Architektur

```
billing-service/
├── cmd/server/main.go           # Entry Point
├── internal/
│   ├── config/config.go         # Konfiguration
│   ├── database/database.go     # DB Connection + Migrations
│   ├── models/models.go         # Datenmodelle
│   ├── middleware/middleware.go # JWT Auth, CORS, Rate Limiting
│   ├── services/
│   │   ├── subscription_service.go  # Subscription Management
│   │   ├── task_service.go          # Task Consumption
│   │   ├── entitlement_service.go   # Feature Gating
│   │   ├── usage_service.go         # Usage Tracking (Legacy)
│   │   └── stripe_service.go        # Stripe API
│   └── handlers/
│       ├── billing_handlers.go      # API Endpoints
│       └── webhook_handlers.go      # Stripe Webhooks
├── Dockerfile
└── go.mod
```

## Task-basiertes Billing

### Konzept

- **1 Task = 1 Kontingentverbrauch** (unabhaengig von Seitenanzahl, Tokens, etc.)
- **Monatliches Kontingent**: Plan-abhaengig (Basic: 30, Standard: 100, Premium: Fair Use)
- **Carryover**: Ungenutzte Tasks sammeln sich bis zu 5 Monate an
- **Max Balance**: `monthly_allowance * 5` (z.B. Basic: max 150 Tasks)

### Task Types

```go
TaskTypeCorrection = "correction"  // Korrekturaufgabe
TaskTypeLetter     = "letter"      // Brief erstellen
TaskTypeMeeting    = "meeting"     // Meeting-Protokoll
TaskTypeBatch      = "batch"       // Batch-Verarbeitung
TaskTypeOther      = "other"       // Sonstige
```

### Monatswechsel-Logik

Bei jedem API-Aufruf wird geprueft, ob ein Monat vergangen ist:
1. `last_renewal_at` pruefen
2. Falls >= 1 Monat: `task_balance += monthly_allowance`
3. Cap bei `max_task_balance`
4. `last_renewal_at` aktualisieren

## API Endpoints

### User Endpoints (JWT Auth)

| Methode | Endpoint | Beschreibung |
|---------|----------|--------------|
| GET | `/api/v1/billing/status` | Aktueller Billing Status |
| GET | `/api/v1/billing/plans` | Verfuegbare Plaene |
| POST | `/api/v1/billing/trial/start` | Trial starten |
| POST | `/api/v1/billing/change-plan` | Plan wechseln |
| POST | `/api/v1/billing/cancel` | Abo kuendigen |
| GET | `/api/v1/billing/portal` | Stripe Portal URL |

### Internal Endpoints (API Key)

| Methode | Endpoint | Beschreibung |
|---------|----------|--------------|
| GET | `/api/v1/billing/entitlements/:userId` | Entitlements abrufen |
| GET | `/api/v1/billing/entitlements/check/:userId/:feature` | Feature pruefen |
| GET | `/api/v1/billing/tasks/check/:userId` | Task erlaubt? |
| POST | `/api/v1/billing/tasks/consume` | Task konsumieren |
| GET | `/api/v1/billing/tasks/usage/:userId` | Task Usage Info |

### Webhook

| Methode | Endpoint | Beschreibung |
|---------|----------|--------------|
| POST | `/api/v1/billing/webhook` | Stripe Webhooks |

## Plaene und Preise

| Plan | Preis | Tasks/Monat | Max Balance | Features |
|------|-------|-------------|-------------|----------|
| Basic | 9.90 EUR | 30 | 150 | Basis-Features |
| Standard | 19.90 EUR | 100 | 500 | + Templates, Batch |
| Premium | 39.90 EUR | Fair Use | 5000 | + Team, Admin, API |

### Fair Use Mode (Premium)

Im Premium-Plan:
- Keine praktische Begrenzung
- Tasks werden trotzdem getrackt (fuer Monitoring)
- Balance wird nicht dekrementiert
- `CheckTaskAllowed` gibt immer `true` zurueck

## Datenbank

### Wichtige Tabellen

```sql
-- Task-basierte Nutzung pro Account
CREATE TABLE account_usage (
    account_id UUID UNIQUE,
    plan VARCHAR(50),
    monthly_task_allowance INT,
    max_task_balance INT,
    task_balance INT,
    last_renewal_at TIMESTAMPTZ
);

-- Einzelne Task-Records
CREATE TABLE tasks (
    id UUID PRIMARY KEY,
    account_id UUID,
    task_type VARCHAR(50),
    consumed BOOLEAN,
    created_at TIMESTAMPTZ
);
```

## Tests

```bash
# Alle Tests
go test -v ./...

# Mit Coverage
go test -cover ./...

# Nur Models
go test -v ./internal/models/...

# Nur Services
go test -v ./internal/services/...

# Nur Handlers
go test -v ./internal/handlers/...
```

## Stripe Integration

### Webhooks

Konfiguriere im Stripe Dashboard:
```
URL: https://your-domain.com/api/v1/billing/webhook
Events:
  - checkout.session.completed
  - customer.subscription.created
  - customer.subscription.updated
  - customer.subscription.deleted
  - invoice.paid
  - invoice.payment_failed
```

### Lokales Testing

```bash
# Stripe CLI installieren
brew install stripe/stripe-cli/stripe

# Webhook forwarding
stripe listen --forward-to localhost:8083/api/v1/billing/webhook

# Test Events triggern
stripe trigger checkout.session.completed
stripe trigger invoice.paid
```

## Umgebungsvariablen

| Variable | Beschreibung | Beispiel |
|----------|--------------|----------|
| `DATABASE_URL` | PostgreSQL Connection String | `postgres://...` |
| `JWT_SECRET` | JWT Signing Secret | `your-secret` |
| `STRIPE_SECRET_KEY` | Stripe Secret Key | `sk_test_...` |
| `STRIPE_WEBHOOK_SECRET` | Webhook Signing Secret | `whsec_...` |
| `BILLING_SUCCESS_URL` | Checkout Success Redirect | `http://...` |
| `BILLING_CANCEL_URL` | Checkout Cancel Redirect | `http://...` |
| `INTERNAL_API_KEY` | Service-to-Service Auth | `internal-key` |
| `TRIAL_PERIOD_DAYS` | Trial Dauer in Tagen | `7` |
| `PORT` | Server Port | `8083` |

## Error Handling

### Task Limit Reached

```json
{
  "error": "TASK_LIMIT_REACHED",
  "message": "Dein Aufgaben-Kontingent ist aufgebraucht.",
  "current_balance": 0,
  "plan": "basic"
}
```

HTTP Status: `402 Payment Required`

### No Subscription

```json
{
  "error": "NO_SUBSCRIPTION",
  "message": "Kein aktives Abonnement gefunden."
}
```

HTTP Status: `403 Forbidden`

## Frontend Integration

### Task Usage anzeigen

```typescript
// Response von GET /api/v1/billing/status
interface TaskUsageInfo {
  tasks_available: number;  // z.B. 45
  max_tasks: number;        // z.B. 150
  info_text: string;        // "Aufgaben verfuegbar: 45 von max. 150"
  tooltip_text: string;     // "Aufgaben koennen sich bis zu 5 Monate ansammeln."
}
```

### Task konsumieren

```typescript
// Vor jeder KI-Aktion
const response = await fetch('/api/v1/billing/tasks/check/' + userId);
const { allowed, message } = await response.json();

if (!allowed) {
  showUpgradeDialog(message);
  return;
}

// Nach erfolgreicher KI-Aktion
await fetch('/api/v1/billing/tasks/consume', {
  method: 'POST',
  body: JSON.stringify({ user_id: userId, task_type: 'correction' })
});
```
