import * as Yup from "yup";
import { Request, Response } from "express";
import { getIO } from "../libs/socket";

import AppError from "../errors/AppError";
import ListPositionService from "../services/PositionService/ListPositionService";
import ShowPositionService from "../services/PositionService/ShowPositionService";
import CreatePositionService from "../services/PositionService/CreatePositionService";
import UpdatePositionService from "../services/PositionService/UpdatePositionService";
import DeletePositionService from "../services/PositionService/DeletePositionService";

type IndexQuery = {
  searchParam: string;
  pageNumber: string;
};

interface PositionData {
  name: string;
}

export const index = async (req: Request, res: Response): Promise<Response> => {
  const { searchParam, pageNumber } = req.query as IndexQuery;

  const { positions, count, hasMore } = await ListPositionService({
    searchParam,
    pageNumber
  });

  return res.json({ positions, count, hasMore });
};

export const store = async (req: Request, res: Response): Promise<Response> => {
  const newPosition: PositionData = req.body;

  const PositionSchema = Yup.object().shape({
    name: Yup.string().required()
  });

  try {
    await PositionSchema.validate(newPosition);
  } catch (err: any) {
    throw new AppError(err.message);
  }

  const position = await CreatePositionService({
    ...newPosition
  });

  const io = getIO();
  io.emit("position", {
    action: "create",
    position
  });

  return res.status(200).json(position);
};

export const show = async (req: Request, res: Response): Promise<Response> => {
  const { positionId } = req.params;

  const position = await ShowPositionService(positionId);

  return res.status(200).json(position);
};

export const update = async (
  req: Request,
  res: Response
): Promise<Response> => {
  const positionData: PositionData = req.body;

  const schema = Yup.object().shape({
    name: Yup.string().required()
  });

  try {
    await schema.validate(positionData);
  } catch (err: any) {
    throw new AppError(err.message);
  }

  const { positionId } = req.params;

  const position = await UpdatePositionService({
    positionData,
    positionId
  });

  const io = getIO();
  io.emit("position", {
    action: "update",
    position
  });

  return res.status(200).json(position);
};

export const remove = async (
  req: Request,
  res: Response
): Promise<Response> => {
  const { positionId } = req.params;

  await DeletePositionService(positionId);

  const io = getIO();
  io.emit("position", {
    action: "delete",
    positionId
  });

  return res.status(200).json({ message: "Position deleted" });
};
