import moment from "moment";

// types.ts (Optional but recommended)
export interface Cell {
  index: number;
  value?: string | number;
}

export interface Row {
  index: number;
  cells: Cell[];
}

export interface ResourceAllocation {
  allocation: Record<string, number>;
  detailedAllocation: Record<string, any>;
  resourceType: string;
  role: string;
  gradeId: number | string | null;
  employeeName: string;
  taskName: string;
  resourceId: string;
  taskId: number | null;
}

/**
 * Transforms the spreadsheet-like ds1 structure into the flat ds2 allocation list.
 */
export function transformDs1ToDs2(ds1: any[]){
  if (!ds1 || ds1.length === 0) return [];

  const rows = ds1[0].rows;
  const ds2: any[] = [];

  // 1. Map columns for months from header (Index 0)
  const monthMap: Record<number, string> = {};
  rows[0].cells.forEach((cell: any) => {
    if (cell.index >= 5 && typeof cell.value === "string") {
      monthMap[cell.index] = cell.value.replace(/\s+/g, "_");
    }
  });

  // Variables to track the current task context
  let currentTaskName = "";
  let currentTaskId: number | null = null;

  rows.slice(1).forEach((row: any) => {
    const cells = row.cells;

    // Extract Index 0 (Column A) - Used for Task context or Subtotal checks
    const colA = cells.find((c: any) => c.index === 0)?.value?.toString() || "";
    // Extract Index 1 (Column B) - Staff/Employee
    const colB = cells.find((c: any) => c.index === 1)?.value?.toString() || "";
    

    // --- LOGIC A: Detect Group Header (Task Info) ---
    // If it starts with '˄', it defines the Task for the following rows
    if (colA.startsWith("˄")) {
      currentTaskName = colA.replace("˄", "").trim();
      // Using row index or a hash as a placeholder for taskId if not explicitly in ds1
      currentTaskId = cells[1]?.textAlign; // Example heuristic for taskId
      return;
    }

    // --- LOGIC B: Skip Totals/Subtotals ---
    if (colA.toLowerCase().includes("subtotal") || colA.toLowerCase() === "total" || !colB) {
      return;
    }

    // --- LOGIC C: Process Resource Row ---
    // Handle "Abhishek Show - K2408137" splitting
    let employeeName = colB;
    let resourceId = "";

    if (colB.includes("-")) {
      const parts = colB.split("-");
      employeeName = parts[0].trim();
      resourceId = parts[1].trim();
    }

    const record: any = {
      allocation: {},
      detailedAllocation: {},
      resourceType: "Named",
      role: cells.find((c: any) => c.index === 3)?.value || "",
      gradeId: cells.find((c: any) => c.index === 2)?.value || null,
      employeeName: employeeName,
      resourceId: resourceId,
      taskName: currentTaskName, // Taken from the last seen Group Header
      taskId: currentTaskId,     // Taken from the last seen Group Header
    };

    // Extract allocations
    cells.forEach((cell: any) => {
      if (monthMap[cell.index]) {
        const monthKey = monthMap[cell.index];
        if (typeof cell.value === "number") {
          record.allocation[monthKey] = cell.value;
        }
        record.detailedAllocation[monthKey] = {};
      }
    });

    ds2.push(record);
  });

  return ds2;
}

export function transformDataToSheet(ds2: any[]) {
  if (!ds2 || ds2.length === 0) return {};

  return ds2.reduce((acc: any, curr: any) => {
    const { taskName, employeeName, resourceId, gradeId, role, allocation, id } = curr;

    // Initialize task group if it doesn't exist
    if (!acc[taskName]) {
      acc[taskName] = [];
    }

    // Push simplified resource object
    acc[taskName].push({
      staff: `${employeeName} - ${resourceId}`,
      grade: gradeId,
      role: role,
      id: id,
      ...allocation // Spreads monthwise FTE (e.g., Dec_2025: 0.12)
    });

    return acc;
  }, {});
}

export async function addMultipleRows(spreadsheetRef: any, rows: number, tasks: {}, taskCells: {}, taskMonths: []) {

  let newTaskCellsWithHeader = { headerTitle: "", taskCells: taskCells };
  for (var t = 0; t < tasks.length; t++) {



    console.log("Batching multiple row addition");
    for (var r = 0; r < rows; r++) {
      let subtotalRow = 0;
      for (var tc of newTaskCellsWithHeader.taskCells) {
        if (tc.headerTitle == tasks[t]) {
          subtotalRow = tc.subtotalRow;
          break;
        }
      }
      if (subtotalRow == 0) {
        continue;
      }


      // await addRowBelow(spreadsheetRef, {row: , taskCells: taskCells})
      const ss = spreadsheetRef.current;
      const sheet = ss.activeSheet();
      const row = subtotalRow - 2;


      // Insert row below
      sheet.insertRow(row + 1);


      const data = (await ss.saveJSON())?.sheets;
      const rows = data[0].rows
      let newRows = []
      rows.forEach((element, i) => {
        if (i == row) {
          let elm = structuredClone(element)
          const frm = element.cells[4].formula;
          element.cells[4].value = 0;
          element.cells[4].formula = frm?.replaceAll(i + 1 + "", i + 2 + "")
          // element.cells[4].formula = frm.replaceAll(row+1+"",row+2+"" )
          if (element.cells[5].validation)
            element.cells[5].validation.from = element.cells[5].validation.from.replaceAll(row + 1 + "", row + 2 + "")

          for (var t in taskMonths) {
            element.cells[5 + parseInt(t)].value = ""
            element.cells[5 + parseInt(t)].enable = false
          }

          newRows.push(elm);
        }
        if (i >= row) {
          element.index = i + 1;
          if (i == row) {
            element.cells[1].value = ""
            element.cells[2].value = ""
            element.cells[3].value = ""
          }

        }
        newRows.push(element);     // 👈 keep existing row
      });
      data[0].rows = newRows
      ss.fromJSON({ sheets: data })

      const totalCols = sheet._columns._count;

      newTaskCellsWithHeader = await updateHeaderAndSubtotal(newTaskCellsWithHeader.taskCells, row)
      // setTaskCells(newTaskCellsWithHeader.taskCells)





      // subtotalRow++;
    }

    for (var i of newTaskCellsWithHeader.taskCells) {
      const sheet = spreadsheetRef.current.activeSheet();
      const monthsArr = [4]
      taskMonths.forEach((t, i) => { monthsArr.push(i + 5) })
      // if(i.headerTitle = taskName){
      monthsArr.forEach((t) => {

        const cell = sheet.range(i.subtotalRow - 1, t);
        let sumF = ""
        for (let v = i.headerRow + 1; v < i.subtotalRow; v++) {
          if (sumF == "") {
            sumF += columnName(t) + v;
            continue
          }
          sumF += "," + columnName(t) + v
        }
        // sumF.slice(sumF.lastIndexOf(","), sumF.length)
        // let formula = cell.formula();
        // formula = formula.replaceAll(formula.charAt(5),Number(formula.charAt(5))-1)
        cell.formula(`SUM(${sumF})`);


      })
      // const row = sheet.range(i.subtotalRow, c);
      // cells = .map(r => `E${r}`).join(",")
      // }
    }

  }
  return newTaskCellsWithHeader;

}

export async function updateHeaderAndSubtotal(taskCells = [], row = 0) {
  // 1. Find the target section
  const targetIndex = taskCells.findIndex(
    ({ headerRow, subtotalRow }) => row >= headerRow && row <= subtotalRow
  );

  // If no section found, return the original data structure
  if (targetIndex === -1) {
    return { headerTitle: null, taskCells };
  }

  const targetName = taskCells[targetIndex].headerTitle;

  // 2. Map through the array to create a NEW updated version
  const updated = taskCells.map((item, index) => {
    // If it's the section we are currently in, increment the subtotal
    if (index === targetIndex) {
      return {
        ...item,
        subtotalRow: item.subtotalRow + 1,
      };
    }

    // If it's a section AFTER the current one, shift everything down by 1
    if (index > targetIndex) {
      return {
        ...item,
        headerRow: item.headerRow + 1,
        subtotalRow: item.subtotalRow + 1,
      };
    }

    // Otherwise, leave it as is
    return item;
  });

  return { headerTitle: targetName, taskCells: updated };
}

export function getTaskTimeline(tasks: any[]) {
  if (!tasks || tasks.length === 0) return [];

  // 1. Calculate End Dates for all tasks
  const tasksWithEnds = tasks.map(t => {
    const taskStart = moment(t.taskStart);
    const taskDuration = parseFloat(t.taskDuration);

    // Calculate logical end date
    let endDate = taskStart.clone().add(Math.floor(taskDuration), "months");
    const daysInLastMonth = endDate.daysInMonth();

    endDate.subtract(1, "day");
    endDate.add(daysInLastMonth * (taskDuration % 1), "days");

    if (endDate.isBefore(taskStart)) endDate = taskStart.clone();

    return {
      ...t,
      start: taskStart,
      end: endDate
    };
  });

  // 2. Define the global range based on tasks
  const minStart = moment.min(tasksWithEnds.map(t => t.start)).clone().startOf('month');
  const maxEnd = moment.max(tasksWithEnds.map(t => t.end)).clone().endOf('month');

  const timeline = [];
  let currentMoment = minStart.clone();

  // 3. Iterate through each month
  while (currentMoment.isSameOrBefore(maxEnd, 'month')) {
    const monthStart = currentMoment.clone().startOf('month');
    const monthEnd = currentMoment.clone().endOf('month');
    const daysInMonth = currentMoment.daysInMonth();

    // Filter and calculate duration for tasks in THIS specific month
    const monthTasks = tasksWithEnds
      .filter(t => t.start.isSameOrBefore(monthEnd) && t.end.isSameOrAfter(monthStart))
      .map(t => {
        const overlapStart = moment.max(t.start, monthStart);
        const overlapEnd = moment.min(t.end, monthEnd);

        const overlapDays = overlapEnd.diff(overlapStart, 'days') + 1;
        const taskMonthDuration = parseFloat((overlapDays / daysInMonth).toFixed(2));

        return {
          taskName: t.taskName,
          taskDuration: taskMonthDuration
        };
      });

    // Generate the month name string as requested: "Jan 2024"
    const dateObj = currentMoment.toDate();
    const monthName = dateObj.toLocaleString("en-US", { month: "long" });
    const year = dateObj.getFullYear();

    timeline.push({
      month: `${monthName.slice(0, 3)} ${year}`,
      tasks: monthTasks
    });

    currentMoment.add(1, 'month');
  }

  return timeline;
}

function columnName(n) {
  let s = "";
  while (n >= 0) {
    s = String.fromCharCode((n % 26) + 65) + s;
    n = Math.floor(n / 26) - 1;
  }
  return s;
}