import React, { useRef, useState } from "react";
import { useGridCore } from "./useGridCore";
import { exportToCSV } from "./utils";
import "./pms-grid.css";
import PmsHeaderOption from "./PmsHeaderOption";
import FilterApplied from "./FilterApplied";

/*
 Props:
  - columns: [{ key, title, width, pinned: 'left'|'right'|null, sortable, render, aggregate }]
  - data OR serverMode + fetcher
  - rowKey
  - features: { selection, search, export, pagination, pinning, resizing, reorder, grouping, aggregation, expand }
  - renderExpanded
*/
export default function PmsGrid({
  columns = [],
  data,
  serverMode = false,
  fetcher,
  rowKey = "id",
  isDropdown = false,
  features = {},
  renderExpanded,
}) {
  const [isFullScreen,setFullScreen] = useState(false)
  const grid = useGridCore({
    data,
    serverMode,
    fetcher,
    rowKey,
    initialPageSize: features.pageSize || 25,
    columns,
  });
  const wrapperRef = useRef();

  const {
    rows,
    page,
    totalPages,
    pageSize,
    setPage,
    setPageSize,
    setGroupBy,
    groupBy,
    search,
    setSearch,
    selected,
    toggleSelect,
    selectAllOnPage,
    deselectAllOnPage,
    changeSort,
    sortBy,
    visibleColumns,
    colState,
    updateColumn,
    loading,
    totalRows,
    expanded,
    toggleExpand,
    setColState,
    onAdvanceFilters,
    setAdanceFilter,
  } = grid;

  // --- Pin / Unpin helpers ---
  const pinColumn = (key, side) => {
    const col = colState.find((c) => c.key === key);
    if (!col) return;
    // if already pinned to that side → unpin
    const newPinned = col.pinned === side || side === "none" ? null : side;
    updateColumn(key, { pinned: newPinned });
  };

  const unpinColumn = (key) => {
    updateColumn(key, { pinned: null });
  };

  // resizing via mouse down on handle
  const onResizeMouseDown = (e, key) => {
    e.preventDefault();
    const startX = e.clientX;
    const col = colState.find((c) => c.key === key);
    const startWidth = col.width || 120;

    const onMove = (ev) => {
      const diff = ev.clientX - startX;
      const newWidth = Math.max(60, startWidth + diff);
      updateColumn(key, { width: newWidth });
    };

    const onUp = () => {
      document.removeEventListener("mousemove", onMove);
      document.removeEventListener("mouseup", onUp);
    };
    document.addEventListener("mousemove", onMove);
    document.addEventListener("mouseup", onUp);
  };

  // reorder columns (drag/drop)
  const dragState = useRef({ from: null });
  const onDragStart = (e, key) => {
    dragState.current.from = key;
    e.dataTransfer.effectAllowed = "move";
  };
  const onDrop = (e, toKey) => {
    e.preventDefault();
    const fromKey = dragState.current.from;
    if (!fromKey || fromKey === toKey) return;
    const from = colState.find((c) => c.key === fromKey);
    const to = colState.find((c) => c.key === toKey);
    if (!from || !to) return;
    // swap orders
    setColState((prev) => {
      const next = prev.map((p) => ({ ...p }));
      const f = next.find((p) => p.key === fromKey);
      const t = next.find((p) => p.key === toKey);
      const tmp = f.order;
      f.order = t.order;
      t.order = tmp;
      return next.sort((a, b) => a.order - b.order);
    });
  };

  // group & aggregate (simple client-side grouping by column key)
  // const groupBy = features.groupByKey || null;
  const groupedRows = React.useMemo(() => {
    if (!groupBy) return null;
    const map = {};
    rows.forEach((r) => {
      const g = String(r[groupBy] ?? "Unknown");
      if (!map[g]) map[g] = [];
      map[g].push(r);
    });
    const groups = Object.keys(map).map((k) => ({ key: k, items: map[k] }));
    // apply aggregation
    const aggregates = groups.map((g) => {
      const ag = {};
      visibleColumns.forEach((col) => {
        if (col.aggregate) {
          ag[col.key] = col.aggregate(g.items.map((it) => it[col.key]));
        }
      });
      return { ...g, aggregates: ag };
    });
    return aggregates;
  }, [rows, groupBy, visibleColumns]);

  const currentRows = rows;

  return (
    <div className={`pms-grid ${isFullScreen ? "card card-action card-fullscreen p-4":""}`}>
      <div className="row  px-4">
        <div className="col-8">
          <div className="d-flex flex-row gap-2 gap-2 ">
            <div>
              {features.search && (
                <input
                  type="search"
                  className="form-control form-control-sm"
                  placeholder="Search..."
                  value={search}
                  onChange={(e) => setSearch(e.target.value)}
                />
              )}
            </div>
            {features.export && (
              <button
                className="btn btn-sm btn-outline-secondary"
                onClick={() =>
                  exportToCSV(
                    currentRows,
                    colState.filter((c) => c.visible)
                  )
                }
              >
                Export CSV
              </button>
            )}
            {features.grouping && (
              <div className="dropdown">
                <button
                  className="btn btn-sm btn-outline-secondary"
                  data-bs-toggle="dropdown"
                >
                  Group By
                </button>

                <div className="dropdown-menu px-1">
                  {visibleColumns
                    .filter((c) => c.groupable)
                    .map((c) => (
                      <li
                        key={c.key}
                        className="dropdown-item rounded py-1 cursor-pointer"
                        onClick={() => {
                          setGroupBy(c.key);
                          // groupByKey = c.key;
                        }}
                      >
                        {c.title}
                      </li>
                    ))}
                </div>
              </div>
            )}
          </div>
        </div>
        <div className="col-4 ">
          <div className="d-flex justify-content-end align-items-center gap-2">
            {features.columnVisibility && (
              <ColumnVisibilityPanel
                columns={colState}
                onToggle={(k) =>
                  updateColumn(k, {
                    visible: !colState.find((c) => c.key === k).visible,
                  })
                }
              />
            )}
            <i className={`bx bx-${isFullScreen ? "exit-fullscreen":"fullscreen"} cursor-pointer`} onClick={()=>setFullScreen(!isFullScreen)}></i>
          </div>
        </div>
        
      </div>

      <div className="d-flex">
         <FilterApplied groupBy={groupBy} removeGroupby={()=>setGroupBy(null)} advance={onAdvanceFilters} />
      </div>
      {/* Table-Start*/}
      <div
        ref={wrapperRef}
        className="grid-wrapper text-nowrap border"
        style={{ maxHeight: features.maxHeight || "80vh" }}
      >
        <table
          className="table  table-sm rounded mb-0 "
          style={{ width: "max-content", minWidth: "100%" }}
        >
          <thead
            className="bg-light-secondary border p-2 bg-light rounded"
            style={{ position: "sticky", top: 0, zIndex: 10 }}
          >
            <tr className="p-2">
              {features.IsNumbering && <th>#</th>}
              {features.expand && (
                <th className="text-center ticky-action-column">
                  <i className="bx bx-collapse-vertical"></i>
                </th>
              )}
              {features.selection && (
                <th
                  style={{ width: 32, position: "sticky", top: 0, zIndex: 10 }}
                  className="text-center ticky-action-column"
                >
                  <input
                    type="checkbox"
                    className="form-check-input mx-3"
                    checked={
                      currentRows.length > 0 &&
                      currentRows.every((r) => selected.has(r[rowKey]))
                    }
                    onChange={(e) =>
                      e.target.checked
                        ? selectAllOnPage(currentRows)
                        : deselectAllOnPage(currentRows)
                    }
                  />
                </th>
              )}

              {visibleColumns.map((col) => {
                const style = {
                  minWidth: col.width || 120,
                  width: col.width || undefined,
                };
                if (col.pinned) style.position = "sticky";
                if (col.pinned === "left")
                  style.left = `${getLeftOffset(colState, col.key)}px`;
                if (col.pinned === "right")
                  style.right = `${getRightOffset(colState, col.key)}px`;

                return (
                  <th
                    key={col.key}
                    draggable={features.reorder}
                    onDragStart={(e) => onDragStart(e, col.key)}
                    onDragOver={(e) => e.preventDefault()}
                    onDrop={(e) => onDrop(e, col.key)}
                    className={`pms-col-header vs-th ${
                      col.pinned ? `pinned pinned-${col.pinned}` : ""
                    }`}
                    style={style}
                  >
                    <div
                      className={`d-flex align-items-center justify-content-between px-1 ${
                        col.pinned ? "z-6" : ""
                      }`}
                    >
                      <div
                        onClick={() => col.sortable && changeSort(col.key)}
                        style={{ cursor: col.sortable ? "pointer" : "default" }}
                      >
                        <strong>{col.title}</strong>
                        {sortBy.key === col.key && (
                          <i
                            className={`bx bx-sm ${
                              sortBy.dir === "asc"
                                ? "bxs-chevron-up"
                                : "bxs-chevron-down"
                            }`}
                          ></i>
                        )}
                        {col.pinned === col.key && <i className="bx bx-x"></i>}
                      </div>

                      <div className="d-flex align-items-center gap-1">
                        {features.pinning && (
                          <PmsHeaderOption
                            column={col}
                            pinned={col.pinned}
                            onPinLeft={() => pinColumn(col.key, "left")}
                            onPinRight={() => pinColumn(col.key, "right")}
                            onUnpin={() => unpinColumn(col.key)}
                            onAdvancedFilter={setAdanceFilter}
                          />
                        )}
                        {features.resizing && (
                          <i
                            className="resize-handle bx bx-move-horizontal"
                            onMouseDown={(e) => onResizeMouseDown(e, col.key)}
                          ></i>
                        )}
                      </div>
                    </div>
                  </th>
                );
              })}

              {features.actions && (
                <th
                  className="text-center sticky-action-column vs-th bg-white fw-semibold th-lastChild"
                  style={{ position: "sticky", right: 0, zIndex: 10 }}
                >
                  Action
                </th>
              )}
            </tr>
          </thead>

          <tbody>
            {loading && (
              <tr>
                <td
                  colSpan={
                    visibleColumns.length +
                    (features.selection ? 1 : 0) +
                    (features.actions ? 1 : 0)
                  }
                  className="text-center py-4"
                >
                  Loading...
                </td>
              </tr>
            )}
            {!loading && groupBy && groupedRows && groupedRows.length > 0
              ? groupedRows.map((g, indG) => (
                  <React.Fragment key={g.key}>
                    <tr className="bg-light-primary">
                      <td
                        colSpan={
                          visibleColumns.length +
                          (features.selection ? 1 : 0) +
                          (features.actions ? 1 : 0)
                        }
                        className="text-start pinned pinned-left tr-group"
                      >
                        <strong>{g.key}</strong>
                        {features.aggregation &&
                          Object.keys(g.aggregates).length > 0 && (
                            <small className="ms-3 text-muted  ">
                              {Object.entries(g.aggregates)
                                .map(([k, v]) => `${k}: ${v}`)
                                .join("  |  ")}
                            </small>
                          )}
                      </td>
                    </tr>
                    {g.items.map((row, indG) => renderRow(row, indG))}
                  </React.Fragment>
                ))
              : currentRows.map((row, ind) => renderRow(row, ind))}
          </tbody>
        </table>
      </div>
      {/* Table-End */}

      {features.pagination && (
        <div className="d-flex justify-content-between align-items-center mt-2">
          <div className="d-flex flex-row align-items-center gap-2">
            {features.pageSizeSelector && (
              <select
                className="form-select form-select-sm"
                style={{ width: "80px" }}
                value={pageSize}
                onChange={(e) => setPageSize(Number(e.target.value))}
              >
                {[10, 25, 50, 100].map((n) => (
                  <option key={n} value={n}>
                    {n}
                  </option>
                ))}
              </select>
            )} <small>{totalRows} rows</small>
          </div>
          <div>
            <button
              className="btn btn-sm btn-outline-secondary me-1"
              disabled={page <= 1}
              onClick={() => setPage(page - 1)}
            >
              Prev
            </button>
            <span className="mx-2">
              {page}/{totalPages}
            </span>
            <button
              className="btn btn-sm btn-outline-secondary"
              disabled={page >= totalPages}
              onClick={() => setPage(page + 1)}
            >
              Next
            </button>
          </div>
        </div>
      )}
    </div>
  );

  // render a single row (function hoisted so it can reference visibleColumns)
  function renderRow(row, ind) {
    const isSelected = selected.has(row[rowKey]);
    const isExpanded = expanded.has(row[rowKey]);

    return (
      <React.Fragment key={row[rowKey]}>
        <tr>
          {features.IsNumbering && (
            <td className="text-center align-middle p-2">
              <small className="text-secondry">{ind + 1}</small>
            </td>
          )}
          {/*  Expand toggle next to selection */}
          {features.expand && (
            <td className="text-center align-middle ">
              <button
                type="button"
                className="btn btn-link p-0 border-none text-secondary"
                onClick={() => toggleExpand(row[rowKey])}
              >
                <i
                  className={`bx ${
                    isExpanded ? "bxs-chevron-up" : "bxs-chevron-down"
                  } bx-sm`}
                ></i>
              </button>
            </td>
          )}
          {/*  Selection checkbox (always left) */}
          {features.selection && (
            <td className="text-center align-middle p-2">
              <input
                type="checkbox"
                className="form-check-input"
                checked={isSelected}
                onChange={() => toggleSelect(row[rowKey])}
              />
            </td>
          )}

          {/*  Data columns */}
          {visibleColumns.map((col) => {
            const style = {
              minWidth: col.width || 120,
              width: col.width || undefined,
            };

            if (col.pinned) style.position = "sticky";
            if (col.pinned === "left")
              style.left = `${getLeftOffset(colState, col.key)}px`;
            if (col.pinned === "right")
              style.right = `${getRightOffset(colState, col.key)}px`;

            return (
              <td
                key={col.key}
                style={style}
                className={`${col.className ?? ""} ${
                  col.pinned
                    ? "pinned-left px-3 bg-white pms-grid td pinned"
                    : "px-3"
                }`}
              >
                {col.render ? col.render(row) : row[col.key] ?? ""}
              </td>
            );
          })}

          {/*   Actions column (always right) */}
          {features.actions && (
            <td
              className="text-center sticky-action-column bg-white td-lastChild"
              style={{
                position: "sticky",
                right: 0,
                zIndex: 2,
                width: "1%",
                whiteSpace: "nowrap",
              }}
            >
              {isDropdown ? (
                <div className="dropdown z-2">
                  <button
                    type="button"
                    className="btn btn-icon btn-text-secondary rounded-pill dropdown-toggle hide-arrow p-0"
                    data-bs-toggle="dropdown"
                    aria-expanded="false"
                  >
                    <i
                      className="bx bx-dots-vertical-rounded bx-sm text-muted"
                      data-bs-toggle="tooltip"
                      data-bs-offset="0,8"
                      data-bs-placement="top"
                      data-bs-custom-class="tooltip-dark"
                      title="More Action"
                    ></i>
                  </button>
                  <ul className="dropdown-menu dropdown-menu-end">
                    <li>
                      <a
                        aria-label="click to  View details"
                        className="dropdown-item"
                      >
                        <i className="bx bx-detail me-2"></i>
                        <span className="align-left">View details</span>
                      </a>
                    </li>
                  </ul>
                </div>
              ) : (
                <div
                  className="d-inline-flex justify-content-center align-items-center gap-2"
                  style={{ minWidth: "fit-content", padding: "0 4px" }}
                >
                  {Array.isArray(features.actions)
                    ? features.actions.map((act, i) => (
                        <button
                          key={i}
                          type="button"
                          className="btn btn-link p-0 border-0"
                          title={act.label}
                          onClick={(e) => {
                            e.stopPropagation();
                            act.onClick && act.onClick(row);
                          }}
                        >
                          <i className={`bx ${act.icon}`} />
                        </button>
                      ))
                    : typeof features.actions === "function"
                    ? features.actions(row, toggleExpand)
                    : null}
                </div>
              )}
            </td>
          )}
        </tr>

        {/*  5. Expanded row content (full width) */}
        {isExpanded && renderExpanded && (
          <tr className="table-active">
            <td
              colSpan={
                visibleColumns.length +
                (features.selection ? 1 : 0) +
                (features.expand ? 1 : 0) +
                (features.actions ? 1 : 0)
              }
            >
              {renderExpanded(row)}
            </td>
          </tr>
        )}
      </React.Fragment>
    );
  }
}

// small helpers to compute sticky offsets
function getLeftOffset(colState, key) {
  let offset = 0;
  for (const c of colState
    .filter((c) => c.visible)
    .sort((a, b) => a.order - b.order)) {
    if (c.key === key) return offset;
    if (c.pinned === "left") offset += c.width || 120;
  }
  return offset;
}
function getRightOffset(colState, key) {
  let offset = 0;
  const rightCols = colState
    .filter((c) => c.visible && c.pinned === "right")
    .sort((a, b) => b.order - a.order);
  for (const c of rightCols) {
    if (c.key === key) return offset;
    offset += c.width || 120;
  }
  return offset;
}

/* ColumnVisibilityPanel component (inline) */
function ColumnVisibilityPanel({ columns, onToggle }) {
  return (
    <div className="dropdown">
      <button
        className="btn btn-sm btn-outline-secondary"
        data-bs-toggle="dropdown"
      >
        <i className="bx bx-sm me-2 bx-columns "></i> Columns
      </button>
      <div className="dropdown-menu dropdown-menu-end p-2">
        {columns.map((c) => (
          <div key={c.key} className="form-check">
            <input
              className="form-check-input"
              type="checkbox"
              id={`colvis-${c.key}`}
              checked={c.visible !== false}
              onChange={() => onToggle(c.key)}
            />
            <label className="form-check-label" htmlFor={`colvis-${c.key}`}>
              {c.title}
            </label>
          </div>
        ))}
      </div>
    </div>
  );
}
// For Full screen - class card card-action card-fullscreen
