import axios from "axios";
import { franc } from "franc";
import { BREATHECODE_HOST, DEV_MODE, RIGOBOT_HOST } from "./constants";
import { Lesson } from "../components/LessonItem";
import { randomUUID } from "./creatorUtils";
import { Syllabus } from "./store";

export function parseLesson(input: string, previous: Lesson[]): Lesson | null {
  const pattern = /^([\d.]+)\s*-\s*(.*?)\s*\[(\w+):\s*(.+)\]$/;
  const match = input.match(pattern);

  if (!match) return null;

  const [, index, title, type, description] = match;

  const alreadyExistsIndex = previous.findIndex(
    (lesson) => lesson.id === index && lesson.title === title
  );

  if (alreadyExistsIndex !== -1) {
    return {
      id: index,
      uid: previous[alreadyExistsIndex].uid,
      title: title.trim(),
      type: type.trim().toUpperCase() as "READ" | "CODE" | "QUIZ",
      description: description.trim(),
      duration: previous[alreadyExistsIndex].duration,
      locked: previous[alreadyExistsIndex].locked || false,
    };
  }

  return {
    id: index,
    title: title.trim(),
    type: type.trim().toUpperCase() as "READ" | "CODE" | "QUIZ",
    description: description.trim(),
    duration: 2,
    uid: randomUUID(),
    locked: false,
  };
}

export const uploadFileToBucket = async (content: string, path: string) => {
  const response = await axios.post(`/upload`, {
    content,
    destination: path,
  });
  return response.data;
};
export const uploadImageToBucket = async (imageUrl: string, path: string) => {
  const response = await axios.post(`/upload-image`, {
    image_url: imageUrl,
    destination: path,
  });
  return response.data;
};

export const checkParams = (paramsToCheck: string[]) => {
  const urlParams = new URLSearchParams(window.location.search);
  const result: Record<string, string> = {};

  paramsToCheck.forEach((param) => {
    const value = urlParams.get(param);
    if (value !== null) {
      result[param] = value;
    }
  });

  return result;
};

export async function getConsumables(token: string): Promise<any> {
  const url = `${BREATHECODE_HOST}/v1/payments/me/service/consumable?virtual=true`;

  const headers = {
    Authorization: `Token ${token}`,
  };

  try {
    const response = await axios.get(url, { headers });
    return response.data;
  } catch (error) {
    console.error("Error fetching consumables:", error);
    throw error;
  }
}

type ConsumableSlug =
  | "ai-conversation-message"
  | "ai-compilation"
  | "ai-generation"
  | "ai-course-generation";

export async function useConsumableCall(
  breathecodeToken: string,
  consumableSlug: ConsumableSlug = "ai-conversation-message"
): Promise<boolean> {
  const url = `${BREATHECODE_HOST}/v1/payments/me/service/${consumableSlug}/consumptionsession`;

  const headers = {
    Authorization: `Token ${breathecodeToken}`,
  };

  try {
    const response = await axios.put(url, {}, { headers });

    if (response.status >= 200 && response.status < 300) {
      console.log(`Successfully consumed ${consumableSlug}`);
      return true;
    } else {
      console.error(`Request failed with status code: ${response.status}`);
      console.error(`Response: ${response.data}`);
      return false;
    }
  } catch (error) {
    console.error(`Error consuming ${consumableSlug}:`, error);
    return false;
  }
}

type ConsumableItem = {
  id: number;
  how_many: number;
  unit_type: string;
  valid_until: string | null;
};

type VoidEntry = {
  id: number;
  slug: string;
  balance: { unit: number };
  items: ConsumableItem[];
};

export const parseConsumables = (
  voids: VoidEntry[]
): Record<string, number> => {
  const result: Record<string, number> = {};

  voids.forEach((entry) => {
    const maxHowMany = entry.items.length
      ? Math.max(...entry.items.map((item) => item.how_many))
      : 0;
    result[entry.slug] = maxHowMany;
  });

  return result;
};

type LoginInfo = {
  email: string;
  password: string;
};

export const getRigobotJSON = async (breathecodeToken: string) => {
  const rigoUrl = `${RIGOBOT_HOST}/v1/auth/me/token?breathecode_token=${breathecodeToken}`;
  const rigoResp = await fetch(rigoUrl);
  if (!rigoResp.ok) {
    throw new Error("Unable to obtain Rigobot token");
  }
  const rigobotJson = await rigoResp.json();
  return rigobotJson;
};
export const validateUser = async (breathecodeToken: string) => {
  const config = {
    method: "GET",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Token ${breathecodeToken}`,
    },
  };

  const res = await fetch(`${BREATHECODE_HOST}/v1/auth/user/me`, config);
  if (!res.ok) {
    console.log("ERROR", res);
    return null;
  }
  const json = await res.json();

  if ("roles" in json) {
    delete json.roles;
  }
  if ("permissions" in json) {
    delete json.permissions;
  }
  if ("settings" in json) {
    delete json.settings;
  }

  return json;
};

export const login4Geeks = async (loginInfo: LoginInfo) => {
  const url = `${BREATHECODE_HOST}/v1/auth/login/`;

  const res = await fetch(url, {
    body: JSON.stringify(loginInfo),
    method: "post",
    headers: {
      "Content-Type": "application/json",
    },
  });

  if (!res.ok) {
    throw Error("Unable to login with provided credentials");
  }

  const json = await res.json();

  const rigoJson = await getRigobotJSON(json.token);

  const user = await validateUser(json.token);
  const returns = { ...json, rigobot: { ...rigoJson }, user };

  return returns;
};

export const loginWithToken = async (token: string) => {
  const rigoJson = await getRigobotJSON(token);

  const user = await validateUser(token);

  const returns = { rigobot: { ...rigoJson }, ...user };

  return returns;
};

export const validateTokens = async (
  breathecodeToken: string,
  onValidRigoToken: (token: string) => void
) => {
  const user = await validateUser(breathecodeToken);
  console.log("USER", user);
  if (!user) {
    return false;
  }

  const rigobotJson = await getRigobotJSON(breathecodeToken);
  if (!rigobotJson) {
    return false;
  }
  onValidRigoToken(rigobotJson.key);
  return true;
};

export function extractImagesFromMarkdown(markdown: string) {
  const imageRegex = /!\[([^\]]*)]\(([^)]+)\)/g;
  const images = [];
  let match;

  while ((match = imageRegex.exec(markdown)) !== null) {
    const altText = match[1];
    const url = match[2];
    images.push({ alt: altText, url: url });
  }

  return images;
}

export function getFilenameFromUrl(url: string): string {
  try {
    // 1) Use the URL constructor to strip off protocol/host/search/hash
    const pathname = new URL(url, location.href).pathname;
    // 2) Grab everything after the last “/”
    return pathname.substring(pathname.lastIndexOf("/") + 1);
  } catch {
    // Fallback for non-absolute URLs or invalid inputs
    const clean = url.split("?")[0].split("#")[0];
    return clean.substring(clean.lastIndexOf("/") + 1);
  }
}

export const makeCallbackUrl = (slug: string) => {
  if (DEV_MODE) {
    return `https://8000-charlytoc-rigobot-bmwdeam7cev.ws-us120.gitpod.io/v1/learnpack/tools/images/callback?slug=${slug}`;
  }
  return `${window.location.origin}/api/v1/webhooks/images`;
};

type TGenerateImageParams = {
  prompt: string;
};

export const generateImage = async (
  token: string,
  { prompt }: TGenerateImageParams
) => {
  try {
    const response = await axios.post(
      `${RIGOBOT_HOST}/v1/learnpack/tools/images`,
      {
        prompt,
        webhook_callback_url: "https://www.learnpack.co/api/v1/webhooks/images",
      },
      {
        headers: {
          "Content-Type": "application/json",
          Authorization: "Token " + token,
        },
      }
    );

    return response.data;
  } catch (error) {
    console.error("Error generating image:", error);
    return null;
  }
};

export const createCourse = async (
  syllabus: Syllabus,
  token: string,
  breathecodeToken: string
) => {
  const response = await axios.post(
    `/actions/create-course`,
    {
      syllabus,
    },
    {
      headers: {
        "x-breathecode-token": breathecodeToken,
        "x-rigo-token": token,
      },
    }
  );
  return response.data;
};

interface SlugAvailabilityResponse {
  slug: string;
  available: boolean;
}

export const isSlugAvailable = async (slug: string): Promise<boolean> => {
  try {
    const url = `${RIGOBOT_HOST}/v1/learnpack/check-slug-availability?slug=${encodeURIComponent(
      slug
    )}`;
    const response = await axios.get<SlugAvailabilityResponse>(url);
    return response.data.available;
  } catch (error) {
    console.error("Error checking slug availability:", error);
    throw error;
  }
};

export const reWriteTitle = async (title: string, token: string) => {
  // We hav in the parsed the newTitle
  try {
    const response = await axios.post(
      `${RIGOBOT_HOST}/v1/prompting/completion/1050/`,
      {
        inputs: {
          current_title: title,
        },
        include_purpose_objective: false,
        execute_async: false,
      },
      {
        headers: {
          "Content-Type": "application/json",
          Authorization: "Token " + token,
        },
      }
    );
    console.log("RESPONSE", response.data);
    return response.data.parsed.newTitle;
  } catch (error) {
    console.error("Error rewriting title:", error);
    // Return the title as it is with a random number of 4 characters
    return `${title} ${Math.random().toString(36).substring(2, 6)}`;
  }
};

export async function registerUserWithFormData(
  firstName: string,
  lastName: string,
  email: string
): Promise<any> {
  const formData = new FormData();
  formData.append("1_first_name", firstName);
  formData.append("1_last_name", lastName);
  formData.append("1_email", email);

  // Puedes modificar este objeto para agregar info real de tracking si la tienes.
  const conversionArray = [
    "$K1",
    {
      user_agent: navigator.userAgent,
      landing_url: "www.learnpack.co/my-tutorials",
      conversion_url: "app.learnpack.co/login",
      translations: "$undefined",
      utm_placement: "$undefined",
      utm_referrer: "$undefined",
      utm_medium: "$undefined",
      utm_source: "$undefined",
      utm_term: "$undefined",
      utm_content: "$undefined",
      utm_campaign: "$undefined",
      internal_cta_placement: "$undefined",
      internal_cta_content: "$undefined",
      internal_cta_campaign: "$undefined",
    },
  ];

  formData.append("0", JSON.stringify(conversionArray));

  try {
    const response = await axios.post(
      "https://www.learnpack.co/register",
      formData,
      {
        headers: {
          "Content-Type": "multipart/form-data",
        },
      }
    );
    return response.data;
  } catch (error: any) {
    // Manejo de errores básico
    console.error(error, "ERROR REGISTERING IN LEARNPACK");
    return {
      success: false,
      message: error?.response?.data?.detail || "Registration error",
      data: error?.response?.data || null,
    };
  }
}

export const isValidRigoToken = async (rigobotToken: string) => {
  const rigoUrl = `${RIGOBOT_HOST}/v1/auth/token/${rigobotToken}`;
  const rigoResp = await fetch(rigoUrl);
  if (!rigoResp.ok) {
    return false;
  }

  return true;
};
export const isValidPublicToken = async (publicToken: string) => {
  const headers = {
    "Content-Type": "application/json",
    Authorization: "Token " + publicToken,
  };
  const rigoUrl = `${RIGOBOT_HOST}/v1/auth/public/token/validate`;
  const rigoResp = await fetch(rigoUrl, { headers });
  if (!rigoResp.ok) {
    return false;
  }

  return true;
};

export const fixTitleLength = (title: string) => {
  const MAX_LENGTH = 49;
  let fixed = title.slice(0, MAX_LENGTH);
  fixed = fixed.replace(/^[^a-zA-Z0-9]+|[^a-zA-Z0-9]+$/g, "");
  return fixed;
};

export const getTechnologies = async () => {
  const response = await axios.get(`/technologies`);
  return response.data;
};

export const detectLanguage = (text: string) => {
  const lang = franc(text);
  if (lang === "spa") return "es";
  if (lang === "eng") return "en";
  return "en"; // fallback to English
};
