import type { Request as ExRequest } from "express";
import {
  Body,
  Controller,
  Get,
  Patch,
  Path,
  Post,
  Query,
  Request,
  Response,
  Route,
  SuccessResponse,
  Tags,
} from "tsoa";
import { createTask, getTaskDetail, listTasks, updateTask } from "../repository";
import type {
  CreateTaskRequest,
  ErrorResponse,
  TaskEnvelope,
  TasksEnvelope,
  UpdateTaskRequest,
} from "../models";
import { HttpError } from "../httpErrors";
import { getDatabase, normalizeCreateTask, normalizeUpdateTask } from "./shared";

@Route("tasks")
@Tags("Tasks")
export class TasksController extends Controller {
  @Get()
  public listTasks(
    @Request() request: ExRequest,
    @Query() orgId?: string,
    @Query() projectId?: string,
    @Query() status?: string,
    @Query() priority?: string,
    @Query() assigneeUserId?: string,
  ): TasksEnvelope {
    return {
      tasks: listTasks(getDatabase(request), {
        orgId,
        projectId,
        status,
        priority,
        assigneeUserId,
      }),
    };
  }

  @Post()
  @SuccessResponse("201", "Created")
  @Response<ErrorResponse>(400, "Invalid payload")
  public createTask(
    @Request() request: ExRequest,
    @Body() body: CreateTaskRequest,
  ): TaskEnvelope {
    this.setStatus(201);
    const task = createTask(getDatabase(request), normalizeCreateTask(body));
    return { task: task! };
  }

  @Get("{taskId}")
  @Response<ErrorResponse>(404, "Task not found")
  public getTask(
    @Request() request: ExRequest,
    @Path() taskId: string,
  ): TaskEnvelope {
    const task = getTaskDetail(getDatabase(request), taskId);
    if (!task) {
      throw new HttpError(404, "Task not found.");
    }

    return { task };
  }

  @Patch("{taskId}")
  @Response<ErrorResponse>(404, "Task not found")
  public updateTask(
    @Request() request: ExRequest,
    @Path() taskId: string,
    @Body() body: UpdateTaskRequest,
  ): TaskEnvelope {
    const task = updateTask(getDatabase(request), taskId, normalizeUpdateTask(body));
    if (!task) {
      throw new HttpError(404, "Task not found.");
    }

    return { task };
  }
}
