# Advanced Usage Guide

## Table of Contents
- [Installation](#installation)
- [Cookie Setup](#cookie-setup)
- [Basic Usage](#basic-usage)
- [Advanced Features](#advanced-features)
- [Error Handling](#error-handling)
- [Utilities](#utilities)
- [Best Practices](#best-practices)
- [Troubleshooting](#troubleshooting)

## Installation

```bash
npm install @chiraitori/hoyolab-core
```

## Cookie Setup

### Obtaining Your Cookie

1. **Visit HoYoLab**: Go to [hoyolab.com](https://www.hoyolab.com/) and log in
2. **Open DevTools**: Press F12 or right-click → Inspect
3. **Navigate to Storage**: 
   - Chrome/Edge: Application → Cookies
   - Firefox: Storage → Cookies
4. **Copy Required Values**:
   - `ltoken_v2` (required)
   - `ltuid_v2` (required)
   - `ltmid_v2` (required)
   - `cookie_token_v2` (for code redemption)
   - `account_mid_v2` (for code redemption)
   - `account_id_v2` (for code redemption)

### Cookie Format

```javascript
const cookie = "ltoken_v2=v2_xxx; ltuid_v2=123456; ltmid_v2=xxx; cookie_token_v2=xxx; account_mid_v2=xxx; account_id_v2=123456";
```

### Validating Your Cookie

```javascript
const { utils } = require('@chiraitori/hoyolab-core');

const validation = utils.validateCookie(yourCookie);
if (!validation.valid) {
  console.error('Invalid cookie:', validation.error);
} else {
  console.log('Cookie valid!');
  console.log('Can redeem codes:', validation.hasRedeemTokens);
}
```

## Basic Usage

### Simple Check-in

```javascript
const { HoyoLabClient, Games } = require('@chiraitori/hoyolab-core');

const client = new HoyoLabClient({ cookie: 'your_cookie_here' });

// Check in to Genshin Impact
const result = await client.dailyCheckIn(Games.GENSHIN_IMPACT);
console.log(utils.formatCheckInResult(result));
```

### Code Redemption

```javascript
// Redeem a specific code
const redeemResult = await client.redeemCode(Games.GENSHIN_IMPACT, 'PROMOCODE123');

// Fetch and redeem all available codes
const codes = await client.fetchAvailableCodes(Games.GENSHIN_IMPACT);
for (const code of codes) {
  try {
    await client.redeemCode(Games.GENSHIN_IMPACT, code.code);
    console.log(`Redeemed: ${code.code}`);
  } catch (error) {
    console.error(`Failed: ${code.code} - ${error.message}`);
  }
}
```

## Advanced Features

### Multi-Account Support

```javascript
const { HoyoLabClient, Games } = require('@chiraitori/hoyolab-core');

const accounts = [
  { cookie: 'account1_cookie', name: 'Main Account' },
  { cookie: 'account2_cookie', name: 'Alt Account' }
];

for (const account of accounts) {
  const client = new HoyoLabClient({ cookie: account.cookie });
  
  try {
    const result = await client.dailyCheckIn(Games.GENSHIN_IMPACT);
    console.log(`${account.name}: ${utils.formatCheckInResult(result)}`);
  } catch (error) {
    console.error(`${account.name}: ${error.message}`);
  }
}
```

### Rate Limiting

```javascript
const { utils } = require('@chiraitori/hoyolab-core');

// Create rate limiter (10 calls per minute)
const rateLimiter = new utils.RateLimiter(10, 60000);

for (const code of codes) {
  await rateLimiter.waitIfNeeded();
  
  try {
    await client.redeemCode(Games.GENSHIN_IMPACT, code.code);
  } catch (error) {
    console.error(error.message);
  }
}
```

### Retry with Backoff

```javascript
const { utils } = require('@chiraitori/hoyolab-core');

const performCheckIn = () => client.dailyCheckIn(Games.GENSHIN_IMPACT);

const result = await utils.retryWithBackoff(performCheckIn, {
  maxRetries: 3,
  baseDelay: 1000,
  maxDelay: 10000
});
```

### Caching

```javascript
const { utils } = require('@chiraitori/hoyolab-core');

// Cache for 10 minutes
const cache = new utils.SimpleCache(600000);

// Check cache first
let codes = cache.get('genshin_codes');
if (!codes) {
  codes = await client.fetchAvailableCodes(Games.GENSHIN_IMPACT);
  cache.set('genshin_codes', codes);
}
```

### Timezone-Aware Operations

```javascript
const { utils } = require('@chiraitori/hoyolab-core');

const lastCheckIn = new Date('2025-06-01T10:00:00Z');
const userRegion = 'NA';

if (utils.isNewDay(userRegion, lastCheckIn)) {
  console.log('New day detected, performing check-in...');
  await client.dailyCheckIn(Games.GENSHIN_IMPACT);
}
```

### Region Mapping

Each HoYoverse game uses different region codes. The package provides game-specific region mapping:

```javascript
const { getRegionName, Games } = require('@chiraitori/hoyolab-core');

// Map game-specific region codes to readable names
const genshinRegion = getRegionName(Games.GENSHIN_IMPACT, 'os_usa');     // 'NA'
const starrailRegion = getRegionName(Games.HONKAI_STAR_RAIL, 'prod_official_eur'); // 'EU'
const zenlessRegion = getRegionName(Games.ZENLESS_ZONE_ZERO, 'prod_gf_jp');  // 'SEA'

// Handle account information with proper region names
const accounts = await client.getAccounts(Games.GENSHIN_IMPACT);
for (const account of accounts) {
  console.log(`Account: ${account.nickname}`);
  console.log(`Region: ${getRegionName(Games.GENSHIN_IMPACT, account.region)}`);
  console.log(`UID: ${account.uid}`);
}
```

#### Supported Region Mappings

| Game | Region Code | Display Name |
|------|-------------|--------------|
| **Genshin Impact** | `os_usa` | NA |
| | `os_euro` | EU |
| | `os_asia` | SEA |
| | `os_cht` | TW/HK/MO |
| **Honkai Star Rail** | `prod_official_usa` | NA |
| | `prod_official_eur` | EU |
| | `prod_official_asia` | SEA |
| | `prod_official_cht` | TW/HK/MO |
| **Zenless Zone Zero** | `prod_gf_us` | NA |
| | `prod_gf_eu` | EU |
| | `prod_gf_jp` | SEA |
| | `prod_gf_sg` | TW/HK/MO |

## Error Handling

### Comprehensive Error Handling

```javascript
const { ErrorCodes } = require('@chiraitori/hoyolab-core');

try {
  await client.dailyCheckIn(Games.GENSHIN_IMPACT);
} catch (error) {
  switch (error.code) {
    case ErrorCodes.INVALID_COOKIE:
      console.log('🚫 Cookie expired. Please update your cookie.');
      // Trigger cookie refresh logic
      break;
      
    case ErrorCodes.ALREADY_CHECKED_IN:
      console.log('✅ Already checked in today.');
      break;
      
    case ErrorCodes.RATE_LIMITED:
      console.log('⏰ Rate limited. Waiting 60 seconds...');
      await utils.sleep(60000);
      // Retry logic here
      break;
      
    case ErrorCodes.NETWORK_ERROR:
      console.log('🌐 Network error. Check your connection.');
      break;
      
    default:
      console.error('❌ Unexpected error:', error.message);
      console.error('Details:', error.details);
  }
}
```

### Graceful Degradation

```javascript
const games = [Games.GENSHIN_IMPACT, Games.HONKAI_STAR_RAIL, Games.ZENLESS_ZONE_ZERO];
const results = {};

for (const game of games) {
  try {
    results[game] = await client.dailyCheckIn(game);
  } catch (error) {
    results[game] = { error: error.message, code: error.code };
    
    // Continue with other games even if one fails
    if (error.code !== ErrorCodes.INVALID_COOKIE) {
      continue;
    } else {
      // Stop if cookie is invalid for all games
      break;
    }
  }
}
```

## Utilities

### Helper Functions

```javascript
const { utils } = require('@chiraitori/hoyolab-core');

// Format results for display
const result = await client.dailyCheckIn(Games.GENSHIN_IMPACT);
console.log(utils.formatCheckInResult(result));

// Sleep/delay
await utils.sleep(5000); // 5 seconds

// Get timezone offset
const offset = utils.getTimezoneOffset('NA'); // -300 minutes

// Check if new day
const isNewDay = utils.isNewDay('EU', lastCheckDate);
```

## Best Practices

### 1. Cookie Management

```javascript
// Store cookies securely
const cookies = {
  main: process.env.HOYOLAB_COOKIE_MAIN,
  alt: process.env.HOYOLAB_COOKIE_ALT
};

// Validate before use
for (const [name, cookie] of Object.entries(cookies)) {
  const validation = utils.validateCookie(cookie);
  if (!validation.valid) {
    console.error(`Invalid cookie for ${name}: ${validation.error}`);
  }
}
```

### 2. Scheduled Operations

```javascript
// Use node-cron for scheduling
const cron = require('node-cron');

// Run daily at 1 AM
cron.schedule('0 1 * * *', async () => {
  console.log('Running daily check-ins...');
  
  const games = [Games.GENSHIN_IMPACT, Games.HONKAI_STAR_RAIL];
  
  for (const game of games) {
    try {
      const result = await client.dailyCheckIn(game);
      console.log(`${game}: ${utils.formatCheckInResult(result)}`);
    } catch (error) {
      console.error(`${game}: ${error.message}`);
    }
  }
});
```

### 3. Logging

```javascript
const fs = require('fs');

function logResult(game, result, error = null) {
  const timestamp = new Date().toISOString();
  const logEntry = {
    timestamp,
    game,
    success: !error,
    result: error ? error.message : result,
    errorCode: error ? error.code : null
  };
  
  fs.appendFileSync('hoyolab.log', JSON.stringify(logEntry) + '\n');
}

try {
  const result = await client.dailyCheckIn(Games.GENSHIN_IMPACT);
  logResult(Games.GENSHIN_IMPACT, result);
} catch (error) {
  logResult(Games.GENSHIN_IMPACT, null, error);
}
```

### 4. Configuration Management

```javascript
const config = {
  cookies: {
    main: process.env.HOYOLAB_COOKIE_MAIN
  },
  games: [Games.GENSHIN_IMPACT, Games.HONKAI_STAR_RAIL],
  retryOptions: {
    maxRetries: 3,
    baseDelay: 1000
  },
  rateLimiting: {
    maxCalls: 10,
    windowMs: 60000
  }
};

const client = new HoyoLabClient({ 
  cookie: config.cookies.main,
  userAgent: 'MyApp/1.0.0'
});
```

## Troubleshooting

### Common Issues

1. **"Missing required cookie token"**
   - Ensure all required tokens are present in cookie
   - Check cookie format and spelling

2. **"Invalid or expired cookie"**
   - Re-obtain cookie from browser
   - Ensure you're logged in to HoYoLab

3. **"Rate limited"**
   - Add delays between requests
   - Use the built-in RateLimiter utility

4. **"Already checked in today"**
   - Normal behavior, check-in only once per day
   - Consider timezone differences

5. **"Code redemption not supported"**
   - Some games don't support code redemption
   - Ensure you have redemption tokens in cookie

### Debug Mode

```javascript
const client = new HoyoLabClient({
  cookie: 'your_cookie',
  userAgent: 'MyApp/1.0.0 (debug)'
});

// Enable verbose logging
process.env.DEBUG = 'hoyolab-core:*';
```

### Testing

```javascript
// Test with a minimal example
const { HoyoLabClient, Games, utils } = require('@chiraitori/hoyolab-core');

async function test() {
  const cookie = 'your_test_cookie';
  
  // Validate cookie first
  const validation = utils.validateCookie(cookie);
  console.log('Cookie validation:', validation);
  
  if (!validation.valid) {
    console.error('Invalid cookie, stopping test');
    return;
  }
  
  const client = new HoyoLabClient({ cookie });
  
  try {
    const accounts = await client.getAccounts();
    console.log('Accounts:', accounts);
    
    const result = await client.dailyCheckIn(Games.GENSHIN_IMPACT);
    console.log('Check-in result:', result);
  } catch (error) {
    console.error('Test failed:', error.message);
    console.error('Error code:', error.code);
  }
}

test();
```
