export const ASSIGNEES_STATUS_REPORT = 'Asset Maintenance Assignees Status Count';

export type AssigneesStatusRow = Record<string, string | number | boolean | null | undefined>;

export type AssigneesStatusFilters = {
  from_date?: string;
  to_date?: string;
  company?: string;
  site_name?: string;
};

export type AssigneesStatusChartData = {
  labels: string[];
  datasets: Array<{ name: string; values: number[]; colors?: string[] }>;
  type: 'Bar';
  rawRows: AssigneesStatusRow[];
};

const STATUS_GROUPS = [
  { label: 'Planned', color: '#6366F1', fields: ['pending', 'Pending'] },
  {
    label: 'Completed',
    color: '#10B981',
    fields: ['completed_on_time', 'completed_within_time', 'delay_in_completion'],
  },
  { label: 'Cancelled', color: '#F59E0B', fields: ['cancelled', 'Cancelled'] },
  { label: 'Overdue', color: '#EF4444', fields: ['overdue', 'Overdue'] },
] as const;

export const getRowNumericField = (row: AssigneesStatusRow, ...keys: string[]): number => {
  for (const key of keys) {
    const value = row[key];
    if (value == null || value === '') continue;
    const parsed = Number(value);
    if (Number.isFinite(parsed)) return parsed;
  }
  return 0;
};

export const getAssigneeName = (row: AssigneesStatusRow): string => {
  const name =
    row['Assigned To'] ||
    row.assign_to_name ||
    row.assigned_to ||
    row.assign_to ||
    'Unknown';
  return String(name).trim() || 'Unknown';
};

export const getAssigneePlanned = (row: AssigneesStatusRow): number =>
  getRowNumericField(row, 'pending', 'Pending');

export const getAssigneeCompleted = (row: AssigneesStatusRow): number =>
  getRowNumericField(row, 'completed_on_time') +
  getRowNumericField(row, 'completed_within_time') +
  getRowNumericField(row, 'delay_in_completion');

export const getAssigneeCancelled = (row: AssigneesStatusRow): number =>
  getRowNumericField(row, 'cancelled', 'Cancelled');

export const getAssigneeOverdue = (row: AssigneesStatusRow): number =>
  getRowNumericField(row, 'overdue', 'Overdue');

export const getAssigneeTotal = (row: AssigneesStatusRow): number =>
  getAssigneePlanned(row) +
  getAssigneeCompleted(row) +
  getAssigneeCancelled(row) +
  getAssigneeOverdue(row);

export const buildAssigneesStatusChartData = (
  rows: AssigneesStatusRow[]
): AssigneesStatusChartData | null => {
  const dataRows = rows.filter(row => row && !row.is_total_row);
  if (!dataRows.length) return null;

  const statusTotals = STATUS_GROUPS.map(({ label, color, fields }) => ({
    label,
    color,
    total: dataRows.reduce(
      (sum, row) => sum + fields.reduce((fieldSum, field) => fieldSum + getRowNumericField(row, field), 0),
      0
    ),
  }));

  return {
    labels: statusTotals.map(item => item.label),
    datasets: [
      {
        name: 'Tasks',
        values: statusTotals.map(item => item.total),
        colors: statusTotals.map(item => item.color),
      },
    ],
    type: 'Bar',
    rawRows: dataRows,
  };
};

export const runAssigneesStatusReport = async (
  filters: AssigneesStatusFilters
): Promise<AssigneesStatusRow[]> => {
  const csrfToken =
    typeof window !== 'undefined' && (window as any).csrf_token && (window as any).csrf_token !== 'None'
      ? (window as any).csrf_token
      : null;

  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
    Accept: 'application/json',
  };
  if (csrfToken) {
    headers['X-Frappe-CSRF-Token'] = csrfToken;
  }

  const cleanedFilters: Record<string, string> = {};
  Object.entries(filters).forEach(([key, value]) => {
    if (value) cleanedFilters[key] = value;
  });

  const response = await fetch('/api/method/frappe.desk.query_report.run', {
    method: 'POST',
    headers,
    credentials: 'include',
    body: JSON.stringify({
      report_name: ASSIGNEES_STATUS_REPORT,
      filters: cleanedFilters,
      ignore_prepared_report: 1,
    }),
  });

  const payload = await response.json();
  if (!response.ok) {
    throw new Error(payload?.message || payload?.exc || 'Failed to load assignees status report');
  }

  const result = payload?.message?.result || payload?.message?.message?.result || [];
  if (!Array.isArray(result)) return [];

  return result.filter(row => row && !row.is_total_row);
};

export const fetchAssigneesStatusChart = async (
  filters: AssigneesStatusFilters
): Promise<AssigneesStatusChartData | null> => {
  const rows = await runAssigneesStatusReport(filters);
  return buildAssigneesStatusChartData(rows);
};
