# Customer Domain - Type Naming Clarity

## The Problem

Current naming is confusing:
- `PortalUser` - What is this?
- `CustomerProfile` - Is this different from a user?
- `UserProfile` - How is this different from the above?
- `AuthenticatedUser` - Another alias?

## Proposed Clear Naming

### Core Principle: Same Entity, Different Data Sources

A customer/user is **ONE business entity** with data from **TWO sources**:

1. **Portal Database** → Authentication & account state
2. **WHMCS** → Profile & billing information

## Recommended Schema Structure

```typescript
// packages/domain/customer/types.ts

// ============================================================================
// User Auth State (from Portal Database)
// ============================================================================

/**
 * User authentication and account state stored in portal database
 * Source: Portal DB (Prisma)
 * Contains: Auth-related fields only
 */
export const userAuthSchema = z.object({
  id: z.string().uuid(),              // Portal user ID (primary key)
  email: z.string().email(),          // Email (for login)
  role: z.enum(["USER", "ADMIN"]),    // User role
  emailVerified: z.boolean(),         // Email verification status
  mfaEnabled: z.boolean(),            // MFA enabled flag
  lastLoginAt: z.string().optional(), // Last login timestamp
  createdAt: z.string(),              // Account created date
  updatedAt: z.string(),              // Account updated date
});

export type UserAuth = z.infer<typeof userAuthSchema>;


// ============================================================================
// Customer Profile Data (from WHMCS)
// ============================================================================

/**
 * Customer profile and billing information from WHMCS
 * Source: WHMCS API
 * Contains: Personal info, address, preferences
 */
export const customerDataSchema = z.object({
  whmcsClientId: z.number().int(),           // WHMCS client ID
  firstname: z.string().nullable().optional(),
  lastname: z.string().nullable().optional(),
  fullname: z.string().nullable().optional(),
  companyname: z.string().nullable().optional(),
  phonenumber: z.string().nullable().optional(),
  address: customerAddressSchema.optional(),
  language: z.string().nullable().optional(),
  currencyCode: z.string().nullable().optional(),
  // ... other WHMCS fields
});

export type CustomerData = z.infer<typeof customerDataSchema>;


// ============================================================================
// Complete User (Auth + Profile Data)
// ============================================================================

/**
 * Complete user profile combining auth state and customer data
 * Composition: UserAuth (portal) + CustomerData (WHMCS)
 * This is what gets returned in API responses
 */
export const userSchema = userAuthSchema.extend({
  // Add customer data fields
  firstname: z.string().nullable().optional(),
  lastname: z.string().nullable().optional(),
  fullname: z.string().nullable().optional(),
  companyname: z.string().nullable().optional(),
  phonenumber: z.string().nullable().optional(),
  address: customerAddressSchema.optional(),
  language: z.string().nullable().optional(),
  currencyCode: z.string().nullable().optional(),
});

/**
 * Complete user - exported as 'User' for simplicity
 * Use this in API responses and business logic
 */
export type User = z.infer<typeof userSchema>;
```

## Naming Comparison

### Option A: Auth/Data (Recommended)
```typescript
UserAuth          // Auth state from portal DB
CustomerData      // Profile data from WHMCS  
User              // Complete entity
```

**Pros:**
- Clear distinction: "Auth" = authentication, "Data" = profile information
- Simple exports: `User` is the main type
- Intuitive: "I need UserAuth for JWT" vs "I need User for profile API"

**Cons:**
- "CustomerData" might seem weird (but it's accurate - it's WHMCS customer data)

### Option B: Portal/Customer (Current-ish)
```typescript
PortalUser        // Auth state from portal DB
CustomerProfile   // Profile data from WHMCS
User              // Complete entity
```

**Pros:**
- "Portal" clearly indicates source
- "CustomerProfile" is business-domain language

**Cons:**
- "PortalUser" vs "User" - what's the difference?
- Implies there are different "user" entities (there's only ONE user)

### Option C: Auth/Profile (Simple)
```typescript
AuthUser          // Auth state
ProfileData       // Profile info
User              // Complete entity
```

**Pros:**
- Very simple and clear
- Purpose-driven naming

**Cons:**
- Less obvious where data comes from

### Option D: Keep Descriptive (Verbose but Clear)
```typescript
UserAuthState           // Auth state from portal DB
CustomerProfileData     // Profile data from WHMCS
UserWithProfile         // Complete entity
```

**Pros:**
- Extremely explicit
- No ambiguity

**Cons:**
- Verbose
- "UserWithProfile" is awkward

## Recommended: Option A

```typescript
// Clear and intuitive
import type { UserAuth, CustomerData, User } from "@customer-portal/domain/customer";

// In JWT strategy - only need auth state
async validate(payload: JwtPayload): Promise<UserAuth> {
  return this.getAuthState(payload.sub);
}

// In profile API - need complete user
async getProfile(userId: string): Promise<User> {
  const auth = await this.getAuthState(userId);
  const data = await this.getCustomerData(userId);
  
  return {
    ...auth,
    ...data,
  };
}
```

## Provider Structure

```
packages/domain/customer/providers/
├── portal/
│   ├── types.ts           # PrismaUserRaw interface
│   └── mapper.ts          # Prisma → UserAuth
│
└── whmcs/
    ├── types.ts           # WhmcsClientRaw interface
    └── mapper.ts          # WHMCS → CustomerData
```

## What Gets Exported

```typescript
// packages/domain/customer/index.ts

export type {
  // Core types (use these in your code)
  User,              // Complete user (UserAuth + CustomerData)
  UserAuth,          // Auth state only (for JWT, auth checks)
  CustomerData,      // Profile data only (rarely used directly)
  
  // Supporting types
  CustomerAddress,
  // ... etc
} from "./types";

export {
  // Schemas for validation
  userSchema,
  userAuthSchema,
  customerDataSchema,
  // ... etc
} from "./types";

export * as Providers from "./providers";
```

## Auth Domain References User

```typescript
// packages/domain/auth/types.ts

import { userSchema } from "../customer/types";

export const authResponseSchema = z.object({
  user: userSchema,        // Reference the User schema from customer domain
  tokens: authTokensSchema,
});

export type AuthResponse = z.infer<typeof authResponseSchema>;
```

## Summary

**Entity**: ONE user/customer entity

**Data Sources**:
- `UserAuth` - From portal database (auth state)
- `CustomerData` - From WHMCS (profile data)

**Combined**:
- `User` - Complete entity (auth + profile)

**Usage**:
- JWT validation → `UserAuth`
- API responses → `User`
- Internal mapping → `CustomerData` (via providers)

