import { formatCode, generateUUID } from "@/utils/utils";

export const DataTypes = [
  "String",
  "Integer",
  "Boolean",
  "Float",
  // "alphaNumeric",
  "Double",
  // "List",
  // "Multiple Field Item",
  //   "alpha",
];
export const methods = ["GET ALL", "GET ONE", "CREATE", "UPDATE", "DELETE"];
export const DataTypesMap = {
  String: "varchar",
  Integer: "int",
  Boolean: "boolean",
  Float: "float",
  Double: "double",
  alphaNumeric: "varchar",
  Date: "date",
  Datetime: "datetime",
  Enum: "enum",
  Time: "time",
  Object: "object",
  Array: "array",
};
export const validationRules = [
  "is_required",
  "is_email",
  "is_url",
  "is_date",
  //   "min",
  //   "max",
  //   "in",
  //   "notIn",
  //   "regex",
  //   "ip",
  //   "ipv4",
  //   "ipv6",
];

export const InputType = [
  { value: "query", display: "Query" },
  { value: "body", display: "Body" },
  { value: "path", display: "Path/Param" },
  { value: "multipart", display: "Multipart (File Upload)" },
];

export const getDefaultResponseValueByType = (type = "string", model = {}) => {
  switch (type.toLowerCase()) {
    case "string":
    case "varchar":
    case "longtext":
    case "text":
      return "text";
    case "integer":
    case "int":
    case "tinyint":
      return 1;
    case "boolean":
      return true;
    case "float":
    case "double":
      return 0.1;
    case "array":
    case "Array":
      return `[{${Object.entries(model)
        .map(
          ([key, type]) =>
            `${key}: "${getDefaultResponseValueByType(type, model[key])}"`
        )
        .join(", ")}}]`;
    case "date":
      return "2024-01-01";
    case "date and time":
    case "datetime":
      return "2024-01-01T00:00:00.000Z";
    case "time":
      return "00:00:00";
    case "object":
      return `{${Object.entries(model)
        .map(
          ([key, type]) =>
            `${key}: "${getDefaultResponseValueByType(type, model[key])}"`
        )
        .join(", ")}}`;
    default:
      break;
  }
};

export const getDefaultRouteConfig = (projectId = null) => {
  return {
    id: generateUUID(),
    name: "",
    description: "",
    method: "GET",
    route: `/v3/api/custom/${projectId ? projectId : ""}${
      projectId ? "/" : ""
    }`,
    inputs: [],
    response: [
      {
        id: "error",
        key: "error",
        value: false,
        valueType: "Boolean",
        parent: "",
      },
      {
        id: "message",
        key: "message",
        value: "text",
        valueType: "String",
        parent: "",
      },
    ],
    response_model: [],
    logic: "",
    code: "",
    doc: "",
    unit: "",
    protected: false,
    authorizedRoles: [],
    imports: "",
    type: "custom",
    group: "custom",
    columns: { error: "Boolean", message: "String" },
  };
};

export const buildWorkflowCode = (selectedRoute, from) => {
  const content = [];
  const routeDefinition = getAPITopTemplate(selectedRoute);
  const routeCatch = getAPIBottomTemplate(selectedRoute);
  const validationCode = onAddValidation(selectedRoute);
  if (validationCode) {
    content.push(
      validationCode.trim().split("//======").filter(Boolean).length
        ? validationCode
        : ""
    );
  }

  // console.log("content >>", content);
  // console.log("bodyValidation :>> ", selectedRoute);
  const logicCode = content.join("\n");

  return [routeDefinition, logicCode, routeCatch];
};

function extractArray(data) {
  for (const key in data) {
    if (Array.isArray(data[key])) {
      return data[key];
    }
  }
  return data; // Return an empty array if no array is found
}
export const createModel = (
  routeName,
  columns,
  authorizedRoles,
  routeType,
  routeDescription,
  inputs,
  mockResponse = {},
  selectedApi
) => {
  console.log("mockResponse :>> ", selectedApi);
  const pathParams = inputs
    .filter((input) => input.type === "path")
    .map((input) => `:${input.name}`)
    .join("/");

  const queryParams = inputs
    .filter((input) => input.type === "query")
    .map((input) => `${input.name}=${input.name}`)
    .join("&");

  const baseRoute = `/v3/api/custom/${routeName}`;
  const routeWithParams = pathParams ? `${baseRoute}/${pathParams}` : baseRoute;
  const routeWithQuery = queryParams
    ? `${routeWithParams}?${queryParams}`
    : routeWithParams;

  const route = routeWithQuery;

  const commonConfig = {
    columns:
      routeType === "POST" || routeType === "PUT"
        ? inputs
            .filter((input) => input.type === "body")
            .reduce(
              (acc, input) => {
                acc[input.name] = input.dataType.toLowerCase();
                return acc;
              },
              { id: "int" }
            )
        : columns.reduce(
            (acc, col) => {
              acc[col.column] =
                col.type === "Array" && col.model
                  ? [
                      Object.fromEntries(
                        Object.entries(col.model).map(([key, type]) => [
                          key,
                          type.toLowerCase(),
                        ])
                      ),
                    ]
                  : col.type === "Object" && col.model
                  ? Object.fromEntries(
                      Object.entries(col.model).map(([key, type]) => [
                        key,
                        type.toLowerCase(),
                      ])
                    )
                  : col.type.toLowerCase();
              return acc;
            },
            { id: "int" }
          ),

    authorizedRoles: authorizedRoles.map((role) => role.value),
    protected: authorizedRoles.length > 0,
    description: routeDescription,
  };

  const mappedInputs = inputs.map((col) => ({
    name: col.name,
    type: col.type,
    rules: col.rules,
    dataType: col.dataType,
  }));

  const response = [
    {
      id: "error",
      key: "error",
      value: false,
      valueType: "Boolean",
      parent: "",
    },
    {
      id: "message",
      key: "message",
      value:
        routeType === "POST"
          ? `"Created successfully"`
          : routeType === "PUT"
          ? `"Successfully updated"`
          : `"Operation successful"`,
      valueType: "String",
      parent: "",
    },
    {
      id:
        routeType === "GET ALL"
          ? "list"
          : routeType === "GET ONE"
          ? "model"
          : "data",
      key:
        routeType === "GET ALL"
          ? "list"
          : routeType === "GET ONE"
          ? "model"
          : "data",

      value:
        routeType === "GET ALL" && mockResponse
          ? `[${extractArray(mockResponse)
              .map(
                (item) =>
                  `{${Object.entries(item)
                    .map(
                      ([key, value]) =>
                        `${key}: ${
                          typeof value === "object" && !Array.isArray(value)
                            ? `{${Object.entries(value)
                                .map(([key2, value2]) => `${key2}: "${value2}"`)
                                .join(", ")}}`
                            : Array.isArray(value)
                            ? `[${value
                                .map((item) =>
                                  typeof item === "object"
                                    ? `{${Object.entries(item)
                                        .map(
                                          ([key2, value2]) =>
                                            `${key2}: "${value2}"`
                                        )
                                        .join(", ")}}`
                                    : `"${item}"`
                                )
                                .join(", ")}]`
                            : `"${value}"`
                        }`
                    )
                    .join(", ")}}`
              )
              .join(", ")}]`
            : routeType === "GET ONE" && mockResponse
            ? `{${Object.entries(mockResponse)
                .map(
                  ([key, value]) =>
                    `${key}: ${
                      typeof value === "object" && !Array.isArray(value)
                        ? `{${Object.entries(value)
                            .map(([key2, value2]) => `${key2}: "${value2}"`)
                            .join(", ")}}`
                        : Array.isArray(value)
                        ? `[${value
                            .map((item) =>
                              typeof item === "object"
                                ? `{${Object.entries(item)
                                    .map(([key2, value2]) => `${key2}: "${value2}"`)
                                    .join(", ")}}`
                                : `"${item}"`
                            )
                            .join(", ")}]`
                        : `"${value}"`
                    }`
                )
                .join(", ")}}`  
          : routeType === "GET ALL"
          ? `[{${columns
              .map(
                (col) =>
                  `${col.column}: ${
                    col.type === "Object" || col.type === "Array"
                      ? `${getDefaultResponseValueByType(col.type, col.model)}`
                      : `"${getDefaultResponseValueByType(col.type)}"`
                  }`
              )
              .join(", ")}}]`
          : routeType === "GET ONE"
          ? `{${columns
              .filter((col) => !col.column.includes("undefined"))
              .map(
                (col) =>
                  `${col.column}: "${getDefaultResponseValueByType(col.type)}"`
              )
              .join(", ")}}`
          : routeType === "POST" || routeType === "PUT"
          ? columns.filter(
              (col) =>
                !["created_at", "updated_at", "id", "ID"].includes(col.column)
            ).length > 0
            ? `{${columns
                .filter(
                  (col) =>
                    !["created_at", "updated_at", "id", "ID"].includes(
                      col.column
                    )
                )
                .map(
                  (col) =>
                    `${col.column}: "${getDefaultResponseValueByType(
                      col.type
                    )}"`
                )
                .join(", ")}}`
            : 1
          : 1,
      valueType:
        routeType === "GET ALL"
          ? "Array"
          : routeType === "GET ONE"
          ? "Object"
          : "Integer",
      parent: "",
    },
  ];

  return {
    ...getDefaultRouteConfig(),
    id: selectedApi ? selectedApi.id : `_${routeName}${routeType.replace(" ", "")}`,
    name: selectedApi ? selectedApi.name : `${routeType} ${
      routeName.charAt(0).toUpperCase() + routeName.slice(1)
    }`,
    method:
      routeType === "GET ALL" || routeType === "GET ONE" ? "GET" : routeType,
    folder: selectedApi ? selectedApi.folder : `${routeName}`,
    route,
    inputs: mappedInputs,
    response,
    ...commonConfig,
  };
};
export const buildWorkflowCodeForAi = (selectedRoute, routeCatch) => {
  const content = [];
  const routeDefinition = getAPITopTemplate(selectedRoute);
  const bottomTemplate = getAPIBottomTemplate2(selectedRoute);
  const validationCode = onAddValidation(selectedRoute);
  if (validationCode) {
    content.push(
      validationCode.trim().split("//======").filter(Boolean).length
        ? validationCode
        : ""
    );
  }

  // console.log("content >>", content);
  // console.log("bodyValidation :>> ", selectedRoute);
  const logicCode = content.join("\n");

  return [routeDefinition, logicCode, routeCatch, bottomTemplate];
};

export const getMiddlewareStack = (endpoint) => {
  if (!endpoint?.protected) {
    return " middlewares ";
  }

  if (endpoint?.authorizedRoles?.length < 1) {
    return "[ ...middlewares, TokenMiddleware()]";
  }

  return `[ ...middlewares, TokenMiddleware({ role: "${endpoint?.authorizedRoles?.join(
    "|"
  )}" }) ] `;
};

export const getAPITopTemplate = (selectedEndpoint) => {
  return `app.${selectedEndpoint?.method?.toLowerCase()}('${
    selectedEndpoint?.route
  }', ${getMiddlewareStack(selectedEndpoint)} , async (req, res) => { 
          const sdk = req.sdk;
          sdk.setProjectId(req.projectId)
          try{
  `;
};
export const getAPIBottomTemplate = (selectedEndpoint) => {
  return `
      return res.status(200).json(${getResponseTemplate(selectedEndpoint)})
      } catch (err) {
          console.error(err);
          res.status(403).json({
              error: true,
              message: err.message
          });
          }
      })
      
  `;
};

export const getAPIBottomTemplate2 = (selectedEndpoint) => {
  return `
 
      } catch (err) {
          console.error(err);
          res.status(403).json({
              error: true,
              message: err.message
          });
          }
      })
      
  `;
};

const getResponseTemplate = (selectedEndpoint) => {
  return Array.isArray(selectedEndpoint?.response)
    ? `{${selectedEndpoint?.response?.map((item) => {
        return `${item?.key}: ${item?.value}`;
      })} }`
    : selectedEndpoint?.response;
};

export const onAddValidation = (selectedEndpoint) => {
  const inputs =
    selectedEndpoint?.inputs && selectedEndpoint?.inputs.length
      ? selectedEndpoint?.inputs
      : [];
  const body = inputs
    .filter((i) => i?.type === "body")
    .filter((i) => i?.rules !== "");

  let bodyValidation = ``;
  if (body?.length >= 1) {
    bodyValidation = `
              let validation = await validateObject({
                  ${body.map(
                    (input) => ` ${input?.name}: '${input?.rules}'
                  `
                  )}
              }, req.body,)
              if (validation.error) return res.status(403).json(validation)
          `;
  }

  const newCode = formatCode(
    ` ${bodyValidation} \n//======\n ${selectedEndpoint?.logic} `
  );
  return newCode;
};
