/**
 * 認證相關 API 場景模組
 * 
 * 此模組提供可重複使用的認證相關場景，包括：
 * - 註冊（帳號密碼、第三方平台）
 * - 登入（帳號密碼、第三方平台）
 * - Token 刷新
 * - 密碼重設流程
 * 
 * 使用方式：
 * import { registerWithCredentials, loginWithCredentials } from './scenarios/apis/auth.js';
 */

import http from 'k6/http';
import { check, sleep } from 'k6';
import { Rate, Trend } from 'k6/metrics';

// 可選的自定義指標
const registerSuccessRate = new Rate('auth_register_success');
const loginSuccessRate = new Rate('auth_login_success');
const registerDuration = new Trend('auth_register_duration');
const loginDuration = new Trend('auth_login_duration');

/**
 * 使用帳號密碼註冊
 * @param {Object} options - 配置選項
 * @param {string} options.baseUrl - API 基礎 URL
 * @param {string} options.loginId - 登入 ID（email 或 phone）
 * @param {string} options.password - 密碼
 * @param {string} options.accountType - 帳號類型（email/phone/any）
 * @param {Object} options.customMetrics - 自定義指標對象（可選）
 * @returns {Object} 註冊結果，包含 tokens 和響應
 */
export function registerWithCredentials(options = {}) {
  const {
    baseUrl = __ENV.BASE_URL || 'http://localhost:8888',
    loginId = `test_${Date.now()}@example.com`,
    password = 'Test123456!',
    accountType = 'email',
    customMetrics = null,
  } = options;

  const url = `${baseUrl}/api/v1/auth/register`;
  const payload = JSON.stringify({
    auth_method: 'credentials',
    login_id: loginId,
    credentials: {
      password: password,
      password_confirm: password,
      account_type: accountType,
    },
  });

  const params = {
    headers: {
      'Content-Type': 'application/json',
    },
    tags: {
      name: 'auth_register_credentials',
      api: 'auth',
      method: 'register',
      auth_type: 'credentials',
    },
  };

  const startTime = Date.now();
  const res = http.post(url, payload, params);
  const duration = Date.now() - startTime;

  // 解析響應
  let result = null;
  let responseData = null;
  
  if (res.status === 200) {
    try {
      result = JSON.parse(res.body);
      
      // 支持兩種響應格式：
      // 1. 直接返回 LoginResp: { access_token, refresh_token, uid, ... }
      // 2. 包裝在 Resp 中: { code, message, data: { access_token, ... } }
      if (result.data && typeof result.data === 'object') {
        // 格式 2: 包裝在 Resp 中
        responseData = result.data;
      } else if (result.access_token) {
        // 格式 1: 直接返回 LoginResp
        responseData = result;
      } else {
        // 無法識別的格式，記錄響應以便調試
        console.warn('Unexpected response format. Full response:', JSON.stringify(result));
        console.warn('Response keys:', Object.keys(result));
        responseData = result;
      }
    } catch (e) {
      console.error('Failed to parse register response:', e);
      console.error('Response body:', res.body);
    }
  }

  // 檢查響應結果
  const success = check(res, {
    'register status is 200': (r) => r.status === 200,
    'register has access_token': () => {
      return responseData && responseData.access_token && responseData.access_token.length > 0;
    },
    'register has refresh_token': () => {
      return responseData && responseData.refresh_token && responseData.refresh_token.length > 0;
    },
    'register has uid': () => {
      return responseData && responseData.uid && responseData.uid.length > 0;
    },
  }, { name: 'register_checks' });

  // 使用自定義指標（如果提供）
  if (customMetrics) {
    customMetrics.registerSuccessRate.add(success);
    customMetrics.registerDuration.add(duration);
  } else {
    // 使用預設指標
    registerSuccessRate.add(success);
    registerDuration.add(duration);
  }

  return {
    success,
    status: res.status,
    response: result,
    responseData: responseData,
    tokens: responseData && responseData.access_token ? {
      accessToken: responseData.access_token,
      refreshToken: responseData.refresh_token,
      uid: responseData.uid,
    } : null,
  };
}

/**
 * 使用第三方平台註冊
 * @param {Object} options - 配置選項
 * @param {string} options.baseUrl - API 基礎 URL
 * @param {string} options.loginId - 登入 ID
 * @param {string} options.provider - 平台名稱（google/line/apple）
 * @param {string} options.token - 平台提供的 Token
 * @param {Object} options.customMetrics - 自定義指標對象（可選）
 * @returns {Object} 註冊結果
 */
export function registerWithPlatform(options = {}) {
  const {
    baseUrl = __ENV.BASE_URL || 'https://localhost:8888',
    loginId = `platform_${Date.now()}@example.com`,
    provider = 'google',
    token = 'mock_platform_token',
    customMetrics = null,
  } = options;

  const url = `${baseUrl}/api/v1/auth/register`;
  const payload = JSON.stringify({
    auth_method: 'platform',
    login_id: loginId,
    platform: {
      provider: provider,
      token: token,
    },
  });

  const params = {
    headers: {
      'Content-Type': 'application/json',
    },
    tags: {
      name: 'auth_register_platform',
      api: 'auth',
      method: 'register',
      auth_type: 'platform',
      provider: provider,
    },
  };

  const startTime = Date.now();
  const res = http.post(url, payload, params);
  const duration = Date.now() - startTime;

  const success = check(res, {
    'register platform status is 200': (r) => r.status === 200,
    'register platform has tokens': (r) => {
      try {
        const body = JSON.parse(r.body);
        return body.access_token && body.refresh_token;
      } catch {
        return false;
      }
    },
  }, { name: 'register_platform_checks' });

  if (customMetrics) {
    customMetrics.registerSuccessRate?.add(success);
    customMetrics.registerDuration?.add(duration);
  } else {
    registerSuccessRate.add(success);
    registerDuration.add(duration);
  }

  let result = null;
  if (res.status === 200) {
    try {
      result = JSON.parse(res.body);
    } catch (e) {
      console.error('Failed to parse register platform response:', e);
    }
  }

  return {
    success,
    status: res.status,
    response: result,
    tokens: result ? {
      accessToken: result.access_token,
      refreshToken: result.refresh_token,
      uid: result.uid,
    } : null,
  };
}

/**
 * 使用帳號密碼登入
 * @param {Object} options - 配置選項
 * @param {string} options.baseUrl - API 基礎 URL
 * @param {string} options.loginId - 登入 ID
 * @param {string} options.password - 密碼
 * @param {Object} options.customMetrics - 自定義指標對象（可選）
 * @returns {Object} 登入結果
 */
export function loginWithCredentials(options = {}) {
  const {
    baseUrl = __ENV.BASE_URL || 'http://localhost:8888',
    loginId,
    password,
    customMetrics = null,
  } = options;

  if (!loginId || !password) {
    throw new Error('loginId and password are required for credentials login');
  }

  const url = `${baseUrl}/api/v1/auth/sessions`;
  const payload = JSON.stringify({
    auth_method: 'credentials',
    login_id: loginId,
    credentials: {
      password: password,
      password_confirm: password,
      account_type: 'email',
    },
  });

  const params = {
    headers: {
      'Content-Type': 'application/json',
    },
    tags: {
      name: 'auth_login_credentials',
      api: 'auth',
      method: 'login',
      auth_type: 'credentials',
    },
  };

  const startTime = Date.now();
  const res = http.post(url, payload, params);
  const duration = Date.now() - startTime;

  // 解析響應
  let result = null;
  let responseData = null;
  
  if (res.status === 200) {
    try {
      result = JSON.parse(res.body);
      
      // 支持兩種響應格式：
      // 1. 直接返回 LoginResp: { access_token, refresh_token, uid, ... }
      // 2. 包裝在 Resp 中: { code, message, data: { access_token, ... } }
      if (result.data && typeof result.data === 'object') {
        // 格式 2: 包裝在 Resp 中
        responseData = result.data;
      } else if (result.access_token) {
        // 格式 1: 直接返回 LoginResp
        responseData = result;
      } else {
        // 無法識別的格式，記錄響應以便調試
        console.warn('Unexpected login response format. Full response:', JSON.stringify(result));
        console.warn('Response keys:', Object.keys(result));
        responseData = result;
      }
    } catch (e) {
      console.error('Failed to parse login response:', e);
      console.error('Response body:', res.body);
    }
  }

  // 檢查響應結果
  const success = check(res, {
    'login status is 200': (r) => r.status === 200,
    'login has access_token': () => {
      return responseData && responseData.access_token && responseData.access_token.length > 0;
    },
    'login has refresh_token': () => {
      return responseData && responseData.refresh_token && responseData.refresh_token.length > 0;
    },
  }, { name: 'login_checks' });

  if (customMetrics) {
    customMetrics.loginSuccessRate?.add(success);
    customMetrics.loginDuration?.add(duration);
  } else {
    loginSuccessRate.add(success);
    loginDuration.add(duration);
  }

  return {
    success,
    status: res.status,
    response: result,
    responseData: responseData,
    tokens: responseData && responseData.access_token ? {
      accessToken: responseData.access_token,
      refreshToken: responseData.refresh_token,
      uid: responseData.uid,
    } : null,
  };
}

/**
 * 使用第三方平台登入
 * @param {Object} options - 配置選項
 * @param {string} options.baseUrl - API 基礎 URL
 * @param {string} options.loginId - 登入 ID
 * @param {string} options.provider - 平台名稱
 * @param {string} options.token - 平台 Token
 * @param {Object} options.customMetrics - 自定義指標對象（可選）
 * @returns {Object} 登入結果
 */
export function loginWithPlatform(options = {}) {
  const {
    baseUrl = __ENV.BASE_URL || 'https://localhost:8888',
    loginId,
    provider = 'google',
    token = 'mock_platform_token',
    customMetrics = null,
  } = options;

  if (!loginId) {
    throw new Error('loginId is required for platform login');
  }

  const url = `${baseUrl}/api/v1/auth/sessions`;
  const payload = JSON.stringify({
    auth_method: 'platform',
    login_id: loginId,
    platform: {
      provider: provider,
      token: token,
    },
  });

  const params = {
    headers: {
      'Content-Type': 'application/json',
    },
    tags: {
      name: 'auth_login_platform',
      api: 'auth',
      method: 'login',
      auth_type: 'platform',
      provider: provider,
    },
  };

  const startTime = Date.now();
  const res = http.post(url, payload, params);
  const duration = Date.now() - startTime;

  const success = check(res, {
    'login platform status is 200': (r) => r.status === 200,
    'login platform has tokens': (r) => {
      try {
        const body = JSON.parse(r.body);
        return body.access_token && body.refresh_token;
      } catch {
        return false;
      }
    },
  }, { name: 'login_platform_checks' });

  if (customMetrics) {
    customMetrics.loginSuccessRate?.add(success);
    customMetrics.loginDuration?.add(duration);
  } else {
    loginSuccessRate.add(success);
    loginDuration.add(duration);
  }

  let result = null;
  if (res.status === 200) {
    try {
      result = JSON.parse(res.body);
    } catch (e) {
      console.error('Failed to parse login platform response:', e);
    }
  }

  return {
    success,
    status: res.status,
    response: result,
    tokens: result ? {
      accessToken: result.access_token,
      refreshToken: result.refresh_token,
      uid: result.uid,
    } : null,
  };
}

/**
 * 刷新 Access Token
 * @param {Object} options - 配置選項
 * @param {string} options.baseUrl - API 基礎 URL
 * @param {string} options.accessToken - 當前的 Access Token
 * @param {string} options.refreshToken - Refresh Token
 * @param {Object} options.customMetrics - 自定義指標對象（可選）
 * @returns {Object} 刷新結果
 */
export function refreshToken(options = {}) {
  const {
    baseUrl = __ENV.BASE_URL || 'https://localhost:8888',
    accessToken,
    refreshToken,
    customMetrics = null,
  } = options;

  if (!accessToken || !refreshToken) {
    throw new Error('accessToken and refreshToken are required');
  }

  const url = `${baseUrl}/api/v1/auth/sessions/refresh`;
  const payload = JSON.stringify({
    access_token: accessToken,
    refresh_token: refreshToken,
  });

  const params = {
    headers: {
      'Content-Type': 'application/json',
    },
    tags: {
      name: 'auth_refresh_token',
      api: 'auth',
      method: 'refresh_token',
    },
  };

  const res = http.post(url, payload, params);

  const success = check(res, {
    'refresh token status is 200': (r) => r.status === 200,
    'refresh token has new access_token': (r) => {
      try {
        const body = JSON.parse(r.body);
        console.log('refresh token response:', body.data);
        return body.data.access_token && body.data.access_token.length > 0;
      } catch {
        return false;
      }
    },
  }, { name: 'refresh_token_checks' });

  let result = null;
  if (res.status === 200) {
    try {
      result = JSON.parse(res.body.data);
    } catch (e) {
      console.error('Failed to parse refresh token response:', e);
    }
  }

  return {
    success,
    status: res.status,
    response: result,
    tokens: result ? {
      accessToken: result.access_token,
      refreshToken: result.refresh_token,
    } : null,
  };
}

/**
 * 請求密碼重設驗證碼
 * @param {Object} options - 配置選項
 * @param {string} options.baseUrl - API 基礎 URL
 * @param {string} options.identifier - 使用者帳號（email 或 phone）
 * @param {string} options.accountType - 帳號類型（email/phone）
 * @returns {Object} 請求結果
 */
export function requestPasswordReset(options = {}) {
  const {
    baseUrl = __ENV.BASE_URL || 'http://localhost:8888',
    identifier,
    accountType = 'email',
  } = options;

  if (!identifier) {
    throw new Error('identifier is required');
  }

  const url = `${baseUrl}/api/v1/auth/password-resets/request`;
  const payload = JSON.stringify({
    identifier: identifier,
    account_type: accountType,
  });

  const params = {
    headers: {
      'Content-Type': 'application/json',
    },
    tags: {
      name: 'auth_request_password_reset',
      api: 'auth',
      method: 'request_password_reset',
    },
  };

  const res = http.post(url, payload, params);

  const success = check(res, {
    'request password reset status is 200': (r) => r.status === 200,
  }, { name: 'request_password_reset_checks' });

  return {
    success,
    status: res.status,
  };
}

/**
 * 驗證密碼重設驗證碼
 * @param {Object} options - 配置選項
 * @param {string} options.baseUrl - API 基礎 URL
 * @param {string} options.identifier - 使用者帳號
 * @param {string} options.verifyCode - 驗證碼
 * @returns {Object} 驗證結果
 */
export function verifyPasswordResetCode(options = {}) {
  const {
    baseUrl = __ENV.BASE_URL || 'http://localhost:8888',
    identifier,
    verifyCode,
  } = options;

  if (!identifier || !verifyCode) {
    throw new Error('identifier and verifyCode are required');
  }

  const url = `${baseUrl}/api/v1/auth/password-resets/verify`;
  const payload = JSON.stringify({
    identifier: identifier,
    verify_code: verifyCode,
  });

  const params = {
    headers: {
      'Content-Type': 'application/json',
    },
    tags: {
      name: 'auth_verify_password_reset_code',
      api: 'auth',
      method: 'verify_password_reset_code',
    },
  };

  const res = http.post(url, payload, params);

  const success = check(res, {
    'verify password reset code status is 200': (r) => r.status === 200,
  }, { name: 'verify_password_reset_code_checks' });

  return {
    success,
    status: res.status,
  };
}

/**
 * 執行密碼重設
 * @param {Object} options - 配置選項
 * @param {string} options.baseUrl - API 基礎 URL
 * @param {string} options.identifier - 使用者帳號
 * @param {string} options.verifyCode - 驗證碼
 * @param {string} options.newPassword - 新密碼
 * @returns {Object} 重設結果
 */
export function resetPassword(options = {}) {
  const {
    baseUrl = __ENV.BASE_URL || 'https://localhost:8888',
    identifier,
    verifyCode,
    newPassword,
  } = options;

  if (!identifier || !verifyCode || !newPassword) {
    throw new Error('identifier, verifyCode, and newPassword are required');
  }

  const url = `${baseUrl}/api/v1/auth/password-resets`;
  const payload = JSON.stringify({
    identifier: identifier,
    verify_code: verifyCode,
    password: newPassword,
    password_confirm: newPassword,
  });

  const params = {
    headers: {
      'Content-Type': 'application/json',
    },
    tags: {
      name: 'auth_reset_password',
      api: 'auth',
      method: 'reset_password',
    },
  };

  const res = http.put(url, payload, params);

  const success = check(res, {
    'reset password status is 200': (r) => r.status === 200,
  }, { name: 'reset_password_checks' });

  return {
    success,
    status: res.status,
  };
}

