// modules/datatable_helper.js
import { fetch_helper } from "./fetch_helper.js";

export async function initDatatable(config) {
  const {
    tableId,
    formData,
    displayColumns = [],
    allowAction = true,
    viewedit_action_url = null,
    delete_action_callback = null,
    // new: array of custom action definitions: [{ name: 'detail', display: 'Detail', callback: fn }]
    custom_action_callback = [],
    filterKolom = [],
    additionalFilterParameter = [],
  } = config;

  const tableEl = document.getElementById(tableId);
  if (!tableEl) return;

  let allDinamisFilters = []; // menampung semua filter dinamis (dari filterKolom)
  let currentFilters = [];
  let currentRowsPerPage = 25;

  // Fungsi untuk fetch data ke backend
  async function loadData(extraFilters = [], dinamisFilters = []) {
    const sendData = new URLSearchParams(formData);

    // Filter biasa (search, order, dsb)
    extraFilters.forEach((f) => {
      if (f.value !== undefined) sendData.set(f.name, f.value);
    });

    // --- 1. Bangun filter dinamis ---
    const filtersArray = dinamisFilters
      .filter((f) => f.value !== "")
      .map((f) => {
        let compareType = 1; // default "="
        if (f.type === "date" || f.type === "datetime")
          compareType = 3; // misal LIKE tanggal
        else if (f.type === "text") compareType = 2; // misal contains
        return [f.name, f.value, compareType];
      });

    // --- 2. Tambahan filter opsional ---
    let additionalFilters = []; // bisa array kosong
    // contoh jika ada tambahan: additionalFilters = [["IDSource", 1, 1]];
    if (
      typeof additionalFilterParameter !== "undefined" &&
      additionalFilterParameter
    ) {
      // pastikan array 3 elemen valid
      if (
        Array.isArray(additionalFilterParameter) &&
        additionalFilterParameter.length === 3
      ) {
        additionalFilters.push(additionalFilterParameter);
      } else if (
        Array.isArray(additionalFilterParameter) &&
        additionalFilterParameter.length > 0
      ) {
        // kalau sudah array of arrays
        additionalFilters = additionalFilterParameter;
      }
    }

    // --- 3. Gabungkan hasil ---
    const finalFilters = [
      ...filtersArray,
      ...(Array.isArray(additionalFilters) ? additionalFilters : []),
    ];

    // --- 4. Serialize dan kirim ---
    sendData.set("filters", JSON.stringify(finalFilters));

    const { result } = await fetch_helper({
      fetchFile: "",
      formData: sendData,
    });

    if (!result || result.Status !== 1) {
      Swal.fire("Error", result?.Keterangan || "Failed to load data", "error");
      return null;
    }

    return result;
  }

  // === FETCH DATA AWAL ===
  const result = await loadData();
  if (!result) return;

  const PKColumn = result.PKColumn;
  const orderColumns = result.orderColumns || [];

  // === HANDLE COLUMNS ===
  const columnsFiltered = displayColumns
    .filter((col) => orderColumns.includes(col.columnName))
    .filter((col) => col.IsShown !== false);

  // Render header
  const thead = document.getElementById(`${tableId}_thead`);
  thead.innerHTML = `
    <th class="text-center"><input type="checkbox" id="${tableId}_select_all" /></th>
    <th class="text-center">#</th>
    ${allowAction ? `<th class="text-center">Action</th>` : ""}
    ${columnsFiltered
      .map((col) => `<th>${col.displayedName || col.columnName}</th>`)
      .join("")}
    
  `;

  // Fill order_by options
  const orderSelect = document.getElementById(`${tableId}_order_by`);
  if (orderSelect) {
    orderSelect.innerHTML = orderColumns
      .map((col) => `<option value="${col}">${col}</option>`)
      .join("");
  }

  // === INIT DATATABLE ===
  const dt = $(`#${tableId}`).DataTable({
    data: result.list_data || [],
    columns: [
      {
        data: null,
        orderable: false,
        className: "text-center",
        render: () => `<input type="checkbox" class="dt-checkbox" />`,
      },
      {
        data: null,
        className: "text-center",
        render: (data, type, row, meta) => meta.row + 1,
      },
      ...(allowAction
        ? [
            {
              data: PKColumn,
              orderable: false,
              className: "no-export text-center",
              render: (data, type, row, meta) => {
                const hasEdit =
                  viewedit_action_url && viewedit_action_url.trim() !== "";

                // build custom action buttons
                const actions = [];

                // view/edit
                if (hasEdit) {
                  actions.push(`
                    <li>
                      <a class="dropdown-item view-edit" href="${viewedit_action_url}?id=${data}" data-id="${data}">
                        <i class="fa fa-pen me-2 text-primary"></i> View/Edit
                      </a>
                    </li>
                  `);
                }

                // custom actions (array)
                if (Array.isArray(custom_action_callback) && custom_action_callback.length > 0) {
                  custom_action_callback.forEach((c) => {
                    // c: { name, display }
                    const name = c.name || String(Math.random()).slice(2);
                    const display = c.display || name;
                    actions.push(`
                      <li>
                        <a class="dropdown-item custom-action" href="#" data-action="${name}" data-id="${data}">
                          <i class="fa fa-info-circle me-2"></i> ${display}
                        </a>
                      </li>
                    `);
                  });
                }

                // delete
                actions.push(`
                  <li>
                    <a class="dropdown-item text-danger delete-item" href="#" data-id="${data}">
                      <i class="fa fa-trash me-2"></i> Delete
                    </a>
                  </li>
                `);

                return `
                  <div class="dropdown">
                    <button class="btn btn-sm btn-primary dropdown-toggle" data-bs-toggle="dropdown">Actions</button>
                    <ul class="dropdown-menu">
                      ${actions.join("")}
                    </ul>
                  </div>`;
              },
            },
          ]
        : []),

      ...columnsFiltered.map((col) => ({
        data: col.columnName,
        defaultContent: "-",
        render: (data, type, row) => {
          // === TYPE HANDLER ===
          const val = data ?? "";
          const t = (col.dataType || "string").toLowerCase();

          switch (t) {
            case "numeric": {
              if (val === null || val === undefined || val === "")
                return `<span class="text-muted">-</span>`;

              const opts = col.displayedValue || {};
              const prefix = opts.prefix || "";
              const suffix = opts.suffix || "";
              const useDecimal = opts.decimal ?? false;
              const decimalDigits = opts.decimalDigits ?? 0;
              const locale = opts.locale || "id-ID"; // default Indonesia

              let num = Number(val);
              if (isNaN(num)) return val;

              const formatted = num.toLocaleString(locale, {
                minimumFractionDigits: useDecimal ? decimalDigits : 0,
                maximumFractionDigits: useDecimal ? decimalDigits : 0,
              });

              return `<span>${prefix}${formatted}${suffix}</span>`;
            }

            case "boolean": {
              const map = col.displayedValue || {
                false: `<span class="badge bg-danger">No</span>`,
                true: `<span class="badge bg-success">Yes</span>`,
              };
              return val == 1 || val === true ? map.true : map.false;
            }

            case "enum": {
              if (val === null || val === undefined || val === "")
                return `<span class="text-muted">-</span>`;

              const map = col.displayedValue;

              // Jika pakai function
              if (typeof map === "function") {
                return map(val, row);
              }

              // Jika pakai object mapping
              if (typeof map === "object") {
                return (
                  map[val] ??
                  `<span class="badge badge-light-dark">${val}</span>`
                );
              }

              // fallback default
              return `<span>${val}</span>`;
            }

            case "date":
            case "datetime": {
              if (!val) return "-";
              const date = new Date(val);
              if (isNaN(date)) return val;

              const fmt =
                col.displayedValue?.format ||
                (t === "date" ? "dd MMM yyyy" : "dd MMM yyyy HH:mm:ss");

              // simple format manual
              const pad = (n) => String(n).padStart(2, "0");
              const formatted = fmt
                .replace("yyyy", date.getFullYear())
                .replace("MM", pad(date.getMonth() + 1))
                .replace("dd", pad(date.getDate()))
                .replace("HH", pad(date.getHours()))
                .replace("mm", pad(date.getMinutes()))
                .replace("ss", pad(date.getSeconds()));

              return `<span>${formatted}</span>`;
            }

            case "image":
              if (!val) return `<span class="text-muted">No Image</span>`;

              const basePath = col.displayedValue?.path || "";
              let addPath = "";

              if (col.displayedValue?.additionalpath) {
                const ap = col.displayedValue.additionalpath;
                addPath = row?.[ap] ? `${row[ap]}/` : "";
              }

              const fullPath = `${basePath}${addPath}${val}`;
              const width = col.displayedValue?.width || 40;
              const height = col.displayedValue?.height || 40;

              // tambahkan class viewer-image agar dikenali viewer
              return `
          <div class="symbol symbol-${width}px symbol-circle" style="width:${width}px; height:${height}px;">
            <img src="${fullPath}" class="img-fluid rounded-circle border viewer-image lozad" alt="img" />
          </div>`;
            case "file": {
              if (!val)
                return `<span class="text-muted">No ${
                  t === "image" ? "Image" : "File"
                }</span>`;

              const basePath = col.displayedValue?.path || "";
              let addPath = "";

              // Jika additionalpath diisi dan merupakan nama kolom di row
              if (col.displayedValue?.additionalpath) {
                const ap = col.displayedValue.additionalpath;
                addPath = row?.[ap] ? `${row[ap]}/` : "";
              }

              const fullPath = `${basePath}${addPath}${val}`;
              if (t === "image") {
                const width = col.displayedValue?.width || 40;
                const height = col.displayedValue?.height || 40;
                return `
          <div class="symbol symbol-${width}px symbol-circle" style="width:${width}px; height:${height}px;">
            <img src="${fullPath}" class="img-fluid rounded-circle border" alt="img" />
          </div>`;
              } else {
                const label =
                  col.displayedValue?.label ||
                  `<i class="fa fa-download me-1"></i>Download`;
                return `<a href="${fullPath}" target="_blank" class="text-primary text-decoration-none">${label}</a>`;
              }
            }

            default: {
              // string
              if (!val) return `<span class="text-muted">-</span>`;
              return col.displayedValue
                ? col.displayedValue.replace("{value}", val)
                : val;
            }
          }
        },
      })),
    ],
    responsive: true,
    paging: true,
    searching: false,
    lengthChange: true,
    pageLength: 25,
    lengthMenu: [
      [10, 25, 50, 100, 1000, 5000, 10000, -1],
      [10, 25, 50, 100, 1000, 5000, 10000, "Semua"],
    ],
    dom: `
    <"d-flex flex-wrap justify-content-between align-items-center mb-3"Bf>
    rt
    <"d-flex flex-column flex-md-row justify-content-between align-items-md-center mt-3 gap-2"li p>
  `,
    buttons: [
      {
        extend: "copyHtml5",
        text: '<i class="fa fa-copy me-1"></i> Salin',
        className: "btn btn-light btn-sm border",
        exportOptions: {
          columns: ":not(.no-export)", // 👈 skip kolom Action
        },
      },
      {
        extend: "excelHtml5",
        text: '<i class="fa fa-file-excel me-1 text-success"></i> Excel',
        className: "btn btn-light btn-sm border",
        exportOptions: {
          columns: ":not(.no-export)",
        },
      },
      {
        extend: "pdfHtml5",
        text: '<i class="fa fa-file-pdf me-1 text-danger"></i> PDF',
        className: "btn btn-light btn-sm border",
        exportOptions: {
          columns: ":not(.no-export)",
        },
      },
    ],
  });

  // === IMAGE VIEWER HANDLER ===
  let tableViewer = null;

  // Fungsi untuk aktifkan viewer di tabel
  function initTableViewer() {
    const tableContainer = document.querySelector(`#${tableId}`);
    if (!tableContainer) return;

    // Destroy viewer lama agar gak duplikat
    if (tableViewer) {
      tableViewer.destroy();
      tableViewer = null;
    }

    // Inisialisasi viewer baru untuk semua gambar di tabel & child row
    tableViewer = new Viewer(tableContainer, {
      toolbar: true,
      navbar: false,
      title: false,
      movable: true,
      zoomable: true,
      rotatable: false,
      scalable: false,
      fullscreen: true,
      transition: true,
      zIndex: 9999,
    });
  }

  // Inisialisasi awal
  initTableViewer();

  // Re-init saat tabel digambar ulang (paging, reload, dsb)
  $(`#${tableId}`).on("draw.dt", function () {
    initTableViewer();
  });

  // Re-init juga saat responsive child dibuka/tutup
  $(`#${tableId}`).on("responsive-display.dt", function () {
    initTableViewer();
  });

  // === CUSTOM ACTION HANDLER (delegated) ===
  $(`#${tableId}`).on("click", ".custom-action", async function (e) {
    e.preventDefault();
    const id = $(this).data("id");
    const action = $(this).data("action");

    if (!Array.isArray(custom_action_callback)) return;

    const def = custom_action_callback.find((c) => c.name === action);
    if (!def) {
      console.warn("No custom action defined for", action);
      return;
    }

    try {
      if (typeof def.callback === "function") {
        // allow callback to return a promise/result
        await def.callback(id, { rowId: id, tableId, dt });
      } else if (typeof window[def.callback] === "function") {
        await window[def.callback](id, { rowId: id, tableId, dt });
      } else {
        console.warn("custom_action_callback callback not a function", def.callback);
      }
    } catch (err) {
      console.error(err);
    }
  });

  // === FILTER HANDLER ===
  const reloadTable = async () => {
    const result = await loadData(currentFilters, allDinamisFilters);
    if (!result) return;

    dt.clear();
    dt.rows.add(result.list_data || []);
    dt.draw();
  };

  // === HANDLE SEARCH, ORDER, ROWS, FILTER ===
  const searchInput = document.getElementById(`${tableId}_search`);
  const orderBySelect = document.getElementById(`${tableId}_order_by`);
  const orderTypeSelect = document.getElementById(`${tableId}_order_type`);
  const rowsSelect = document.getElementById(`${tableId}_rows_per_page`);

  if (searchInput) {
    searchInput.addEventListener(
      "keyup",
      debounce(() => {
        updateFilter("search", searchInput.value);
      }, 400),
    );
  }

  if (orderBySelect) {
    orderBySelect.addEventListener("change", () => {
      updateFilter("order_by", orderBySelect.value);
    });
  }

  if (orderTypeSelect) {
    orderTypeSelect.addEventListener("change", () => {
      updateFilter("order_type", orderTypeSelect.value);
    });
  }

  if (rowsSelect) {
    rowsSelect.addEventListener("change", () => {
      updateFilter("rows_per_page", rowsSelect.value);
      currentRowsPerPage = rowsSelect.value;
    });
  }

  // === HANDLE FILTER KOLOM DINAMIS ===
  if (Array.isArray(filterKolom) && filterKolom.length > 0) {
    filterKolom.forEach(([filterName, placeholder, tipe]) => {
      const el = document.querySelector(`[data-filter="${filterName}"]`);
      if (!el) return;

      // Simpan default ke allDinamisFilters
      allDinamisFilters.push({ name: filterName, value: "", type: tipe });

      switch (tipe) {
        case "options":
          el.addEventListener("change", () => {
            updateDinamisFilter(filterName, el.value, tipe);
          });
          break;

        case "date":
        case "datetime":
          el.addEventListener("change", () => {
            updateDinamisFilter(filterName, el.value, tipe);
          });
          break;

        default:
          el.addEventListener(
            "keyup",
            debounce(() => {
              updateDinamisFilter(filterName, el.value, tipe);
            }, 400),
          );
          break;
      }
    });
  }

  // Untuk dipanggil dari bindDatatableFilters()
  tableEl.reloadWithFilters = async (filters) => {
    currentFilters = filters;
    await reloadTable();
  };

  function updateFilter(name, value) {
    const idx = currentFilters.findIndex((f) => f.name === name);
    if (idx >= 0) currentFilters[idx].value = value;
    else currentFilters.push({ name, value });
    reloadTable();
  }

  // === UPDATE FILTER DINAMIS ===
  function updateDinamisFilter(name, value, type) {
    const idx = allDinamisFilters.findIndex((f) => f.name === name);
    if (idx >= 0) allDinamisFilters[idx].value = value;
    else allDinamisFilters.push({ name, value, type });

    // Reload data table dengan semua filter dinamis terbaru
    reloadTable();
  }

  // === CHECKBOX HANDLING ===
  const selectAll = document.getElementById(`${tableId}_select_all`);
  selectAll.addEventListener("change", function () {
    const checked = this.checked;
    $(`#${tableId} .dt-checkbox`).prop("checked", checked);
    toggleDeleteButton();
  });

  $(`#${tableId}`).on("change", ".dt-checkbox", toggleDeleteButton);

  function toggleDeleteButton() {
    if (!allowAction) return;
    const anyChecked = $(`#${tableId} .dt-checkbox:checked`).length > 0;
    const btn = document.getElementById(`${tableId}_delete_selected`);
    if (btn) btn.classList.toggle("d-none", !anyChecked);
  }

  // === DELETE HANDLERS ===
  $(`#${tableId}`).on("click", ".delete-item", async function (e) {
    e.preventDefault();
    const id = $(this).data("id");

    const confirm = await Swal.fire({
      text: "Yakin ingin menghapus data ini?",
      icon: "warning",
      showCancelButton: true,
      confirmButtonText: "Ya, Hapus",
      cancelButtonText: "Batal",
    });

    if (confirm.isConfirmed && typeof delete_action_callback === "function") {
      const result = await delete_action_callback(id);

      // ✅ reloadTable hanya jika Status = 1
      if (result?.Status === 1) {
        reloadTable();
      }
    }
  });

  document
    .getElementById(`${tableId}_delete_selected`)
    .addEventListener("click", async () => {
      const ids = [];
      $(`#${tableId} .dt-checkbox:checked`).each(function (_, el) {
        const row = $(el).closest("tr");
        const rowData = dt.row(row).data();
        if (rowData) {
          ids.push(rowData[PKColumn]);
        }
      });

      if (!ids.length) return;

      const confirm = await Swal.fire({
        text: `Yakin ingin menghapus ${ids.length} data ini?`,
        icon: "warning",
        showCancelButton: true,
        confirmButtonText: "Ya, Hapus",
        cancelButtonText: "Batal",
      });

      if (confirm.isConfirmed && typeof delete_action_callback === "function") {
        await delete_action_callback(ids);
        reloadTable();
      }
    });

  // === DEBOUNCE UTILITY ===
  function debounce(fn, delay = 400) {
    let timeout;
    return (...args) => {
      clearTimeout(timeout);
      timeout = setTimeout(() => fn(...args), delay);
    };
  }

  return dt;
}
