import type { Database } from "bun:sqlite";
import type { Request as ExRequest } from "express";
import { HttpError } from "../httpErrors";
import type { CreateTaskRequest, UpdateTaskRequest } from "../models";

export function getDatabase(request: ExRequest): Database {
  return request.app.locals.db as Database;
}

function optionalText(value: unknown) {
  return typeof value === "string" ? value.trim() : undefined;
}

function nullableText(value: unknown) {
  if (typeof value === "string") {
    return value.trim();
  }

  return value === null ? null : undefined;
}

function nullableInteger(value: unknown) {
  if (typeof value === "number") {
    return Math.trunc(value);
  }

  return value === null ? null : undefined;
}

export function normalizeCreateTask(body: CreateTaskRequest): CreateTaskRequest {
  if (typeof body.orgId !== "string" || body.orgId.trim() === "") {
    throw new HttpError(400, "orgId is required.");
  }
  if (typeof body.projectId !== "string" || body.projectId.trim() === "") {
    throw new HttpError(400, "projectId is required.");
  }
  if (typeof body.title !== "string" || body.title.trim() === "") {
    throw new HttpError(400, "title is required.");
  }

  return {
    orgId: body.orgId.trim(),
    projectId: body.projectId.trim(),
    assigneeUserId:
      typeof body.assigneeUserId === "string" ? body.assigneeUserId.trim() : null,
    title: body.title.trim(),
    description: optionalText(body.description),
    status: optionalText(body.status),
    priority: optionalText(body.priority),
    storyPoints: nullableInteger(body.storyPoints),
    dueDate:
      typeof body.dueDate === "string"
        ? body.dueDate
        : body.dueDate === null
          ? null
          : undefined,
  };
}

export function normalizeUpdateTask(body: UpdateTaskRequest): UpdateTaskRequest {
  return {
    title: optionalText(body.title),
    description: optionalText(body.description),
    status: optionalText(body.status),
    priority: optionalText(body.priority),
    assigneeUserId: nullableText(body.assigneeUserId),
    storyPoints: nullableInteger(body.storyPoints),
    dueDate:
      typeof body.dueDate === "string"
        ? body.dueDate
        : body.dueDate === null
          ? null
          : undefined,
  };
}
