import { Response } from "express";
import { CustomRequest } from "../interfaces/auth";
import { STATUS_CODES } from "../constants/statusCodes";
import { GAS_STATION_REVIEW_CONSTANTS } from "../constants/messages";
import ResponseUtil from "../utils/Response/responseUtils";
import {
  createGasStationReviewSchema,
  gasStationReviewStationParamSchema,
  gasStationReviewIdParamSchema,
  gasStationReviewListSchema,
} from "../validators/gasStationReviewValidator";
import {
  createGasStationReview,
  listGasStationReviews,
  deleteGasStationReview,
} from "../services/gasStationReviewService";

function handleReviewError(res: Response, err: unknown): void {
  if (!(err instanceof Error)) {
    ResponseUtil.errorResponse(
      res,
      STATUS_CODES.INTERNAL_SERVER_ERROR,
      "An unexpected error occurred",
    );
    return;
  }

  switch (err.message) {
    case "STATION_NOT_FOUND":
      ResponseUtil.errorResponse(
        res,
        STATUS_CODES.NOT_FOUND,
        GAS_STATION_REVIEW_CONSTANTS.STATION_NOT_FOUND,
      );
      break;
    case "STATION_UNAVAILABLE":
      ResponseUtil.errorResponse(
        res,
        STATUS_CODES.BAD_REQUEST,
        GAS_STATION_REVIEW_CONSTANTS.STATION_UNAVAILABLE,
      );
      break;
    case "CANNOT_REVIEW_OWN":
      ResponseUtil.errorResponse(
        res,
        STATUS_CODES.BAD_REQUEST,
        GAS_STATION_REVIEW_CONSTANTS.CANNOT_REVIEW_OWN,
      );
      break;
    case "NOT_FOUND":
      ResponseUtil.errorResponse(
        res,
        STATUS_CODES.NOT_FOUND,
        GAS_STATION_REVIEW_CONSTANTS.NOT_FOUND,
      );
      break;
    case "FORBIDDEN":
      ResponseUtil.errorResponse(
        res,
        STATUS_CODES.FORBIDDEN,
        GAS_STATION_REVIEW_CONSTANTS.FORBIDDEN,
      );
      break;
    default:
      ResponseUtil.errorResponse(
        res,
        STATUS_CODES.INTERNAL_SERVER_ERROR,
        err.message,
      );
  }
}

const CREATE_ERRORS = [
  "STATION_NOT_FOUND",
  "STATION_UNAVAILABLE",
  "CANNOT_REVIEW_OWN",
];

/**
 * POST /api/v1/gas-stations/:gasStationId/reviews
 */
export const createStationReview = async (
  req: CustomRequest,
  res: Response,
) => {
  try {
    const { gasStationId } = await gasStationReviewStationParamSchema.parseAsync(
      req.params,
    );
    const { rating, comment } = await createGasStationReviewSchema.parseAsync(
      req.body ?? {},
    );
    const result = await createGasStationReview(
      req.userId!,
      gasStationId,
      rating,
      comment,
    );
    ResponseUtil.successResponse(
      res,
      STATUS_CODES.SUCCESS,
      result,
      GAS_STATION_REVIEW_CONSTANTS.CREATED,
    );
  } catch (err) {
    if (err instanceof Error && CREATE_ERRORS.includes(err.message)) {
      handleReviewError(res, err);
    } else {
      ResponseUtil.handleError(res, err);
    }
  }
};

/**
 * GET /api/v1/gas-stations/:gasStationId/reviews
 */
export const listStationReviews = async (
  req: CustomRequest,
  res: Response,
) => {
  try {
    const { gasStationId } = await gasStationReviewStationParamSchema.parseAsync(
      req.params,
    );
    const { page, limit } = await gasStationReviewListSchema.parseAsync(
      req.query,
    );
    const result = await listGasStationReviews(gasStationId, page, limit);
    ResponseUtil.successResponse(
      res,
      STATUS_CODES.SUCCESS,
      result,
      GAS_STATION_REVIEW_CONSTANTS.LIST_FETCHED,
    );
  } catch (err) {
    if (
      err instanceof Error &&
      ["STATION_NOT_FOUND", "STATION_UNAVAILABLE"].includes(err.message)
    ) {
      handleReviewError(res, err);
    } else {
      ResponseUtil.handleError(res, err);
    }
  }
};

/**
 * DELETE /api/v1/gas-stations/:gasStationId/reviews/:reviewId
 */
export const deleteStationReview = async (
  req: CustomRequest,
  res: Response,
) => {
  try {
    const { gasStationId, reviewId } =
      await gasStationReviewIdParamSchema.parseAsync(req.params);
    await deleteGasStationReview(req.userId!, gasStationId, reviewId);
    ResponseUtil.successResponse(
      res,
      STATUS_CODES.SUCCESS,
      {},
      GAS_STATION_REVIEW_CONSTANTS.DELETED,
    );
  } catch (err) {
    if (
      err instanceof Error &&
      ["NOT_FOUND", "FORBIDDEN"].includes(err.message)
    ) {
      handleReviewError(res, err);
    } else {
      ResponseUtil.handleError(res, err);
    }
  }
};
