// smoke: member endpoints (Bearer)
//
// Covers (14 endpoints + change password negatives):
//   GET    /api/v1/members/me
//   PATCH  /api/v1/members/me
//   POST   /api/v1/members/me/verifications/email/start
//   POST   /api/v1/members/me/verifications/email/confirm  (negative: invalid code)
//   POST   /api/v1/members/me/verifications/phone/start
//   POST   /api/v1/members/me/verifications/phone/confirm  (negative: invalid code)
//   GET    /api/v1/members/me/totp                          (status before enroll)
//   POST   /api/v1/members/me/totp/enroll-start
//   POST   /api/v1/members/me/totp/enroll-confirm           (negative: invalid code)
//   POST   /api/v1/members/me/totp/verify                   (negative: not enrolled)
//   POST   /api/v1/members/me/totp/backup-codes             (negative: not enrolled)
//   POST   /api/v1/members/me/password                  (negative: wrong current / no bearer / weak)
//
// Happy paths for TOTP and verification end-to-end live in journeys/.
import { get, post, patch, del, checkEnvelope, checkError } from '../lib/http.js';
import { registerAndConfirm } from '../lib/auth.js';
import { unique } from '../lib/config.js';

export const options = {
  vus: 1,
  iterations: 1,
  thresholds: { checks: ['rate==1.0'] },
};

export default function () {
  const { identity, tokens } = registerAndConfirm();
  const bearer = { Authorization: `Bearer ${tokens.access_token}` };

  // 1. GET /me
  const me = checkEnvelope(get('/api/v1/members/me', bearer), 'GET /members/me').data;
  if (me.uid !== tokens.uid) throw new Error('me.uid mismatch');

  // 2. PATCH /me
  const newName = `smoke-${unique('m')}`;
  const patched = checkEnvelope(patch('/api/v1/members/me', { display_name: newName }, bearer), 'PATCH /members/me').data;
  if (patched.display_name !== newName) throw new Error('display_name not updated');

  // 3. POST /me/verifications/email/start
  const eStart = checkEnvelope(
    post('/api/v1/members/me/verifications/email/start', { target: `verify-${unique('e')}@k6.local` }, bearer),
    'POST /me/verifications/email/start',
  ).data;
  if (!eStart.challenge_id) throw new Error('email start: missing challenge_id');

  // 4. POST /me/verifications/email/confirm (negative — wrong code 000000)
  checkError(
    post('/api/v1/members/me/verifications/email/confirm', { challenge_id: eStart.challenge_id, code: '000000' }, bearer),
    'POST /me/verifications/email/confirm (bad code)',
    403,
    29505000,
  );

  // 5. POST /me/verifications/phone/start
  const pStart = checkEnvelope(
    post('/api/v1/members/me/verifications/phone/start', { target: '+886912000001' }, bearer),
    'POST /me/verifications/phone/start',
  ).data;
  if (!pStart.challenge_id) throw new Error('phone start: missing challenge_id');

  // 6. POST /me/verifications/phone/confirm (negative)
  checkError(
    post('/api/v1/members/me/verifications/phone/confirm', { challenge_id: pStart.challenge_id, code: '000000' }, bearer),
    'POST /me/verifications/phone/confirm (bad code)',
    403,
    29505000,
  );

  // 7. GET /me/totp (status — not enrolled)
  const totpStatus = checkEnvelope(get('/api/v1/members/me/totp', bearer), 'GET /me/totp').data;
  if (totpStatus.enrolled !== false) throw new Error('totp should not be enrolled');

  // 8. POST /me/totp/enroll-start (happy)
  const enroll = checkEnvelope(post('/api/v1/members/me/totp/enroll-start', null, bearer), 'POST /me/totp/enroll-start').data;
  if (!enroll.otpauth_url) throw new Error('enroll-start: missing otpauth_url');

  // 9. POST /me/totp/enroll-confirm (negative — bad code)
  checkError(
    post('/api/v1/members/me/totp/enroll-confirm', { code: '000000' }, bearer),
    'POST /me/totp/enroll-confirm (bad code)',
    403,
    29505000,
  );

  // 10. POST /me/totp/verify (negative — not enrolled)
  checkError(
    post('/api/v1/members/me/totp/verify', { code: '000000' }, bearer),
    'POST /me/totp/verify (not enrolled)',
    409,
    29309000,
  );

  // 11. POST /me/totp/backup-codes (negative — not enrolled)
  checkError(
    post('/api/v1/members/me/totp/backup-codes', null, bearer),
    'POST /me/totp/backup-codes (not enrolled)',
    409,
    29309000,
  );

  // 12. DELETE /me/totp — when not enrolled the contract returns 200 (idempotent disable).
  // Accept either 200 success envelope or 404 (member-not-found edge case).
  const delRes = del('/api/v1/members/me/totp', null, bearer);
  if (delRes.status !== 200 && delRes.status !== 404) {
    throw new Error(`DELETE /me/totp unexpected status ${delRes.status}: ${delRes.body}`);
  }

  // 13. POST /me/password (negative — totp not enrolled)
  checkError(
    post(
      '/api/v1/members/me/password',
      { current_password: identity.password, new_password: 'K6-NewPass-2!' },
      bearer,
    ),
    'POST /me/password (totp not enrolled)',
    403,
    29505000,
  );

  // 14. POST /me/password (negative — no bearer)
  checkError(
    post('/api/v1/members/me/password', {
      current_password: identity.password,
      new_password: 'K6-NewPass-2!',
    }),
    'POST /me/password (no bearer)',
    401,
    29501000,
  );

}
