const { getSetting } = require("./settings");
const { createLogger } = require("./logger");

const platformLog = createLogger("core:command-platform", { category: "integration" });
const entitlementCache = new Map();

async function createPlatformClip(ctx) {
  if (ctx.platform !== "twitch") {
    return { ok: false, unsupported: true, message: `${platformLabel(ctx.platform)} does not provide clip creation through Lumi.` };
  }
  const broadcasterId = twitchBroadcasterId(ctx);
  if (!broadcasterId) return { ok: false, message: "Twitch did not provide the current channel ID." };
  const payload = await twitchRequest("POST", "/helix/clips", { broadcaster_id: broadcasterId });
  const clip = payload?.data?.[0];
  if (!clip?.id) return { ok: false, message: "Twitch accepted the request but did not return a clip." };
  platformLog.info("Twitch clip requested", { broadcaster_id: broadcasterId, clip_id: clip.id }, { event: "clip_created" });
  return {
    ok: true,
    id: clip.id,
    url: `https://clips.twitch.tv/${encodeURIComponent(clip.id)}`,
    editUrl: clip.edit_url || null
  };
}

async function startPlatformRaid(ctx, targetChannel) {
  if (ctx.platform !== "twitch") {
    return { ok: false, unsupported: true, message: `${platformLabel(ctx.platform)} does not provide raids through Lumi.` };
  }
  const fromBroadcasterId = twitchBroadcasterId(ctx);
  if (!fromBroadcasterId) return { ok: false, message: "Twitch did not provide the current channel ID." };
  const login = String(targetChannel || "").trim().replace(/^[@#]/, "").toLowerCase();
  if (!login) return { ok: false, message: "Choose a channel to raid." };
  const users = await twitchRequest("GET", "/helix/users", { login });
  const target = users?.data?.[0];
  if (!target?.id) return { ok: false, message: `Twitch channel “${login}” was not found.` };
  if (target.id === fromBroadcasterId) return { ok: false, message: "A channel cannot raid itself." };
  const payload = await twitchRequest("POST", "/helix/raids", {
    from_broadcaster_id: fromBroadcasterId,
    to_broadcaster_id: target.id
  });
  platformLog.info("Twitch raid started", { from_broadcaster_id: fromBroadcasterId, to_broadcaster_id: target.id }, { event: "raid_started" });
  return { ok: true, target: target.display_name || target.login || login, viewers: payload?.data?.[0]?.viewer_count ?? null };
}

async function cancelPlatformRaid(ctx) {
  if (ctx.platform !== "twitch") {
    return { ok: false, unsupported: true, message: `${platformLabel(ctx.platform)} does not provide raids through Lumi.` };
  }
  const broadcasterId = twitchBroadcasterId(ctx);
  if (!broadcasterId) return { ok: false, message: "Twitch did not provide the current channel ID." };
  await twitchRequest("DELETE", "/helix/raids", { broadcaster_id: broadcasterId });
  platformLog.info("Twitch raid cancelled", { broadcaster_id: broadcasterId }, { event: "raid_cancelled" });
  return { ok: true };
}

async function getProviderStreamIdentity(ctx) {
  if (ctx.platform === "youtube") {
    const id = String(ctx.meta?.activeVideoId || ctx.meta?.liveChatId || "");
    const channelId = String(ctx.meta?.broadcasterChannelId || ctx.meta?.liveChatId || "");
    return id && channelId ? { streamKey: `youtube:${channelId}`, providerStreamId: id } : null;
  }
  if (ctx.platform !== "twitch") return null;
  const broadcasterId = twitchBroadcasterId(ctx);
  if (!broadcasterId) return null;
  try {
    const payload = await twitchRequest("GET", "/helix/streams", { user_id: broadcasterId });
    const stream = payload?.data?.[0];
    return {
      streamKey: `twitch:${broadcasterId}`,
      providerStreamId: stream?.id || null,
      live: Boolean(stream?.id)
    };
  } catch (error) {
    platformLog.warn("Could not resolve Twitch stream identity", { error, broadcaster_id: broadcasterId }, { event: "stream_identity_failed" });
    return { streamKey: `twitch:${broadcasterId}`, providerStreamId: null, live: null };
  }
}

async function getTwitchEntitlement(ctx, role, minimumTier = 1) {
  if (ctx.platform !== "twitch") return false;
  const broadcasterId = twitchBroadcasterId(ctx);
  const userId = String(ctx.platformUser?.id || ctx.user?.platformId || "");
  if (!broadcasterId || !userId) return false;
  const key = `${role}:${broadcasterId}:${userId}:${minimumTier}`;
  const cached = entitlementCache.get(key);
  if (cached && cached.expiresAt > Date.now()) return cached.value;
  let value = false;
  if (role === "follower") {
    const result = await twitchRequest("GET", "/helix/channels/followers", { broadcaster_id: broadcasterId, user_id: userId });
    value = Boolean(result?.data?.length);
  } else if (role === "subscriber") {
    const result = await twitchRequest("GET", "/helix/subscriptions", { broadcaster_id: broadcasterId, user_id: userId });
    const tier = Number(result?.data?.[0]?.tier || 0) / 1000;
    value = tier >= Math.max(1, Number(minimumTier) || 1);
  } else if (role === "editor") {
    const result = await twitchRequest("GET", "/helix/channels/editors", { broadcaster_id: broadcasterId, first: 100 });
    value = Boolean(result?.data?.some((entry) => String(entry.user_id) === userId));
  }
  entitlementCache.set(key, { value, expiresAt: Date.now() + 60_000 });
  return value;
}

async function twitchRequest(method, pathname, query = {}) {
  const clientId = String(getSetting("twitch_client_id", "") || "").trim();
  const token = normalizeOauthToken(getSetting("twitch_bot_oauth", ""));
  if (!clientId || !token) throw new Error("Twitch API credentials are not configured.");
  const url = new URL(`https://api.twitch.tv${pathname}`);
  Object.entries(query).forEach(([key, value]) => {
    if (value !== undefined && value !== null && value !== "") url.searchParams.set(key, String(value));
  });
  const response = await fetch(url, {
    method,
    headers: { "Client-Id": clientId, Authorization: `Bearer ${token}` }
  });
  const body = response.status === 204 ? null : await response.json().catch(() => null);
  if (!response.ok) {
    const detail = String(body?.message || body?.error || response.statusText || "Twitch request failed").slice(0, 300);
    const error = new Error(detail);
    error.status = response.status;
    throw error;
  }
  return body;
}

function twitchBroadcasterId(ctx) {
  return String(ctx.meta?.tags?.["room-id"] || "").trim() || null;
}

function normalizeOauthToken(value) {
  return String(value || "").trim().replace(/^oauth:/i, "");
}

function platformLabel(platform) {
  return ({ discord: "Discord", twitch: "Twitch", youtube: "YouTube" })[platform] || "This platform";
}

module.exports = {
  cancelPlatformRaid,
  createPlatformClip,
  getProviderStreamIdentity,
  getTwitchEntitlement,
  startPlatformRaid,
  twitchRequest
};
