/**
 * Wiki.js Tier Sync — syncs subscriber tier groups in Wiki.js via GraphQL API.
 * REQ-2026-04-15-subscriber-wiki-auth (Chronicler #92, Task #138)
 *
 * Wiki.js is deployed at subscribers.firefrostgaming.com. Auth via API key.
 * User email convention: {discordId}@firefrost.local (unique, internal).
 *
 * Pre-requisites (Michael does once in Wiki.js admin panel):
 *   1. Create 6 groups: Awakened, Elemental, Knight, Master, Legend, Sovereign
 *   2. Generate API key: Admin → API Access → add key → copy to .env
 *
 * Silent-fail pattern: never let wiki sync break the Stripe webhook.
 */

const axios = require('axios');

const WIKIJS_URL = process.env.WIKIJS_URL || 'https://subscribers.firefrostgaming.com';
const WIKIJS_API_KEY = process.env.WIKIJS_API_KEY || '';

// tier_level (from Stripe webhook) → Wiki.js group name
const TIER_GROUP_MAP = {
  1: 'Awakened',
  2: 'Elemental',
  3: 'Knight',
  4: 'Master',
  5: 'Legend',
  6: 'Sovereign'
};

/**
 * Execute a GraphQL query/mutation against Wiki.js.
 */
async function gql(query, variables) {
  if (!WIKIJS_API_KEY) {
    console.warn('[WikiSync] WIKIJS_API_KEY not set — skipping');
    return null;
  }
  const resp = await axios.post(
    `${WIKIJS_URL}/graphql`,
    { query, variables },
    {
      headers: {
        'Authorization': `Bearer ${WIKIJS_API_KEY}`,
        'Content-Type': 'application/json'
      },
      timeout: 10000
    }
  );
  return resp.data;
}

/**
 * Fetch all Wiki.js groups and return a map of name → id.
 */
async function getGroupMap() {
  const result = await gql(`
    query {
      groups {
        list { id name }
      }
    }
  `);
  const groups = result?.data?.groups?.list || [];
  const map = {};
  for (const g of groups) {
    map[g.name] = g.id;
  }
  return map;
}

/**
 * Search for a Wiki.js user by their internal email ({discordId}@firefrost.local).
 * Returns { id, email } or null.
 */
async function findUser(discordId) {
  const email = `${discordId}@firefrost.local`;
  const result = await gql(`
    query ($query: String!) {
      users {
        search(query: $query) { id email }
      }
    }
  `, { query: email });
  const users = result?.data?.users?.search || [];
  return users.find(u => u.email === email) || null;
}

/**
 * Create a Wiki.js user for the given Discord subscriber.
 */
async function createUser(discordId, username, groupIds) {
  const email = `${discordId}@firefrost.local`;
  const result = await gql(`
    mutation ($email: String!, $name: String!, $groups: [Int!]!) {
      users {
        create(email: $email, name: $name, passwordRaw: "", providerKey: "discord", groups: $groups) {
          responseResult { succeeded message }
        }
      }
    }
  `, { email, name: username || discordId, groups: groupIds });
  const res = result?.data?.users?.create?.responseResult;
  if (res && !res.succeeded) {
    throw new Error(`Wiki.js create failed: ${res.message}`);
  }
  return res;
}

/**
 * Update a Wiki.js user's group assignment.
 */
async function updateUserGroups(userId, groupIds) {
  const result = await gql(`
    mutation ($id: Int!, $groups: [Int!]!) {
      users {
        update(id: $id, groups: $groups) {
          responseResult { succeeded message }
        }
      }
    }
  `, { id: userId, groups: groupIds });
  const res = result?.data?.users?.update?.responseResult;
  if (res && !res.succeeded) {
    throw new Error(`Wiki.js update failed: ${res.message}`);
  }
  return res;
}

/**
 * Sync a subscriber's Wiki.js group to match their Stripe tier.
 * Creates user if not exists, updates group if they do.
 *
 * @param {string} discordId
 * @param {string} username  — Discord display name
 * @param {number} tierLevel — 1-6 from Stripe webhook
 */
async function syncWikiUser(discordId, username, tierLevel) {
  if (!WIKIJS_API_KEY) {
    console.warn('[WikiSync] WIKIJS_API_KEY not set — skipping');
    return { success: false, reason: 'no API key' };
  }

  const groupName = TIER_GROUP_MAP[tierLevel];
  if (!groupName) {
    console.warn(`[WikiSync] Unknown tier level ${tierLevel} — skipping`);
    return { success: false, reason: `unknown tier ${tierLevel}` };
  }

  const groupMap = await getGroupMap();
  const groupId = groupMap[groupName];
  if (!groupId) {
    console.error(`[WikiSync] Group '${groupName}' not found in Wiki.js — did Michael create it?`);
    return { success: false, reason: `group '${groupName}' missing` };
  }

  const existing = await findUser(discordId);
  if (existing) {
    await updateUserGroups(existing.id, [groupId]);
    console.log(`📚 [WikiSync] Updated ${username} (${discordId}) → ${groupName}`);
  } else {
    await createUser(discordId, username, [groupId]);
    console.log(`📚 [WikiSync] Created ${username} (${discordId}) → ${groupName}`);
  }

  return { success: true, group: groupName };
}

/**
 * Demote a subscriber to Awakened group (on cancellation/grace period).
 */
async function demoteToAwakened(discordId) {
  return syncWikiUser(discordId, null, 1);
}

module.exports = { syncWikiUser, demoteToAwakened };
