// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.

/**
 * Consumption history table management.
 *
 * @module     aiprovider_datacurso/consumption
 * @copyright  2025 Industria Elearning
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */

import Ajax from 'core/ajax';
import { get_string as getString } from 'core/str';
import Templates from 'core/templates';
import Notification from 'core/notification';
import AutoComplete from 'core/form-autocomplete';
import { getConsumptionHistory } from 'aiprovider_datacurso/repository';

export const init = async () => {
  // Elements DOM
  const filterUser = document.getElementById('filter-user');
  const filterService = document.getElementById('filter-service');
  const filterAction = document.getElementById('filter-action');
  const filterFrom = document.getElementById('filter-date-from');
  const filterTo = document.getElementById('filter-date-to');
  const prevPageBtn = document.getElementById('prev-page');
  const nextPageBtn = document.getElementById('next-page');
  const pageInfo = document.getElementById('page-info');
  const exportBtn = document.getElementById('export-csv');
  const tableRegionSelector =
    '[data-region="aiprovider_datacurso/consumption-table"]';

  // Order
  let currentSortField = "";
  let currentSortDir = "asc";

  // Rows currently shown in the table (current page), used for CSV export.
  let currentConsumptions = [];

  // Select and input for limit and page
  const limitSelect = document.getElementById("filter-limit");
  const pageInput = document.getElementById("filter-page");

  // Init status
  let currentPage = parseInt(sessionStorage.getItem("consumptionPage")) || 1;
  let currentLimit = parseInt(sessionStorage.getItem("consumptionLimit")) || 10;

  const savePage = (page) => sessionStorage.setItem("consumptionPage", page);
  const saveLimit = (limit) =>
    sessionStorage.setItem("consumptionLimit", limit);

  const updateSortIndicators = () => {
    document
      .querySelectorAll(`${tableRegionSelector} .sort-icon`)
      .forEach((icon) => {
        icon.className = "fa fa-sort sort-icon";
      });

    if (!currentSortField) {
      return;
    }

    const activeHeader = document.querySelector(
      `${tableRegionSelector} [data-sort="${currentSortField}"] .sort-icon`
    );
    if (activeHeader) {
      activeHeader.className =
        currentSortDir === "asc"
          ? "fa fa-sort-up sort-icon"
          : "fa fa-sort-down sort-icon";
    }
  };

  const bindSortingHandlers = () => {
    document
      .querySelectorAll(`${tableRegionSelector} .sortable`)
      .forEach((header) => {
        header.addEventListener("click", () => {
          const field = header.dataset.sort;
          if (!field) {
            return;
          }

          if (currentSortField === field) {
            currentSortDir = currentSortDir === "asc" ? "desc" : "asc";
          } else {
            currentSortField = field;
            currentSortDir = "desc";
          }

          updateSortIndicators();
          currentPage = 1;
          savePage(currentPage);
          fetchData();
        });
      });

    updateSortIndicators();
  };

  // Load users for filter
  // Setup user autocomplete with AJAX.
  const setupUserAutocomplete = async () => {
    try {
      const placeholder = await getString('search', 'core');
      AutoComplete.enhance(
        '#filter-user',
        false,
        'aiprovider_datacurso/repository',
        placeholder,
        false,
        true,
        '',
        false,
        1
      );
    } catch (error) {
      Notification.exception(error);
    }
  };

  const loadServices = async () => {
    try {
      const response = await Ajax.call([
        {
          methodname: "aiprovider_datacurso_get_services",
          args: {},
        },
      ])[0];

      if (response?.services?.length) {
        response.services.forEach((s) => {
          const opt = document.createElement("option");
          opt.value = s.id;
          opt.textContent = s.name;
          filterService.appendChild(opt);
        });
      }
    } catch (error) {
      Notification.exception(error);
      return [];
    }
  };

  const loadActions = async () => {
    try {
      const response = await Ajax.call([
        {
          methodname: "aiprovider_datacurso_get_actions",
          args: {},
        },
      ])[0];

      if (response?.actions?.length) {
        response.actions.forEach((a) => {
          const opt = document.createElement("option");
          opt.value = a.id;
          opt.textContent = a.name;
          filterAction.appendChild(opt);
        });
      }
    } catch (error) {
      Notification.exception(error);
      return [];
    }
  };

  const renderTable = async (listconsumptions, { loading = false } = {}) => {
    const container = document.querySelector(tableRegionSelector);
    if (!container) {
      return;
    }

    const consumptions = Array.isArray(listconsumptions)
      ? listconsumptions
      : [];
    const context = {
      initialized: !loading,
      consumptions: consumptions,
    };

    try {
      const render = await Templates.renderForPromise(
        "aiprovider_datacurso/consumption_row",
        context
      );
      await Templates.replaceNodeContents(container, render.html, render.js);
      bindSortingHandlers();
    } catch (error) {
      Notification.exception(error);
      const fallback = await Templates.renderForPromise(
        "aiprovider_datacurso/consumption_row",
        {
          initialized: true,
          consumptions: [],
        }
      );
      await Templates.replaceNodeContents(
        container,
        fallback.html,
        fallback.js
      );
      bindSortingHandlers();
    }
  };

  // Get history with filters
  const fetchData = async () => {
    const serviceValue = filterService.value;
    const actionValue = filterAction.value;
    const userValue = filterUser.value;
    const fromValue = filterFrom.value;
    const toValue = filterTo.value;

    const args = {
      page: currentPage,
      limit: currentLimit,
      userid: userValue !== "" ? parseInt(userValue) : 0,
      service: serviceValue !== "all" ? serviceValue : "",
      action: actionValue !== "all" ? actionValue : "",
      fromdate: fromValue || "",
      todate: toValue || "",
    };

    if (currentSortField) {
      args.shor = currentSortField;
      args.shordir = currentSortDir;
    }

    await renderTable([], { loading: true });

    const response = await getConsumptionHistory(args);

    const consumptions = response?.consumption || [];
    currentConsumptions = consumptions;
    if (exportBtn) {
      exportBtn.disabled = consumptions.length === 0;
    }
    await renderTable(consumptions);

    const pagination = response?.pagination;
    if (pagination) {
      const { current_page, total_pages, total } = pagination;
      const pageInfoText = await getString('pageinfo', 'aiprovider_datacurso', {
        current: current_page,
        totalpages: total_pages,
        total: total,
      });
      pageInfo.textContent = pageInfoText;
      if (pageInput) {
        pageInput.value = current_page;
      }
      prevPageBtn.disabled = current_page <= 1;
      nextPageBtn.disabled = current_page >= total_pages;
    } else {
      pageInfo.textContent = "";
      prevPageBtn.disabled = true;
      nextPageBtn.disabled = true;
    }
  };

  // Build and download a CSV of the rows currently shown in the table (current page only).
  const exportCsv = async () => {
    if (!currentConsumptions.length) {
      return;
    }

    const [hId, hUser, hAction, hService, hTokens, hBalance, hDate] =
      await Promise.all([
        getString("id", "aiprovider_datacurso"),
        getString("user", "core"),
        getString("action", "aiprovider_datacurso"),
        getString("service", "aiprovider_datacurso"),
        getString("tokensused", "aiprovider_datacurso"),
        getString("remainingtokens", "aiprovider_datacurso"),
        getString("date", "core"),
      ]);

    const escape = (val) => `"${String(val ?? "").replace(/"/g, '""')}"`;
    const lines = [[hId, hUser, hAction, hService, hTokens, hBalance, hDate].map(escape).join(",")];
    currentConsumptions.forEach((c) => {
      lines.push(
        [
          c.id_consumption,
          c.username,
          c.action,
          c.id_service,
          c.cant_tokens,
          c.balance,
          c.date,
        ].map(escape).join(",")
      );
    });

    // Prepend a UTF-8 BOM so Excel renders accents correctly.
    const csv = "\uFEFF" + lines.join("\r\n");
    const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
    const url = URL.createObjectURL(blob);

    const now = new Date();
    const stamp =
      `${now.getFullYear()}` +
      `${String(now.getMonth() + 1).padStart(2, "0")}` +
      `${String(now.getDate()).padStart(2, "0")}`;

    const link = document.createElement("a");
    link.href = url;
    link.download = `consumption-history-${stamp}.csv`;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    URL.revokeObjectURL(url);
  };

  if (exportBtn) {
    exportBtn.addEventListener("click", exportCsv);
  }

  // Event listeners for filters
  [filterUser, filterService, filterAction, filterFrom, filterTo].forEach((el) => {
    el.addEventListener("change", () => {
      currentPage = 1;
      savePage(currentPage);
      fetchData();
    });
  });

  prevPageBtn.addEventListener("click", () => {
    if (currentPage > 1) {
      currentPage--;
      savePage(currentPage);
      fetchData();
    }
  });

  nextPageBtn.addEventListener("click", () => {
    currentPage++;
    savePage(currentPage);
    fetchData();
  });

  if (limitSelect) {
    limitSelect.value = currentLimit;
    limitSelect.addEventListener("change", () => {
      currentLimit = parseInt(limitSelect.value);
      saveLimit(currentLimit);
      currentPage = 1;
      savePage(currentPage);
      fetchData();
    });
  }

  if (pageInput) {
    pageInput.addEventListener("change", () => {
      const newPage = parseInt(pageInput.value);
      if (newPage && newPage > 0) {
        currentPage = newPage;
        savePage(currentPage);
        fetchData();
      }
    });
  }

  // Initial load
  await setupUserAutocomplete();
  await loadServices();
  await loadActions();
  await fetchData();
};
