import { ConsoleUserRepository } from "@/internal/console-users/console-users.repository";
import type { RepositoryContext } from "@/internal/datastore/repository";
import { logError } from "@/lib/logger";
import { error as errorResponse, success } from "@/lib/response";
import { init as gcsInit } from "@/lib/storage/gcs";
import type { Context } from "hono";

/** Avatars are small; anything larger is a mistake rather than a portrait. */
const MAX_AVATAR_BYTES = 2 * 1024 * 1024;
const ALLOWED_MIME = ["image/jpeg", "image/png", "image/webp"];

const repo = (c: Context) => ConsoleUserRepository(c as RepositoryContext);

/** The signed-in user's own profile fields. */
export const updateMyProfileHandler = async (c: Context) => {
  try {
    const consoleUserId = String(c.get("consoleUserId") ?? "");
    if (!consoleUserId) {
      return errorResponse(c, "Not signed in", 401);
    }
    const body = (await c.req.json()) as Record<string, unknown>;

    // Deliberately narrow: roles, activation and super-admin status are the
    // admin path's business, not a user's own.
    const updated = await repo(c).UpdateProfile(consoleUserId, {
      first_name:
        typeof body.first_name === "string" ? body.first_name : undefined,
      last_name:
        typeof body.last_name === "string" ? body.last_name : undefined,
      phone: typeof body.phone === "string" ? body.phone : undefined,
      job_title:
        typeof body.job_title === "string" ? body.job_title : undefined,
    });
    c.set("entityId", consoleUserId);
    return success(c, updated, "Profile updated");
  } catch (err) {
    logError(err);
    return errorResponse(c, "Failed to update profile", 500, err);
  }
};

/**
 * Avatar upload.
 *
 * Stored in GCS under `console-avatars/`; only the resulting URL is written to
 * the user row. The object name carries a timestamp so a replaced avatar isn't
 * served from cache under the old URL.
 */
export const uploadMyAvatarHandler = async (c: Context) => {
  try {
    const consoleUserId = String(c.get("consoleUserId") ?? "");
    if (!consoleUserId) {
      return errorResponse(c, "Not signed in", 401);
    }

    const form = await c.req.parseBody();
    const file = form["file"];
    if (!file || typeof file === "string") {
      return errorResponse(c, "A file is required", 400);
    }
    if (!ALLOWED_MIME.includes(file.type)) {
      return errorResponse(
        c,
        `Unsupported image type ${file.type}. Use JPEG, PNG or WebP.`,
        415,
      );
    }
    if (file.size > MAX_AVATAR_BYTES) {
      return errorResponse(c, "Image must be 2MB or smaller", 413);
    }

    const extension = file.type.split("/")[1]?.replace("jpeg", "jpg") ?? "jpg";
    const name = `console-avatars/${consoleUserId}-${Date.now()}.${extension}`;
    const storage = gcsInit();
    const buffer = Buffer.from(await file.arrayBuffer());

    await storage.upload({ name, mime: file.type, size: file.size, buffer });
    const avatarUrl = await storage.getSignedUrl({
      name,
      mime: file.type,
      size: file.size,
    });

    const updated = await repo(c).UpdateProfile(consoleUserId, {
      avatar_url: String(avatarUrl),
    });
    c.set("entityId", consoleUserId);
    return success(c, updated, "Avatar updated");
  } catch (err) {
    logError(err);
    return errorResponse(c, "Failed to upload avatar", 500, err);
  }
};
