/**
 * /api/assetImageRedirect takes an asset type, Neopets ID, and image size,
 * and redirects to a corresponding image URL.
 *
 * Parameters:
 *   - type: "biology" or "object"
 *   - remoteId: The Neopets ID of the asset
 *   - idealSize: "600x600", "300x300", or "150x150"
 *
 * This is designed to be a new backend for impress-asset-images.openneo.net,
 * which has URLs like: http://impress-asset-images.openneo.net/biology/000/000/000/596/600x600.png?1326426317
 * (That said, we still need some of the AWS images, which will still be
 * accessible at aws.impress-asset-images.openneo.net.)
 *
 * Note that this endpoint doesn't always respect the `idealSize` parameter very
 * closely; when our best canonical image is on images.neopets.com, it's
 * usually 600x600, and I don't think it's worth the negligible network savings
 * on Classic DTI to do resizing work here (and add another cache layer vs just
 * serving from the original CDN that's much more likely to be a cache hit!).
 */
const beeline = require("honeycomb-beeline")({
  writeKey: process.env["HONEYCOMB_WRITE_KEY"],
  dataset:
    process.env["NODE_ENV"] === "production"
      ? "Dress to Impress (2020)"
      : "Dress to Impress (2020, dev)",
  serviceName: "impress-2020-gql-server",
});
import { gql, loadGraphqlQuery } from "../../src/server/ssr-graphql";

async function handle(req, res) {
  if (!["biology", "object"].includes(req.query.type)) {
    res.setHeader("Content-Type", "text/plain");
    res.status(400).end(`type must be "biology" or "object"`);
    return;
  }
  if (!["600x600", "300x300", "150x150"].includes(req.query.idealSize)) {
    res.setHeader("Content-Type", "text/plain");
    res.status(400).end(`idealSize must be 600x600, 300x300, or 150x150`);
    return;
  }

  const { data, errors } = await loadGraphqlQuery({
    query: gql`
      query ApiAssetImageRedirect_GetImageUrl(
        $type: LayerType!
        $remoteId: ID!
        $idealSize: LayerImageSize!
      ) {
        appearanceLayerByRemoteId(type: $type, remoteId: $remoteId) {
          imageUrlV2(idealSize: $idealSize)
        }
      }
    `,
    variables: {
      type: req.query.type === "biology" ? "PET_LAYER" : "ITEM_LAYER",
      remoteId: req.query.remoteId,
      idealSize: "SIZE_" + parseInt(req.query.idealSize),
    },
  });
  if (errors) {
    console.error("Error loading image URL from GraphQL:");
    for (const error of errors) {
      console.error(error);
    }
    res.setHeader("Content-Type", "text/plain");
    res.status(500).end(`Error loading image URL from GraphQL`);
    return;
  }

  const layer = data.appearanceLayerByRemoteId;
  if (layer == null) {
    res.setHeader("Content-Type", "text/plain");
    res.status(404).end(`appearance layer not found`);
    return;
  }
  const imageUrl = layer.imageUrlV2;
  if (imageUrl == null) {
    res.setHeader("Content-Type", "text/plain");
    res.status(404).end(`appearance layer has no image available`);
    return;
  }

  // Cache for 5 minutes, and immediately serve stale data for an hour.
  // I don't expect asset image URLs to change often, but when they do, it'll
  // probably be important! And this is a pretty fast operation tbh.
  res.setHeader(
    "Cache-Control",
    "public, max-age=300, stale-while-revalidate=3600"
  );
  res.setHeader("Content-Type", "image/png");
  return res.redirect(imageUrl);
}

async function handleWithBeeline(req, res) {
  beeline.withTrace(
    {
      name: "api/assetImageRedirect",
      operation_name: "api/assetImageRedirect",
    },
    () => handle(req, res)
  );
}

export default handleWithBeeline;