import { NextResponse, NextRequest } from "next/server";
import { randomUUID } from "crypto";
interface APiData {
  "Users.uuid": string;
  "Users.firstName": string;
  "Users.lastName": string;
  "Users.email": string;
  "Users.phoneNumber": string;
  "Users.country": string;
  "Users.description": string;
  "Users.isDeleted": boolean;
  "Users.isConfirmed": boolean;
  "Users.createdAt": Date;
  "Users.updatedAt": Date;
}

function generateMockData(volume: number): APiData[] {
  const data: APiData[] = [];

  for (let i = 0; i < volume; i++) {
    data.push({
      "Users.uuid": randomUUID(),
      "Users.firstName": "test-name-" + i,
      "Users.lastName": "test-lastName-" + i,
      "Users.email": "test-email-" + i,
      "Users.phoneNumber": "test-phoneNumber-" + i,
      "Users.country": "test-country-" + i,
      "Users.description": "test-description-" + i,
      "Users.isDeleted": Math.random() > 0.5,
      "Users.isConfirmed": Math.random() > 0.5,
      "Users.createdAt": new Date(),
      "Users.updatedAt": new Date(),
    });
  }
  return data;
}

interface RequestParams {
  page: number;
  size: number;
  orderField: string[];
  orderType: string[];
  query: Record<string, any>;
}

const apiMockData: APiData[] = generateMockData(108);

interface PaginationRequest {
  page: number;
  size: number;
  orderField: string[];
  orderType: string[];
  query: Record<string, any>;
}

interface PaginationResponse {
  onPage: number;
  onPageCount: number;
  totalPage: number;
  totalCount: number;
  next: boolean;
  back: boolean;
}

interface DataResponse<T> {
  data: T[];
  pagination: PaginationResponse;
}
interface NextApiResponse<T> {
  status: number;
  data: DataResponse<T>;
}

export async function POST(
  request: NextRequest
): Promise<NextResponse<NextApiResponse<APiData>>> {
  const pagination: PaginationRequest = await request.json();

  const ceilLength = Math.ceil(apiMockData.length / pagination.size);
  const isNext = pagination.page < ceilLength;
  const isBack = pagination.page > 1;
  const sliceIfPaginationCorrect =
    pagination.page <= ceilLength ? pagination.page : ceilLength;
  const sliceParams = [
    (pagination.page - 1) * pagination.size,
    sliceIfPaginationCorrect * pagination.size,
  ];
  const orderField = pagination.orderField;
  const orderType = pagination.orderType;
  const query = pagination.query;

  const filteredData = apiMockData.filter((item) => {
    return Object.keys(query).every((key) => {
      return item[key as keyof APiData] === query[key];
    });
  });
  if (orderField && orderType) {
    for (let i = 0; i < orderField.length; i++) {
      const field = orderField[i];
      const order = orderType[i];
      if (order === "asc") {
        filteredData.sort((a, b) => {
          if (a[field as keyof APiData] < b[field as keyof APiData]) {
            return -1;
          }
          if (a[field as keyof APiData] > b[field as keyof APiData]) {
            return 1;
          }
          return 0;
        });
      } else {
        filteredData.sort((a, b) => {
          if (a[field as keyof APiData] < b[field as keyof APiData]) {
            return 1;
          }
          if (a[field as keyof APiData] > b[field as keyof APiData]) {
            return -1;
          }
          return 0;
        });
      }
    }
  }

  return NextResponse.json({
    status: 200,
    data: {
      data: filteredData.slice(...sliceParams),
      pagination: {
        onPage: pagination.page,
        onPageCount: pagination.size,
        totalPage: ceilLength,
        totalCount: apiMockData.length,
        next: isNext,
        back: isBack,
      },
    },
  });
}
