import { Body, Controller, Get, Inject, Param, Post, Query, UseGuards } from "@nestjs/common";
import type Redis from "ioredis";
import {
  AssignTaskRequest,
  CreateTaskRequest,
  ListTasksQuery,
  UpdateTaskRequest,
  UpdateTaskStatusRequest,
} from "@slackwsh/contracts";
import * as messaging from "@slackwsh/messaging";
import { AuthGuard } from "../auth/auth.guard";
import { CurrentUser } from "../auth/current-user.decorator";
import type { RequestUser } from "../auth/auth.guard";
import { REDIS_PUBSUB } from "../common/redis-pubsub.provider";

@UseGuards(AuthGuard)
@Controller("workspaces/:workspaceId/tasks")
export class TasksController {
  constructor(@Inject(REDIS_PUBSUB) private readonly redis: Redis) {}

  @Post()
  async create(@CurrentUser() user: RequestUser, @Param("workspaceId") workspaceId: string, @Body() body: unknown) {
    const input = CreateTaskRequest.parse(body);
    return messaging.createTask(this.redis, workspaceId, user.userId, input);
  }

  @Get()
  async list(@CurrentUser() user: RequestUser, @Param("workspaceId") workspaceId: string, @Query() query: unknown) {
    const filters = ListTasksQuery.parse(query);
    return { tasks: await messaging.listTasks(workspaceId, user.userId, filters) };
  }

  @Get("unread-assigned")
  async unreadAssigned(@CurrentUser() user: RequestUser, @Param("workspaceId") workspaceId: string) {
    return { unread: await messaging.unreadAssignedTaskCount(workspaceId, user.userId) };
  }

  /** Bodyless POST is valid — opening the Tasks page acknowledges everything. */
  @Post("mark-assigned-seen")
  async markAssignedSeen(@CurrentUser() user: RequestUser, @Param("workspaceId") workspaceId: string) {
    return messaging.markAssignedTasksSeen(workspaceId, user.userId);
  }

  @Get(":taskId")
  async get(@CurrentUser() user: RequestUser, @Param("workspaceId") workspaceId: string, @Param("taskId") taskId: string) {
    return messaging.getTask(workspaceId, user.userId, taskId);
  }

  @Post(":taskId/update")
  async update(
    @CurrentUser() user: RequestUser,
    @Param("workspaceId") workspaceId: string,
    @Param("taskId") taskId: string,
    @Body() body: unknown,
  ) {
    const input = UpdateTaskRequest.parse(body);
    return messaging.updateTask(this.redis, workspaceId, user.userId, taskId, input);
  }

  @Post(":taskId/assign")
  async assign(
    @CurrentUser() user: RequestUser,
    @Param("workspaceId") workspaceId: string,
    @Param("taskId") taskId: string,
    @Body() body: unknown,
  ) {
    const { assigneeUserId } = AssignTaskRequest.parse(body);
    return messaging.assignTask(this.redis, workspaceId, user.userId, taskId, assigneeUserId);
  }

  @Post(":taskId/status")
  async setStatus(
    @CurrentUser() user: RequestUser,
    @Param("workspaceId") workspaceId: string,
    @Param("taskId") taskId: string,
    @Body() body: unknown,
  ) {
    const { status } = UpdateTaskStatusRequest.parse(body);
    return messaging.updateTaskStatus(this.redis, workspaceId, user.userId, taskId, status);
  }

  @Post(":taskId/delete")
  async remove(@CurrentUser() user: RequestUser, @Param("workspaceId") workspaceId: string, @Param("taskId") taskId: string) {
    await messaging.deleteTask(this.redis, workspaceId, user.userId, taskId);
    return { deleted: true };
  }

  @Post(":taskId/restore")
  async restore(@CurrentUser() user: RequestUser, @Param("workspaceId") workspaceId: string, @Param("taskId") taskId: string) {
    return messaging.restoreTask(this.redis, workspaceId, user.userId, taskId);
  }
}
