import axios from "axios"
import { writeFile } from "fs/promises"
import Console from "../utils/console"
import { PackageInfo } from "./creatorUtilities"
import * as fs from "fs"
import * as path from "path"
import { RIGOBOT_HOST } from "./api"

type TCreateReadmeInputs = {
  title: string;
  output_lang: string;
  list_of_exercises: string;
  tutorial_description: string;
  include_quiz: string;
  lesson_description: string;
  prev_lesson: string;
};

export const createReadme = async (
  token: string,
  inputs: TCreateReadmeInputs,
  purpose: string,
  webhookUrl?: string
) => {
  try {
    const response = await axios.post(
      `${RIGOBOT_HOST}/v1/prompting/completion/create-sequencial-readme/`,
      {
        inputs,
        include_purpose_objective: true,
        execute_async: !!webhookUrl,
        purpose_slug: purpose,
        webhook_url: webhookUrl,
      },
      {
        headers: {
          "Content-Type": "application/json",
          Authorization: "Token " + token.trim(),
        },
      }
    )
    return response.data
  } catch (error) {
    console.error(error)
    return null
  }
}

export const hasCreatorPermission = async (token: string) => {
  Console.debug("Checking if user has creator permission")
  try {
    const response = await axios.get(
      `${RIGOBOT_HOST}/v1/learnpack/permissions/creator`,
      {
        headers: {
          "Content-Type": "application/json",
          Authorization: "Token " + token,
        },
      }
    )

    // If the status code is 403, it means no permission
    if (response.status === 403) return false

    Console.debug("The user is a creator! 🎉")
    return true
  } catch (error) {
    Console.error(error as string)
    return false
  }
}

type TGenerateImageParams = {
  prompt: string;
  callbackUrl: string;
};

export const generateImage = async (
  token: string,
  { prompt, callbackUrl }: TGenerateImageParams
) => {
  try {
    const response = await axios.post(
      `${RIGOBOT_HOST}/v1/learnpack/tools/images`,
      {
        prompt,
        webhook_callback_url: callbackUrl,
        provider: "bfl",
        model: "flux-pro-1.1",
      },
      {
        headers: {
          "Content-Type": "application/json",
          Authorization: "Token " + token,
        },
      }
    )

    return response.data
  } catch (error) {
    Console.debug(error)
    return null
  }
}

export async function downloadImage(
  imageUrl: string,
  savePath: string
): Promise<void> {
  const response = await axios.get(imageUrl, { responseType: "arraybuffer" })

  const buffer = Buffer.from(response.data, "binary")

  await writeFile(savePath, buffer)
}

type TTranslateInputs = {
  text_to_translate: string;
  output_language: string;
};
export const translateExercise = async (
  token: string,
  inputs: TTranslateInputs,
  webhookUrl: string
) => {
  const response = await axios.post(
    `${RIGOBOT_HOST}/v1/prompting/completion/translate-asset-markdown/`,
    {
      inputs: inputs,
      include_purpose_objective: false,
      execute_async: true,
      webhook_url: webhookUrl,
    },
    {
      headers: {
        "Content-Type": "application/json",
        Authorization: "Token " + token,
      },
    }
  )

  return response.data
}

type TGenerateCourseIntroductionInputs = {
  course_title: string;
  lessons_context: string;
};

export const generateCourseIntroduction = async (
  token: string,
  inputs: TGenerateCourseIntroductionInputs
) => {
  const response = await axios.post(
    `${RIGOBOT_HOST}/v1/prompting/completion/192/`,
    {
      inputs: inputs,
      include_purpose_objective: false,
      execute_async: false,
    },
    {
      headers: {
        "Content-Type": "application/json",
        Authorization: "Token " + token,
      },
    }
  )

  return response.data
}

type TInteractiveCreationInputs = {
  courseInfo: string;
  prevInteractions: string;
};
export const interactiveCreation = async (
  token: string,
  inputs: TInteractiveCreationInputs
) => {
  const response = await axios.post(
    `${RIGOBOT_HOST}/v1/prompting/completion/390/`,
    {
      inputs: inputs,
      include_purpose_objective: false,
      execute_async: false,
    },
    {
      headers: {
        "Content-Type": "application/json",
        Authorization: "Token " + token,
      },
    }
  )

  return response.data
}

type TCreateCodeFileInputs = {
  readme: string;
  tutorial_info: string;
};

export const createCodeFile = async (
  token: string,
  inputs: TCreateCodeFileInputs
) => {
  const response = await axios.post(
    `${RIGOBOT_HOST}/v1/prompting/completion/456/`,
    {
      inputs: inputs,
      include_purpose_objective: false,
      execute_async: false,
    },
    {
      headers: {
        "Content-Type": "application/json",
        Authorization: "Token " + token,
      },
    }
  )

  return response.data
}

type TCreateCodingReadmeInputs = {
  title: string;
  output_lang: string;
  prev_lesson: string;
  tutorial_info: string;
  list_of_exercises: string;
  lesson_description: string;
};
export const createCodingReadme = async (
  token: string,
  inputs: TCreateCodingReadmeInputs,
  purpose: string,
  webhookUrl?: string
) => {
  const response = await axios.post(
    `${RIGOBOT_HOST}/v1/prompting/completion/create-coding-exercise/`,
    {
      inputs,
      include_purpose_objective: true,
      purpose_slug: purpose,
      execute_async: !!webhookUrl,
      webhook_url: webhookUrl,
    },
    {
      headers: {
        "Content-Type": "application/json",
        Authorization: "Token " + token,
      },
    }
  )

  return response.data
}

type TReadmeCreatorInputs = {
  tutorial_description: string;
  list_of_exercises: string;
  output_lang: string;
  title: string;
  lesson_description: string;
  kind: string;
  last_lesson: string;
};

export const readmeCreator = async (
  token: string,
  inputs: TReadmeCreatorInputs,
  purpose: string,
  webhookUrl?: string
) => {
  if (inputs.kind === "quiz" || inputs.kind === "read") {
    const createReadmeInputs: TCreateReadmeInputs = {
      title: inputs.title,
      output_lang: inputs.output_lang,
      list_of_exercises: inputs.list_of_exercises,
      tutorial_description: inputs.tutorial_description,
      include_quiz: inputs.kind === "quiz" ? "true" : "false",
      lesson_description: inputs.lesson_description,
      prev_lesson: inputs.last_lesson,
    }
    return createReadme(token, createReadmeInputs, purpose, webhookUrl)
  }

  if (inputs.kind === "code") {
    return createCodingReadme(
      token,
      {
        title: inputs.title,
        output_lang: inputs.output_lang,
        list_of_exercises: inputs.list_of_exercises,
        tutorial_info: inputs.tutorial_description,
        lesson_description: inputs.lesson_description,
        prev_lesson: inputs.last_lesson,
      },
      purpose,
      webhookUrl
    )
  }

  throw new Error("Invalid kind of lesson")
}

type TCreateStructuredPreviewReadmeInputs = {
  tutorial_info: string;
};

export const createStructuredPreviewReadme = async (
  token: string,
  inputs: TCreateStructuredPreviewReadmeInputs,
  webhookUrl?: string
) => {
  const response = await axios.post(
    `${RIGOBOT_HOST}/v1/prompting/completion/write-course-introduction-readme/`,
    {
      inputs: inputs,
      include_purpose_objective: false,
      webhook_url: webhookUrl,
    },
    {
      headers: {
        "Content-Type": "application/json",
        Authorization: "Token " + token.trim(),
      },
    }
  )

  return response.data
}

export const translateCourseMetadata = async (
  token: string,
  inputs: {
    title: string;
    description: string;
    new_languages: string;
  }
) => {
  const response = await axios.post(
    `${RIGOBOT_HOST}/v1/prompting/completion/translate-course-metadata/`,
    { inputs, include_purpose_objective: false, execute_async: false },
    {
      headers: {
        "Content-Type": "application/json",
        Authorization: "Token " + token,
      },
    }
  )

  return response.data
}

export async function createPreviewReadme(
  tutorialDir: string,
  packageInfo: PackageInfo,
  rigoToken: string,
  readmeContents: string[]
) {
  const readmeFilename = `README.md`

  const readmeContent = await generateCourseIntroduction(rigoToken, {
    course_title: packageInfo.title.us,
    lessons_context: readmeContents.join("\n"),
  })
  fs.writeFileSync(
    path.join(tutorialDir, readmeFilename),
    readmeContent.answer
  )
}

// {"lesson": "The text of the lesson", "number_of_words": "Words lenght of the lesson", "expected_number_words": "The expected number of words"}

type TReduceReadmeInputs = {
  lesson: string;
  number_of_words: string;
  expected_number_words: string;
  fkgl_results: string;
  expected_grade_level: string;
};
export async function makeReadmeReadable(
  rigoToken: string,
  inputs: TReduceReadmeInputs,
  purpose: string
) {
  try {
    const response = await axios.post(
      `${RIGOBOT_HOST}/v1/prompting/completion/588/`,
      { inputs, include_purpose_objective: false, execute_async: false },
      {
        headers: {
          "Content-Type": "application/json",
          Authorization: "Token " + rigoToken,
        },
      }
    )

    return response.data
  } catch (error) {
    Console.debug(error)
    return null
  }
}

export const isValidRigoToken = async (rigobotToken: string) => {
  const rigoUrl = `${RIGOBOT_HOST}/v1/auth/token/${rigobotToken}`
  const rigoResp = await fetch(rigoUrl)
  if (!rigoResp.ok) {
    Console.debug("Invalid Rigobot token", rigoResp.status)
    Console.debug(rigoResp.statusText)
    return false
  }

  return true
}

type TGenerateCourseShortNameInputs = {
  learnJSON: string;
};

export const generateCourseShortName = async (
  token: string,
  inputs: TGenerateCourseShortNameInputs
) => {
  const response = await axios.post(
    `${RIGOBOT_HOST}/v1/prompting/completion/852/`,
    { inputs, include_purpose_objective: false, execute_async: false },
    {
      headers: {
        "Content-Type": "application/json",
        Authorization: "Token " + token,
      },
    }
  )

  return response.data
}

type TFillSidebarJSONInputs = {
  needed_translations: string;
  sidebar_json: string;
};

export const fillSidebarJSON = async (
  token: string,
  inputs: TFillSidebarJSONInputs
) => {
  const response = await axios.post(
    `${RIGOBOT_HOST}/v1/prompting/completion/951/`,
    { inputs, include_purpose_objective: false, execute_async: false },
    {
      headers: {
        "Content-Type": "application/json",
        Authorization: "Token " + token,
      },
    }
  )

  return response.data
}

export const isPackageAuthor = async (
  token: string,
  packageSlug: string
): Promise<{ isAuthor: boolean; status: number }> => {
  const url = `${RIGOBOT_HOST}/v1/learnpack/package/${packageSlug}/`

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

  try {
    const response = await axios.get(url, { headers })
    return { isAuthor: response.status === 200, status: response.status }
  } catch (error: any) {
    const status = error?.response?.status || 500
    console.error("Error fetching package:", error)
    return { isAuthor: false, status }
  }
}

type TGetLanguageCodesInputs = {
  raw_languages: string;
};
export const getLanguageCodes = async (
  token: string,
  inputs: TGetLanguageCodesInputs
) => {
  const response = await axios.post(
    `${RIGOBOT_HOST}/v1/prompting/completion/get-language-codes/`,
    { inputs, include_purpose_objective: false, execute_async: false },
    {
      headers: {
        "Content-Type": "application/json",
        Authorization: "Token " + token,
      },
    }
  )

  return response.data
}

// New two-phase generation functions

type TInitialContentGeneratorInputs = {
  // prev_lesson: string;
  output_language: string;
  current_syllabus: string;
  lesson_description: string;
};

export const initialContentGenerator = async (
  token: string,
  inputs: TInitialContentGeneratorInputs,
  webhookUrl?: string
) => {
  try {
    const response = await axios.post(
      `${RIGOBOT_HOST}/v1/prompting/completion/initial-step-content-generator/`,
      {
        inputs,
        include_purpose_objective: false,
        execute_async: !!webhookUrl,
        webhook_url: webhookUrl,
      },
      {
        headers: {
          "Content-Type": "application/json",
          Authorization: "Token " + token.trim(),
        },
      }
    )
    return response.data
  } catch (error) {
    console.error("Error in initialContentGenerator:", error)
    return null
  }
}

type TAddInteractivityInputs = {
  components: string;
  prev_lesson: string;
  initial_lesson: string;
  output_language: string;
  current_syllabus: string;
};

export const addInteractivity = async (
  token: string,
  inputs: TAddInteractivityInputs,
  webhookUrl?: string
) => {
  try {
    const response = await axios.post(
      `${RIGOBOT_HOST}/v1/prompting/completion/lesson-refiner/`,
      {
        inputs,
        include_purpose_objective: false,
        execute_async: !!webhookUrl,
        webhook_url: webhookUrl,
      },
      {
        headers: {
          "Content-Type": "application/json",
          Authorization: "Token " + token.trim(),
        },
      }
    )
    return response.data
  } catch (error) {
    console.error("Error in addInteractivity:", error)
    return null
  }
}

type TGenerateCodeChallengeInputs = {
  lesson_content: string;
  challenge_proposal: string;
};

export const generateCodeChallenge = async (
  token: string,
  inputs: TGenerateCodeChallengeInputs,
  webhookUrl?: string
) => {
  try {
    const response = await axios.post(
      `${RIGOBOT_HOST}/v1/prompting/completion/generate-code-challenge-files/`,
      {
        inputs,
        include_purpose_objective: false,
        execute_async: !!webhookUrl,
        webhook_url: webhookUrl,
      },
      {
        headers: {
          "Content-Type": "application/json",
          Authorization: "Token " + token.trim(),
        },
      }
    )
    return response.data
  } catch (error) {
    console.error("Error in generateCodeChallenge:", error)
    return null
  }
}
