import type { HttpContextContract } from "@ioc:Adonis/Core/HttpContext";
import Database from "@ioc:Adonis/Lucid/Database";
import KeyValue from "App/Models/KeyValue";
import LogDetectFile from "App/Models/LogDetectFile";
import axios from "axios";
import Env from "@ioc:Adonis/Core/Env";
import { checkSpecialVersion } from "App/utils/helper";

const BASE_URL = Env.get("BASE_URL_LOG");

export default class LogsController {
  public async showLog({ request, response }: HttpContextContract) {
    try {
      const fileName = decodeURIComponent(request.params().name);
      console.log(fileName);
      const fileDetect = await LogDetectFile.findBy("file_name", fileName);

      if (!fileDetect) {
        return response.status(203).send("FILE NOT FOUND");
      }

      const logsDetect = await Database.rawQuery(
        "SELECT * FROM log_reports WHERE id_file = ?",
        [fileDetect.id_ldf]
      );

      const lines = [...new Set(logsDetect[0].map((obj) => obj.line))].sort(
        (a: number, b: number) => a - b
      );

      const logUrl = `${BASE_URL}/${fileName}`;

      const content = await axios.get(logUrl);
      const allKeyValues = await KeyValue.all();

      const keyValueMap = allKeyValues.reduce((acc, { $original }) => {
        acc[$original.key] = acc[$original.key] || [];
        acc[$original.key].push($original.value);
        return acc;
      }, {} as Record<string, string[]>);

      const MODEL_SPECIAL = keyValueMap["MODEL_SPECIAL"] || [];
      const CATCH_FAULTY = keyValueMap["CATCH_FAULTY"] || [];
      const EXCLUDE_ERR = keyValueMap["EXCLUDE_ERR"] || [];

      const rawData = content.data.split("\n");
      const processedData: string[] = [];
      const modelSpecialDetected: string[] = [];
      const issueSpecialDetected: string[] = [];

      for (let i = 0; i < rawData.length; i++) {
        let line = rawData[i];
        let numberedLine = `${i + 1}|-|${line}`;
        const specialVersion = checkSpecialVersion(line);

        if (specialVersion) {
          const index = numberedLine.indexOf(specialVersion);
          numberedLine =
            numberedLine.slice(0, index) +
            "|-|" +
            specialVersion +
            "|-|" +
            numberedLine.slice(index + specialVersion.length);
        }

        for (const value of [...MODEL_SPECIAL, ...CATCH_FAULTY]) {
          if (
            line.includes(value) &&
            !EXCLUDE_ERR.some((err) => line.includes(err))
          ) {
            const index = numberedLine.indexOf(value);
            numberedLine =
              numberedLine.slice(0, index) +
              "|-|" +
              value +
              "|-|" +
              numberedLine.slice(index + value.length);
            break;
          }
        }

        processedData.push(numberedLine);
      }

      for (const lineIndex of lines) {
        const line = processedData[Number(lineIndex) - 1];
        if (!line) continue;
        if (EXCLUDE_ERR.some((err) => line.includes(err))) continue;

        if (
          MODEL_SPECIAL.some((model) => line.includes(model)) ||
          checkSpecialVersion(line)
        ) {
          modelSpecialDetected.push(line);
        } else {
          issueSpecialDetected.push(line);
        }
      }

      response.status(200).send({
        modelSpecial: modelSpecialDetected.join("\n"),
        issueItem: issueSpecialDetected.join("\n"),
        contentFile: processedData.join("\n"),
      });
    } catch (error) {
      console.error("Error fetching log:", error);
      response.status(203).send("FILE NOT FOUND");
    }
  }

  public async getAllLogDetect({ response }: HttpContextContract) {
    try {
      const files = await LogDetectFile.all();
      const fileNames = files.map((file) => file.file_name);
      response.status(200).send(fileNames);
    } catch {
      response.status(203).send("NO FILE");
    }
  }

  public async store({}: HttpContextContract) {}
  public async show({}: HttpContextContract) {}
  public async edit({}: HttpContextContract) {}
  public async update({}: HttpContextContract) {}
  public async destroy({}: HttpContextContract) {}
}
