import type { Request as ExRequest } from "express";
import {
  Body,
  Controller,
  Get,
  Path,
  Post,
  Query,
  Request,
  Response,
  Route,
  SuccessResponse,
  Tags,
} from "tsoa";
import {
  createOrganization,
  getOrganizationSummary,
  listOrganizations,
  listProjects,
  listTasks,
} from "../repository";
import type {
  CreateOrganizationRequest,
  ErrorResponse,
  OrganizationEnvelope,
  OrganizationsEnvelope,
  ProjectsEnvelope,
  TasksEnvelope,
} from "../models";
import { HttpError } from "../httpErrors";
import { getDatabase, normalizeCreateOrganization } from "./shared";

@Route("orgs")
@Tags("Organizations")
export class OrganizationsController extends Controller {
  @Get()
  public listOrganizations(@Request() request: ExRequest): OrganizationsEnvelope {
    return { organizations: listOrganizations(getDatabase(request)) };
  }

  @Post()
  @SuccessResponse("201", "Created")
  @Response<ErrorResponse>(400, "Invalid payload")
  public createOrganization(
    @Request() request: ExRequest,
    @Body() body: CreateOrganizationRequest,
  ): OrganizationEnvelope {
    this.setStatus(201);
    const organization = createOrganization(
      getDatabase(request),
      normalizeCreateOrganization(body),
    );

    if (!organization) {
      throw new HttpError(500, "Failed to create organization.");
    }

    return { organization };
  }

  @Get("{orgId}")
  @Response<ErrorResponse>(404, "Organization not found")
  public getOrganization(
    @Request() request: ExRequest,
    @Path() orgId: string,
  ): OrganizationEnvelope {
    const organization = getOrganizationSummary(getDatabase(request), orgId);
    if (!organization) {
      throw new HttpError(404, "Organization not found.");
    }

    return { organization };
  }

  @Get("{orgId}/projects")
  public listOrganizationProjects(
    @Request() request: ExRequest,
    @Path() orgId: string,
  ): ProjectsEnvelope {
    return { projects: listProjects(getDatabase(request), orgId) };
  }

  @Get("{orgId}/tasks")
  public listOrganizationTasks(
    @Request() request: ExRequest,
    @Path() 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,
      }),
    };
  }
}
