import { queryOptions } from "@tanstack/react-query";
import apiFetch from "../../utils/api";
import { jsonQuery } from "../apiAdapter";

export interface PlanUser {
  id: number;
  full_name: string;
  username: string;
  role_name: string | null;
  is_active: boolean;
  has_attendance_record: boolean;
}

export interface ResolvedCell {
  source: "entry" | "override";
  entryId: number | null;
  overrideId: number | null;
  user_id: number;
  shift_date: string;
  project_id: number | null;
  /** Project label resolved server-side (see resolveGrid). Lets the UI show
   * the project without depending on the capped/permission-gated projects
   * list. Null when the cell has no project. */
  project_number: string | null;
  project_name: string | null;
  category: string;
  note: string;
  rangeFrom: string | null;
  rangeTo: string | null;
}

export interface PlanCategory {
  id: number;
  key: string;
  label: string;
  color: string;
  sort_order: number;
  is_active: boolean;
}

export const planCategoriesOptions = () =>
  queryOptions({
    queryKey: ["plan", "categories"],
    queryFn: () => jsonQuery<PlanCategory[]>("/api/admin/plan/categories"),
  });

/** Build a key → category lookup from the categories list. */
export function categoryMap(
  categories: PlanCategory[] | undefined,
): Record<string, PlanCategory> {
  const map: Record<string, PlanCategory> = {};
  for (const c of categories ?? []) map[c.key] = c;
  return map;
}

/** Czech label for a plan category key, resolved from the loaded categories
 * map, falling back to the raw key. The `map` arg is optional so callers not
 * yet threading categories still compile (they show the raw key until wired). */
export function planCategoryLabel(
  key: string,
  map?: Record<string, PlanCategory>,
): string {
  return map?.[key]?.label ?? key;
}

/** Build the display label for a cell's project, preferring the server-
 * embedded fields. Returns null when the cell has no project. */
export function cellProjectLabel(cell: {
  project_number: string | null;
  project_name: string | null;
}): string | null {
  if (!cell.project_number && !cell.project_name) return null;
  if (cell.project_number && cell.project_name) {
    return `${cell.project_number} — ${cell.project_name}`;
  }
  return cell.project_number ?? cell.project_name;
}

export interface GridData {
  view: "week" | "month";
  date_from: string;
  date_to: string;
  users: PlanUser[];
  cells: Record<number, Record<string, ResolvedCell[]>>;
}

export const planKeys = {
  all: ["plan"] as const,
  grid: (dateFrom: string, dateTo: string, view: "week" | "month") =>
    ["plan", "grid", { dateFrom, dateTo, view }] as const,
  entries: (userId: number | null, dateFrom: string, dateTo: string) =>
    ["plan", "entries", { userId, dateFrom, dateTo }] as const,
  overrides: (userId: number | null, dateFrom: string, dateTo: string) =>
    ["plan", "overrides", { userId, dateFrom, dateTo }] as const,
  users: () => ["plan", "users"] as const,
};

export const gridQuery = (
  dateFrom: string,
  dateTo: string,
  view: "week" | "month",
) =>
  queryOptions({
    queryKey: planKeys.grid(dateFrom, dateTo, view),
    queryFn: () =>
      jsonQuery<GridData>(
        `/api/admin/plan/grid?date_from=${dateFrom}&date_to=${dateTo}&view=${view}`,
      ),
  });

export const usersQuery = () =>
  queryOptions({
    queryKey: planKeys.users(),
    queryFn: () => jsonQuery<PlanUser[]>("/api/admin/plan/users"),
  });
