import { BadRequestException, Controller, Get, Header, Param, Post, Req, Res, UseGuards } from "@nestjs/common";
import { createReadStream } from "node:fs";
import { EntityId } from "@slackwsh/contracts";
import { AuthGuard, type RequestUser } from "./auth.guard";
import { CurrentUser } from "./current-user.decorator";
import { ProfileService } from "./profile.service";

interface MultipartPhoto {
  filename: string;
  mimetype: string;
  toBuffer: () => Promise<Buffer>;
}

@Controller()
export class ProfileController {
  constructor(private readonly profiles: ProfileService) {}

  @UseGuards(AuthGuard)
  @Get("profile")
  async profile(@CurrentUser() user: RequestUser) {
    return { user: await this.profiles.getProfile(user.userId) };
  }

  @UseGuards(AuthGuard)
  @Post("profile/photo")
  async uploadPhoto(
    @CurrentUser() user: RequestUser,
    @Req() req: { file: () => Promise<MultipartPhoto | undefined> },
  ) {
    const part = await req.file();
    if (!part) throw new BadRequestException("photo is required");
    const buffer = await part.toBuffer();
    return { user: await this.profiles.setPhoto(user.userId, buffer, part.mimetype || "application/octet-stream") };
  }

  @UseGuards(AuthGuard)
  @Post("profile/photo/remove")
  async removePhoto(@CurrentUser() user: RequestUser) {
    return { user: await this.profiles.removePhoto(user.userId) };
  }

  @Get("profile-photos/:userId/:photoName")
  @Header("cache-control", "public, max-age=31536000, immutable")
  async photo(
    @Param("userId") userId: string,
    @Param("photoName") photoName: string,
    @Res() reply: { header: (name: string, value: string) => void; send: (payload: unknown) => unknown },
  ) {
    const path = await this.profiles.photoPath(EntityId.parse(userId), photoName);
    reply.header("content-type", "image/webp");
    return reply.send(createReadStream(path));
  }
}
