# SDK Guidelines para Agentes IA

## Arquitectura

SDK monolítico para React Native/Expo que centraliza funcionalidades core de aplicaciones móviles. No es multi-plataforma aún (planificado). Estructura singleton con módulos especializados.

## Punto de Entrada

```javascript
import SDK from 'apps-sdk';
await SDK.session.init();
```

**Inicialización obligatoria**: `SDK.session.init()` debe ejecutarse al inicio de la app. Configura:
- Estructura de sesión con datos de device/app
- UserID persistente
- Endpoints desde backend
- Configuración de tracking y eventos
- Validación de suscripción

## Módulos Core

### Session (`SDK.session`)
Gestión de sesión, datos de usuario y configuración global.

**Responsabilidades**:
- Generar y mantener sessionID
- Almacenar datos de device (modelo, OS, versión)
- Gestionar userID persistente
- Detectar first_open
- Estado de suscripción
- Configuración de idioma/región

**Flujo típico**:
```javascript
await SDK.session.init();
const userID = SDK.session.getUserID();
const isSubscribed = SDK.session.getIsSubscribed();
const deviceLang = SDK.session.getDeviceLanguage();
```

**sessionData estructura**:
```javascript
{
  user_id: string,
  isFirstOpen: boolean,
  app: { shortVersion, package, languageCode, regionCode, buildVersionNumber },
  device: { name, systemName, systemVersion, model },
  adjust: { attribution_id, idfa, googleAdid, attribution },
  lang: string,
  package: string
}
```

### Storage (`SDK.storage`)
Persistencia local con AsyncStorage + FileSystem de Expo.

**Patrones de uso**:
```javascript
// Datos JSON simples
await SDK.storage.storeData(key, value);
const data = await SDK.storage.getData(key);
await SDK.storage.removeData(key);

// Imágenes en galería
await SDK.storage.handleDownloadImageToGallery(imageUri);

// Sistema de archivos (creations)
await SDK.storage.handleDownloadImageToCreations(base64, fileName, metadata);
const creations = await SDK.storage.getCreations();
await SDK.storage.deleteCreation(dirName);

// Compresión automática
const compressed = await SDK.storage.compressImage(imageUri, maxSizeMB);

// Compartir archivos
await SDK.storage.handleShareFile(fileUri);
```

**Directorios**:
- `${FileSystem.documentDirectory}/creations` - Almacenamiento persistente
- `${FileSystem.documentDirectory}/tmp` - Temporal (se limpia con `deleteTempFiles()`)

**Permisos**: Gestiona permisos de galería automáticamente, solicitándolos cuando sea necesario.

### Networking (`SDK.networking`)
Comunicación HTTP con backend. Todas las peticiones incluyen `sessionData` automáticamente.

**Request unificado**:
```javascript
const response = await SDK.networking.request(url, data);
```

**Sistema de eventos**:
```javascript
await SDK.networking.sendEvent(eventType, eventKeyword, eventData);
// eventType: 'action', 'screen', 'other'
// Se envía a tracking (Adjust) automáticamente
```

**Eventos especiales**: Primera ocurrencia de eventos se trackea con prefijo `first_` (ej: `first_paywall_shown`).

**Pending Events**: Cola para eventos que no pueden enviarse de inmediato:
```javascript
SDK.networking.addPendingEvent({ eventType, eventKeyword, eventData });
SDK.networking.sendPendingEvents();
```

**Configuración dinámica**: `executeInit()` carga desde backend:
- Endpoints (`config.ENDPOINTS`)
- Eventos de tracking (`config.EVENTS`)
- Configuración de paywall (`config.PAYWALL_DATA`)
- Forced update check
- Quick actions
- Compresión de imágenes

### Utils (`SDK.utils`)
Funciones auxiliares:
```javascript
SDK.utils.isBase64(str);
SDK.utils.isBase64Image(str);
SDK.utils.isSpecialEvent(eventKeyword);
```

## Integraciones de Analytics

### Adjust (`SDK.adjust`)
Attribution y tracking de instalación.

```javascript
await SDK.adjust.initialize(adjustToken, sendAttributionToAdapty);
SDK.adjust.trackEventIfExist(eventKeyword, eventValue);
await SDK.adjust.getAttribution();
await SDK.adjust.getIdfa(); // iOS
await SDK.adjust.getGoogleAdId(); // Android
```

**Integración con Session**: Attribution data se almacena en `sessionData.adjust`.

### MixPanel (`SDK.mixpanel`)
Analytics de comportamiento.

```javascript
await SDK.mixpanel.initialize(token, trackAutomaticEvents, useNative, devMode);
await SDK.mixpanel.trackEvent(event, properties);
await SDK.mixpanel.identifyUser(userID);
await SDK.mixpanel.superProperties({ plan_type: 'premium' });
```

**Super Properties**: Propiedades globales que se envían con todos los eventos.

### Facebook (`SDK.facebook`)
Facebook Analytics.

```javascript
await SDK.facebook.initialize(appId, clientToken, debugMode, devMode);
await SDK.facebook.trackEvent(eventName, properties);
await SDK.facebook.trackPurchase(amount, currency);
await SDK.facebook.trackStartTrial();
```

## Sistema de Paywall

### Adapty (`SDK.adapty`)
Gestión de suscripciones y paywalls.

```javascript
await SDK.adapty.initialize(apiKey);
await SDK.adapty.showPaywall(placementID, lang, eventHandlers);
const profile = await SDK.adapty.getProfile();
await SDK.adapty.updateAdjustAttributionData(attribution);
```

**Event Handlers**:
```javascript
{
  onPurchaseCompleted: (result, product) => {},
  onPurchaseFailed: (error) => {},
  onRestoreCompleted: (profile) => {},
  onCloseButtonPress: () => {}
}
```

**Onboarding**:
```javascript
await SDK.adapty.showOnboarding(placementID, lang, eventHandlers);
```

### PayWall Component (`SDK.paywall`)
Componente React para paywalls custom.

```jsx
<SDK.paywall
  visible={true}
  onClose={() => {}}
  type="subscription"
  keyword="premium_monthly"
/>
```

### PayWallLogic (`SDK.paywallLogic`)
Lógica de compra con react-native-iap (legacy, usar Adapty).

## Funcionalidades Específicas

### Notifications (`SDK.notifications`)
Push notifications con Expo Notifications.

```javascript
await SDK.initializePushNotifications(); // Retorna expo token
const status = await SDK.getPushNotificationsStatus();
```

**Token se envía automáticamente** al backend en `initializePushNotifications()`.

### Rating (`SDK.rating`)
Sistema de reviews.

```javascript
await SDK.rating.showRatingDialog(force);
```

### Voice (`SDK.voice`)
Speech-to-text y text-to-speech.

```javascript
// Speech-to-text
await SDK.voice.startRecognizing(
  onSpeechStart,
  onSpeechRecognized,
  onSpeechResults,
  onInactivityTimeout,
  inactivitySeconds
);
await SDK.voice.stopRecognizing();

// Text-to-speech
SDK.voice.speak(message, language, voice, onStart, onDone, onError);
await SDK.voice.stopSpeaking();
```

### TrackingTransparency (`SDK.tracking`)
ATT para iOS.

```javascript
const status = await SDK.tracking.requestTrackingTransparencyPermission();
const idfa = await SDK.tracking.getAdvertisingIdentifier();
```

**Almacenamiento automático**: El estado se guarda en `TRACKING_PERMISSION` y actualiza `config.TRACKING_ACTIVE`.

### HomeActions (`SDK.homeActions`)
Quick Actions (iOS/Android shortcuts).

```javascript
await SDK.homeActions.setItems(quickActionsArray);
await SDK.homeActions.itemCallback(callbackFunction);
```

## Configuración Global

### config.js
Variables globales del SDK:

```javascript
config.DEBUG_MODE = true/false;
config.TRACKING_ACTIVE = true/false;
config.FORCED_UPDATE = true/false;
config.ENDPOINTS = { CONFIG, EVENTS_PUSH, SUB_STATUS, ... };
config.EVENTS = { eventKeyword: eventToken };
config.EVENTS_MIXPANEL = { eventKeyword: eventName };
config.PAYWALL_DATA = { actions, scenes, others, products };
config.CONFIG_EXTRA = {}; // Configuración custom desde backend
config.QUICK_ACTIONS = []; // Quick actions desde backend
config.IMAGE_COMPRESSION = { ACTIVE, COMPRESSION, WIDTH };
config.EVENT_TYPES = { ACTION: 'action', SCREEN: 'screen', OTHER: 'other' };
```

## Principios de Diseño

1. **Singleton Pattern**: Todos los módulos son instancias singleton exportadas directamente
2. **Auto-inicialización**: Módulos se inicializan en importación cuando sea posible
3. **sessionData global**: Todas las peticiones incluyen sessionData automáticamente
4. **Persistencia transparente**: Storage abstrae AsyncStorage para uso sencillo
5. **Error handling silencioso**: Logs en consola, no crashes
6. **Permission management**: Gestión automática de permisos con fallback a settings

## Convenciones

- **Async/await**: Todas las operaciones I/O usan async/await
- **Console logs condicionales**: `config.DEBUG_MODE && console.debug(...)`
- **Naming**: camelCase para métodos, UPPER_CASE para constantes globales
- **Return values**: null en caso de error, throw solo cuando sea crítico
- **Storage keys**: Snake_case en mayúsculas (ej: `TRACKING_PERMISSION`)
- **Event naming**: snake_case en minúsculas (ej: `first_open`, `paywall_shown`)

## Dependencias Críticas

```json
{
  "@react-native-async-storage/async-storage": "Persistencia",
  "expo-file-system": "Sistema de archivos",
  "expo-media-library": "Galería",
  "expo-notifications": "Push notifications",
  "expo-constants": "App metadata",
  "expo-device": "Device info",
  "react-native-adapty": "Suscripciones",
  "react-native-adjust": "Attribution",
  "mixpanel-react-native": "Analytics",
  "react-native-fbsdk-next": "Facebook",
  "@react-native-voice/voice": "Speech",
  "expo-tracking-transparency": "ATT iOS",
  "react-native-iap": "IAP legacy",
  "semver": "Version comparison"
}
```

## Flujo de Inicialización Típico

```javascript
// 1. Inicializar SDK
await SDK.session.init();

// 2. Configurar tracking (si necesario)
const trackingStatus = await SDK.tracking.requestTrackingTransparencyPermission();
await SDK.storage.setTrackingPermissionGranted(trackingStatus === 'authorized');

// 3. Inicializar analytics
await SDK.adjust.initialize(ADJUST_TOKEN, true);
await SDK.mixpanel.initialize(MIXPANEL_TOKEN);
await SDK.facebook.initialize(FB_APP_ID, FB_CLIENT_TOKEN);

// 4. Inicializar monetización
await SDK.adapty.initialize(ADAPTY_KEY);
await SDK.adapty.setAdjustIntegrationIdentifier(adjustIntegrationID);
await SDK.adapty.setMixpanelIntegrationIdentifier(mixpanelDistinctID);

// 5. Setup notifications
const expoToken = await SDK.initializePushNotifications();

// 6. Limpiar temporal
await SDK.storage.deleteTempFiles();

// 7. Verificar suscripción cada 24h
await SDK.session.checkSubscription24h();
```

## TypeScript Support

Definiciones completas en `types/index.d.ts`. Todos los módulos y métodos están tipados.

## Debugging

```javascript
// Console override automático con timestamps
SDK.sobrescribeConsole(); // Ya ejecutado en constructor

// Ver todas las claves de AsyncStorage
await SDK.storage.printAllKeys();

// Limpiar todo AsyncStorage
await SDK.storage.removeAllKeys();

// Verificar endpoints cargados
const endpoints = await SDK.networking.getEndpoints();

// Ver configuración extra del backend
const config = SDK.networking.getConfigExtra();
```

## Limitaciones Conocidas

- **Solo Expo/React Native**: No funciona en web ni otras plataformas
- **Backend dependency**: Requiere endpoints configurados para init
- **Singleton limitations**: No soporta múltiples instancias
- **No lazy loading**: Todos los módulos se cargan al importar
- **AsyncStorage limits**: No usar para datos grandes (>6MB)

## Migración a Arquitectura Multi-plataforma (Futuro)

Estructura planificada con adaptadores:
- `@apps-sdk/core`: Lógica compartida
- `@apps-sdk/expo`: Adaptadores React Native/Expo
- `@apps-sdk/web`: Adaptadores Web (localStorage, Canvas, etc)

Ver `EJEMPLO_USO_SDK.md` para detalles de arquitectura propuesta.
