import { useQuery } from '@tanstack/react-query';
import { useMemo, useState } from 'react';
import {
  listCampusAttendanceConfigs,
  listCampusAttendanceSummaries,
  saveCampusAttendanceConfig,
  saveCampusAttendanceSummary,
} from '@/shared/api/campusAttendance';
import { useCampusCatalog } from '@/business/campuses/hooks';
import { CAMPUS_ATTENDANCE_QUERY_KEYS } from '@/shared/constants/campusAttendance';
import { findCampusByNameOrCode } from '@/shared/constants/campusDisplay';
import { UI_FEEDBACK_CLEAR_DELAY_MS } from '@/shared/constants/ui';
import type {
  CampusAttendanceCampusKey,
  CampusAttendanceListFilter,
} from '@/shared/types/campusAttendance';
import {
  toCampusAttendanceConfigViewModel,
  toCampusAttendanceSummaryMutationDto,
  toCampusAttendanceSummaryViewModel,
} from '@/business/campus-attendance/mappers';
import {
  buildAttendanceEntryInput,
  buildCampusAttendanceScopeModel,
  buildCampusAttendanceStats,
  buildCombinedAttendanceStats,
  buildOverallAttendanceStats,
  getToday,
  getTodayPercentage,
  getWeeklyAverage,
  getWeekEnd,
  getWeekStart,
} from '@/business/campus-attendance/selectors';
import {
  useStaffAttendanceRecords,
  useStaffAttendanceSummary,
} from '@/business/staff-attendance/hooks';
import { saveStaffAttendanceRecord } from '@/shared/api/staffAttendance';
import {
  CAMPUS_ATTENDANCE_PRINT_POPUP_BLOCKED_MESSAGE,
  openCampusAttendancePrintReport,
} from '@/business/campus-attendance/printReport';
import type {
  CampusAttendanceChildStats,
  CampusAttendanceEntryDraft,
  CampusAttendanceEntryInput,
  CampusAttendanceRollupDraft,
  AttendanceRosterStatus,
  StaffAttendanceEntryDraft,
} from '@/business/campus-attendance/types';
import type { CampusId, UserRole } from '@/shared/types/app';
import { getOptionalErrorMessage } from '@/shared/errors/errorMessages';
import { mapApiListRows } from '@/shared/business/apiListRows';
import { useInvalidatingMutation } from '@/shared/business/queryMutations';
import { usePermissions } from '@/shared/app/usePermissions';
import { useScopeContext } from '@/shared/app/scope-context';
import { getScopeChildren } from '@/shared/api/scope';
import type { CampusInfo } from '@/shared/types/app';
import type { TenantChild, TenantLevel } from '@/shared/types/scope';
import { listUsers, type AdminUserRow } from '@/shared/api/users';
import { STAFF_ATTENDANCE_QUERY_KEYS } from '@/shared/constants/staffAttendance';
import { getClass } from '@/shared/api/classes';
import type { StaffAttendanceRecordViewModel } from '@/business/staff-attendance/types';

const EMPTY_CONFIGS: ReturnType<typeof toCampusAttendanceConfigViewModel>[] = [];
const EMPTY_SUMMARIES: ReturnType<typeof toCampusAttendanceSummaryViewModel>[] = [];
const EMPTY_STAFF_RECORDS: readonly StaffAttendanceRecordViewModel[] = [];
const EMPTY_CAMPUSES: CampusInfo[] = [];
const EMPTY_TENANT_CHILDREN: TenantChild[] = [];
const EMPTY_CAMPUS_CHILDREN_BY_PARENT: Readonly<Record<string, readonly TenantChild[]>> = {};
const SCHOOL_TILE_GRADIENTS = [
  'from-emerald-500 to-green-500',
  'from-orange-600 to-amber-500',
  'from-rose-500 to-pink-500',
  'from-violet-500 to-purple-500',
  'from-blue-500 to-cyan-500',
] as const;

export function useCampusAttendanceConfigs(campusKey?: CampusAttendanceCampusKey, enabled = true) {
  return useQuery({
    queryKey: [CAMPUS_ATTENDANCE_QUERY_KEYS.configs, campusKey],
    enabled,
    queryFn: () => mapApiListRows(
      listCampusAttendanceConfigs(campusKey ? { campusKey } : undefined),
      toCampusAttendanceConfigViewModel,
    ),
  });
}

export function useSaveCampusAttendanceConfig() {
  return useInvalidatingMutation({
    mutationFn: (input: { campusKey: CampusAttendanceCampusKey; attendanceLink: string | null }) => (
      saveCampusAttendanceConfig(input.campusKey, { attendance_link: input.attendanceLink })
    ),
    invalidateQueryKey: [CAMPUS_ATTENDANCE_QUERY_KEYS.configs],
  });
}

export function useCampusAttendanceSummaries(filter?: CampusAttendanceListFilter, enabled = true) {
  return useQuery({
    queryKey: [CAMPUS_ATTENDANCE_QUERY_KEYS.summaries, filter],
    enabled,
    queryFn: () => mapApiListRows(
      listCampusAttendanceSummaries(filter),
      toCampusAttendanceSummaryViewModel,
    ),
  });
}

export function useSaveCampusAttendanceSummary() {
  return useInvalidatingMutation({
    mutationFn: (input: CampusAttendanceEntryInput) => saveCampusAttendanceSummary(
      input.campusId,
      input.date,
      toCampusAttendanceSummaryMutationDto(input),
    ),
    invalidateQueryKey: [CAMPUS_ATTENDANCE_QUERY_KEYS.summaries],
  });
}

export function useAttendanceDetailsChildCampuses(
  level: TenantLevel | undefined,
  tenantId: string | undefined,
) {
  return useQuery({
    queryKey: ['attendance-details-child-campuses', level, tenantId],
    enabled: level === 'school' && Boolean(tenantId),
    queryFn: () => getScopeChildren('school', tenantId ?? '', { limit: 500 }),
  });
}

export function useSaveStaffAttendanceRecord() {
  return useInvalidatingMutation({
    mutationFn: (input: StaffAttendanceEntryDraft) => saveStaffAttendanceRecord(
      input.userId,
      input.date,
      { status: input.status, note: input.note.trim() || null },
    ),
    invalidateQueryKeys: [
      [STAFF_ATTENDANCE_QUERY_KEYS.records],
      [STAFF_ATTENDANCE_QUERY_KEYS.summary],
    ],
  });
}

type UseCampusAttendancePageInput = {
  readonly userRole: UserRole;
  readonly userCampus: string;
  readonly userName: string;
};

const emptyEntryDraft = (date: string, campusId: CampusId = ''): CampusAttendanceEntryDraft => ({
  date,
  campusId,
  enrolled: '',
  present: '',
  absent: '',
  tardy: '',
  notes: '',
});

const emptyStaffEntryDraft = (date: string): StaffAttendanceEntryDraft => ({
  date,
  userId: '',
  status: 'present',
  note: '',
});

type AttendanceStatusMap = Record<string, AttendanceRosterStatus>;
type StudentRollupOverrideMap = Record<CampusId, Partial<Pick<
  CampusAttendanceRollupDraft,
  'enrolled' | 'present' | 'absent' | 'tardy' | 'notes'
>>>;

function userDisplayName(user: AdminUserRow): string {
  const fullName = `${user.firstName ?? ''} ${user.lastName ?? ''}`.trim();
  return fullName || user.email;
}

function reconcileAttendanceStatuses(
  current: AttendanceStatusMap,
  userIds: readonly string[],
): AttendanceStatusMap {
  const next: AttendanceStatusMap = {};
  for (const userId of userIds) {
    next[userId] = current[userId] ?? 'present';
  }
  return next;
}

function isBlankRollupRow(row: CampusAttendanceRollupDraft): boolean {
  return !row.enrolled && !row.present && !row.absent && !row.tardy && !row.notes.trim();
}

function toRollupEntryInput(
  row: CampusAttendanceRollupDraft,
  date: string,
): CampusAttendanceEntryInput | null {
  return buildAttendanceEntryInput(
    {
      date,
      campusId: row.campusId,
      enrolled: row.enrolled,
      present: row.present,
      absent: row.absent,
      tardy: row.tardy,
      notes: row.notes,
    },
    row.campusId,
  );
}

function isOfficeStaffUser(user: AdminUserRow, mode: 'organization' | 'school' | 'campus'): boolean {
  const role = user.app_role?.name;
  if (role === 'student' || role === 'guardian') {
    return false;
  }

  if (mode === 'organization') {
    return !user.schoolId && !user.campusId;
  }

  if (mode === 'school') {
    return Boolean(user.schoolId) && !user.campusId;
  }

  return Boolean(user.campusId || user.classId);
}

function isStaffRosterUser(user: AdminUserRow): boolean {
  const role = user.app_role?.name;
  return role !== 'student' && role !== 'guardian';
}

function mapAttendanceRosterUser(user: AdminUserRow) {
  return {
    id: user.id,
    name: userDisplayName(user),
    role: user.app_role?.name ?? null,
  };
}

interface ScopedAttendanceChildren {
  readonly directChildren: readonly TenantChild[];
  readonly campusChildrenByParentId: Readonly<Record<string, readonly TenantChild[]>>;
  readonly campusChildren: readonly TenantChild[];
}

async function listScopedAttendanceChildren(
  level: TenantLevel,
  tenantId: string,
): Promise<ScopedAttendanceChildren> {
  if (level === 'campus') {
    return {
      directChildren: [],
      campusChildrenByParentId: {},
      campusChildren: [],
    };
  }

  if (level === 'school') {
    const response = await getScopeChildren(level, tenantId, { limit: 500 });
    const campusChildren = response.rows.filter((child) => child.level === 'campus');
    return {
      directChildren: campusChildren,
      campusChildrenByParentId: Object.fromEntries(campusChildren.map((campus) => [campus.id, [campus]])),
      campusChildren,
    };
  }

  if (level === 'organization') {
    const schoolsResponse = await getScopeChildren(level, tenantId, { limit: 500 });
    const schools = schoolsResponse.rows.filter((child) => child.level === 'school');
    const campusGroups = await Promise.all(
      schools.map((school) => getScopeChildren('school', school.id, { limit: 500 })),
    );
    const campusChildrenByParentId = Object.fromEntries(
      schools.map((school, index) => [
        school.id,
        campusGroups[index]?.rows.filter((child) => child.level === 'campus') ?? [],
      ]),
    );
    return {
      directChildren: schools,
      campusChildrenByParentId,
      campusChildren: Object.values(campusChildrenByParentId).flat(),
    };
  }

  return {
    directChildren: [],
    campusChildrenByParentId: {},
    campusChildren: [],
  };
}

function percentageFromRecords(
  records: readonly ReturnType<typeof toCampusAttendanceSummaryViewModel>[],
): number | null {
  const enrolled = records.reduce((sum, record) => sum + record.total_enrolled, 0);
  const present = records.reduce((sum, record) => sum + record.total_present, 0);
  return enrolled > 0 ? Number(((present / enrolled) * 100).toFixed(2)) : null;
}

function percentageFromStaffDailySummaries(
  records: readonly { readonly total_staff: number; readonly total_present: number }[],
): number | null {
  const staff = records.reduce((sum, record) => sum + record.total_staff, 0);
  const present = records.reduce((sum, record) => sum + record.total_present, 0);
  return staff > 0 ? Number(((present / staff) * 100).toFixed(2)) : null;
}

export function useCampusAttendancePage({
  userRole,
  userCampus,
  userName,
}: UseCampusAttendancePageInput) {
  const permissions = usePermissions();
  const { tier, effectiveTenant, selectedTenant } = useScopeContext();
  const effectiveTier = selectedTenant ? selectedTenant.level : tier;
  const selectedCampusId = effectiveTier === 'campus' ? effectiveTenant?.id ?? null : null;
  const selectedClassId = effectiveTier === 'class' ? effectiveTenant?.id ?? null : null;
  const roleAccess = {
    isSuperintendent: userRole === 'superintendent',
    isDirector: userRole === 'director',
    isOfficeManager: userRole === 'office_manager',
    canSeeAllCampuses: effectiveTier === 'organization' || effectiveTier === 'school',
    canEnterData: permissions.has('FILL_ATTENDANCE') && (
      effectiveTier === 'organization'
      || effectiveTier === 'school'
      || effectiveTier === 'campus'
      || effectiveTier === 'class'
    ),
    canPrint: userRole === 'superintendent' || userRole === 'director' || userRole === 'office_manager' || permissions.has('READ_STAFF_ATTENDANCE_REPORTS'),
    canReadStaffReports: permissions.has('READ_STAFF_ATTENDANCE_REPORTS'),
  };
  const campusCatalog = useCampusCatalog();
  const classQuery = useQuery({
    queryKey: ['attendance-class-scope', selectedClassId],
    enabled: Boolean(selectedClassId),
    queryFn: () => getClass(selectedClassId ?? ''),
  });
  const classCampusTenantId = classQuery.data?.campusId ?? null;
  const scopedCampusTenantId = selectedCampusId ?? classCampusTenantId;
  const campusInfo = scopedCampusTenantId
    ? campusCatalog.campuses.find((campus) => campus.tenantId === scopedCampusTenantId || campus.id === scopedCampusTenantId)
    : findCampusByNameOrCode(campusCatalog.campuses, userCampus);
  const campusId = campusInfo?.id ?? null;
  const today = getToday();
  const weekStart = getWeekStart(new Date());
  const weekEnd = getWeekEnd(new Date());
  const scopeModel = buildCampusAttendanceScopeModel(
    effectiveTier,
    effectiveTenant,
    campusId,
    campusInfo?.fullName || userCampus,
  );
  const attendanceCampusId = scopeModel.campusId;
  const attendanceSummaryFilter = attendanceCampusId ? { campusKey: attendanceCampusId } : undefined;
  const scopedAttendanceChildrenQuery = useQuery({
    queryKey: ['attendance-scoped-children', effectiveTier, effectiveTenant?.id ?? null],
    enabled: Boolean(
      effectiveTenant?.id
      && (effectiveTier === 'organization' || effectiveTier === 'school'),
    ),
    queryFn: () => listScopedAttendanceChildren(effectiveTier as TenantLevel, effectiveTenant?.id ?? ''),
  });

  const hasAttendanceScope = scopeModel.mode !== 'campus' || Boolean(attendanceCampusId);
  const configsQuery = useCampusAttendanceConfigs(
    attendanceCampusId ?? undefined,
    hasAttendanceScope,
  );
  const summariesQuery = useCampusAttendanceSummaries(
    attendanceSummaryFilter,
    hasAttendanceScope,
  );
  const staffSummaryQuery = useStaffAttendanceSummary(
    { startDate: today, endDate: today },
    roleAccess.canReadStaffReports && hasAttendanceScope,
  );
  const staffRecordsQuery = useStaffAttendanceRecords(
    { limit: 500 },
    roleAccess.canReadStaffReports && hasAttendanceScope,
  );
  const officeStaffQuery = useQuery({
    queryKey: ['attendance-office-staff-users', effectiveTier, effectiveTenant?.id ?? null],
    enabled: roleAccess.canEnterData && hasAttendanceScope,
    queryFn: ({ signal }) => listUsers({ limit: 500, field: 'name', sort: 'asc' }, { signal }),
  });
  const saveConfigMutation = useSaveCampusAttendanceConfig();
  const saveSummaryMutation = useSaveCampusAttendanceSummary();
  const saveStaffAttendanceMutation = useSaveStaffAttendanceRecord();

  const configs = configsQuery.data ?? EMPTY_CONFIGS;
  const attendanceData = summariesQuery.data ?? EMPTY_SUMMARIES;
  const staffSummary = staffSummaryQuery.data ?? null;
  const staffRecords = staffRecordsQuery.data ?? EMPTY_STAFF_RECORDS;
  const officeStaffUsers = useMemo(() => (
    (officeStaffQuery.data?.rows ?? [])
      .filter((user) => isOfficeStaffUser(user, scopeModel.mode) && isStaffRosterUser(user))
      .map(mapAttendanceRosterUser)
  ), [officeStaffQuery.data?.rows, scopeModel.mode]);
  const scopedAttendanceChildren = scopedAttendanceChildrenQuery.data;
  const scopedCampusTenants = scopedAttendanceChildren?.campusChildren;
  const scopedDirectChildren = scopedAttendanceChildren?.directChildren ?? EMPTY_TENANT_CHILDREN;
  const campusChildrenByParentId = scopedAttendanceChildren?.campusChildrenByParentId ?? EMPTY_CAMPUS_CHILDREN_BY_PARENT;
  const scopedCampusOptions = useMemo(() => {
    if (scopeModel.mode === 'campus') {
      return campusInfo ? [campusInfo] : EMPTY_CAMPUSES;
    }

    const scopedTenantIds = new Set((scopedCampusTenants ?? EMPTY_TENANT_CHILDREN).map((campus) => campus.id));
    return campusCatalog.campuses.filter((campus) => (
      campus.tenantId ? scopedTenantIds.has(campus.tenantId) : false
    ));
  }, [campusCatalog.campuses, campusInfo, scopeModel.mode, scopedCampusTenants]);
  const loading = campusCatalog.isLoading
    || (effectiveTier === 'class' && classQuery.isLoading)
    || configsQuery.isLoading
    || summariesQuery.isLoading
    || (roleAccess.canReadStaffReports && staffSummaryQuery.isLoading)
    || (roleAccess.canReadStaffReports && staffRecordsQuery.isLoading)
    || (roleAccess.canEnterData && officeStaffQuery.isLoading)
    || (roleAccess.canSeeAllCampuses && scopedAttendanceChildrenQuery.isLoading);
  const saving = saveConfigMutation.isPending || saveSummaryMutation.isPending || saveStaffAttendanceMutation.isPending;
  const loadError = campusCatalog.error
    ?? (effectiveTier === 'class' ? classQuery.error : null)
    ?? configsQuery.error
    ?? summariesQuery.error
    ?? (roleAccess.canReadStaffReports ? staffSummaryQuery.error : null)
    ?? (roleAccess.canReadStaffReports ? staffRecordsQuery.error : null)
    ?? (roleAccess.canEnterData ? officeStaffQuery.error : null)
    ?? (roleAccess.canSeeAllCampuses ? scopedAttendanceChildrenQuery.error : null);
  const saveError = saveConfigMutation.error ?? saveSummaryMutation.error ?? saveStaffAttendanceMutation.error;
  const [successMessage, setSuccessMessage] = useState('');
  const [printError, setPrintError] = useState<string | null>(null);
  const errorMessage = printError ?? getOptionalErrorMessage(loadError ?? saveError);
  const [editingLink, setEditingLink] = useState<CampusId | null>(null);
  const [linkValue, setLinkValue] = useState('');
  const [showEntryForm, setShowEntryForm] = useState(false);
  const [expandedCampus, setExpandedCampus] = useState<CampusId | null>(null);
  const [entryDraft, setEntryDraft] = useState<CampusAttendanceEntryDraft>(() => emptyEntryDraft(today, attendanceCampusId ?? ''));
  const [staffEntryDraft, setStaffEntryDraft] = useState<StaffAttendanceEntryDraft>(() => emptyStaffEntryDraft(today));
  const [entryError, setEntryError] = useState<string | null>(null);
  const [staffEntryError, setStaffEntryError] = useState<string | null>(null);
  const [studentAttendanceStatusOverrides, setStudentAttendanceStatusOverrides] = useState<AttendanceStatusMap>({});
  const [staffAttendanceStatusOverrides, setStaffAttendanceStatusOverrides] = useState<AttendanceStatusMap>({});
  const [studentRollupOverrides, setStudentRollupOverrides] = useState<StudentRollupOverrideMap>({});

  const campusStats = useMemo(
    () => buildCampusAttendanceStats(campusCatalog.campuses, configs, attendanceData, today, weekStart, weekEnd, staffRecords),
    [attendanceData, campusCatalog.campuses, configs, staffRecords, today, weekEnd, weekStart],
  );
  const visibleCampusStats = useMemo(() => {
    if (scopeModel.mode === 'campus') {
      return attendanceCampusId
        ? campusStats.filter((campus) => campus.id === attendanceCampusId)
        : [];
    }

    const scopedCampusIds = new Set([
      ...scopedCampusOptions.map((campus) => campus.id),
      ...configs.map((config) => config.campus_id),
      ...attendanceData.map((record) => record.campus_id),
    ]);

    return campusStats.filter((campus) => scopedCampusIds.has(campus.id));
  }, [attendanceCampusId, attendanceData, campusStats, configs, scopeModel.mode, scopedCampusOptions]);
  const attendanceChildStats = useMemo((): readonly CampusAttendanceChildStats[] => {
    if (scopeModel.mode === 'campus') {
      return visibleCampusStats.map((campus) => ({
        id: campus.tenantId ?? campus.id,
        level: 'campus',
        mascot: campus.mascot,
        fullName: campus.fullName,
        bgGradient: campus.bgGradient,
        isOnline: campus.isOnline,
        todayPct: campus.todayPct,
        weekAvg: campus.weekAvg,
        recentData: campus.recentData,
        todayRecord: campus.todayRecord,
        childCampusIds: [campus.id],
        recentStaffData: campus.recentStaffData,
        todayStaffRecord: campus.todayStaffRecord,
      }));
    }

    if (scopeModel.mode === 'school') {
      return scopedDirectChildren
        .filter((child) => child.level === 'campus')
        .map((child, index) => {
          const campus = visibleCampusStats.find((item) => item.tenantId === child.id)
            ?? campusStats.find((item) => item.tenantId === child.id);
          return {
            id: child.id,
            level: child.level,
            mascot: campus?.mascot ?? child.name ?? 'Campus',
            fullName: campus?.fullName ?? child.name ?? 'Campus',
            bgGradient: campus?.bgGradient ?? SCHOOL_TILE_GRADIENTS[index % SCHOOL_TILE_GRADIENTS.length],
            isOnline: campus?.isOnline,
            todayPct: campus?.todayPct ?? null,
            weekAvg: campus?.weekAvg ?? null,
            recentData: campus?.recentData ?? [],
            todayRecord: campus?.todayRecord ?? null,
            childCampusIds: campus ? [campus.id] : [],
            recentStaffData: campus?.recentStaffData ?? [],
            todayStaffRecord: campus?.todayStaffRecord ?? null,
          };
        });
    }

    return scopedDirectChildren
      .filter((child) => child.level === 'school')
      .map((child, index) => {
        const childCampuses = (campusChildrenByParentId[child.id] ?? [])
          .map((campusChild) => campusCatalog.campuses.find((campus) => campus.tenantId === campusChild.id))
          .filter((campus): campus is CampusInfo => Boolean(campus));
        const childCampusIds = childCampuses.map((campus) => campus.id);
        const childTodayRecords = attendanceData.filter((record) => (
          childCampusIds.includes(record.campus_id) && record.date === today
        ));
        const childWeekRecords = attendanceData.filter((record) => (
          childCampusIds.includes(record.campus_id)
          && record.date >= weekStart
          && record.date <= weekEnd
        ));
        const childStaffRecords = campusStats
          .filter((campus) => childCampusIds.includes(campus.id))
          .flatMap((campus) => campus.recentStaffData);
        const childTodayStaffRecords = childStaffRecords.filter((record) => record.date === today);
        const todayStaffRecord = childTodayStaffRecords.length > 0
          ? {
              id: `school-staff:${child.id}:${today}`,
              campus_id: null,
              date: today,
              total_staff: childTodayStaffRecords.reduce((sum, record) => sum + record.total_staff, 0),
              total_present: childTodayStaffRecords.reduce((sum, record) => sum + record.total_present, 0),
              total_absent: childTodayStaffRecords.reduce((sum, record) => sum + record.total_absent, 0),
              total_late: childTodayStaffRecords.reduce((sum, record) => sum + record.total_late, 0),
              attendance_percentage: percentageFromStaffDailySummaries(childTodayStaffRecords) ?? 0,
              notes: null,
            }
          : null;
        const weekDays = Array.from(new Set(childWeekRecords.map((record) => record.date)));
        const weekAvg = weekDays.length > 0
          ? Number((weekDays.reduce((sum, day) => (
              sum + (percentageFromRecords(childWeekRecords.filter((record) => record.date === day)) ?? 0)
            ), 0) / weekDays.length).toFixed(2))
          : null;

        return {
          id: child.id,
          level: child.level,
          mascot: child.name ?? 'School',
          fullName: child.name ?? 'School',
          bgGradient: SCHOOL_TILE_GRADIENTS[index % SCHOOL_TILE_GRADIENTS.length],
          todayPct: percentageFromRecords(childTodayRecords),
          weekAvg,
          recentData: childWeekRecords.slice(0, 10),
          todayRecord: null,
          childCampusIds,
          recentStaffData: childStaffRecords.slice(0, 10),
          todayStaffRecord,
        };
      });
  }, [
    attendanceData,
    campusCatalog.campuses,
    campusChildrenByParentId,
    campusStats,
    scopeModel.mode,
    scopedDirectChildren,
    today,
    visibleCampusStats,
    weekEnd,
    weekStart,
  ]);
  const overallStats = useMemo(
    () => buildOverallAttendanceStats(attendanceData, today, weekStart, weekEnd),
    [attendanceData, today, weekEnd, weekStart],
  );
  const combinedStats = useMemo(
    () => buildCombinedAttendanceStats(
      overallStats,
      staffSummary,
      scopeModel.mode === 'campus' ? undefined : attendanceChildStats,
    ),
    [attendanceChildStats, overallStats, scopeModel.mode, staffSummary],
  );
  const myCampusConfig = attendanceCampusId ? configs.find((config) => config.campus_id === attendanceCampusId) : undefined;
  const myCampusData = attendanceCampusId ? attendanceData.filter((record) => record.campus_id === attendanceCampusId) : [];
  const myCampusStats = attendanceCampusId ? visibleCampusStats.find((campus) => campus.id === attendanceCampusId) : undefined;
  const myStaffData = myCampusStats?.recentStaffData ?? [];
  const myTodayPct = attendanceCampusId ? getTodayPercentage(attendanceData, attendanceCampusId, today) : null;
  const myWeekAvg = attendanceCampusId ? getWeeklyAverage(attendanceData, attendanceCampusId, weekStart, weekEnd) : null;
  const selectedEntryCampus = scopedCampusOptions.find((campus) => campus.id === entryDraft.campusId);
  const selectedEntryCampusTenantId = scopeModel.mode === 'campus'
    ? scopedCampusTenantId
    : selectedEntryCampus?.tenantId ?? null;
  const selectedEntryClassId = scopeModel.mode === 'campus' ? selectedClassId : null;
  const attendanceStudentsQuery = useQuery({
    queryKey: ['attendance-student-users', selectedEntryCampusTenantId, selectedEntryClassId],
    enabled: roleAccess.canEnterData
      && showEntryForm
      && Boolean(selectedEntryClassId || selectedEntryCampusTenantId),
    queryFn: ({ signal }) => listUsers({
      app_role: 'student',
      classId: selectedEntryClassId ?? undefined,
      campusId: selectedEntryClassId ? undefined : selectedEntryCampusTenantId ?? undefined,
      limit: 1000,
      field: 'name',
      sort: 'asc',
    }, { signal }),
  });
  const attendanceStudents = useMemo(() => (
    (attendanceStudentsQuery.data?.rows ?? []).map((user) => ({
      id: user.id,
      name: userDisplayName(user),
      role: user.app_role?.name ?? null,
    }))
  ), [attendanceStudentsQuery.data?.rows]);

  const studentAttendanceStatuses = useMemo(
    () => reconcileAttendanceStatuses(
      studentAttendanceStatusOverrides,
      attendanceStudents.map((student) => student.id),
    ),
    [attendanceStudents, studentAttendanceStatusOverrides],
  );
  const staffAttendanceStatuses = useMemo(
    () => reconcileAttendanceStatuses(
      staffAttendanceStatusOverrides,
      officeStaffUsers.map((staff) => staff.id),
    ),
    [officeStaffUsers, staffAttendanceStatusOverrides],
  );
  const studentRollupRows = useMemo((): readonly CampusAttendanceRollupDraft[] => {
    if (scopeModel.mode === 'campus') {
      return [];
    }

    return scopedCampusOptions.map((campus) => {
      const todayRecord = attendanceData.find((record) => (
        record.campus_id === campus.id && record.date === entryDraft.date
      ));
      const override = studentRollupOverrides[campus.id] ?? {};

      return {
        campusId: campus.id,
        campusName: campus.fullName,
        enrolled: override.enrolled ?? (todayRecord ? String(todayRecord.total_enrolled) : ''),
        present: override.present ?? (todayRecord ? String(todayRecord.total_present) : ''),
        absent: override.absent ?? (todayRecord ? String(todayRecord.total_absent) : ''),
        tardy: override.tardy ?? (todayRecord ? String(todayRecord.total_tardy) : ''),
        notes: override.notes ?? todayRecord?.notes ?? '',
        hasRecordedData: Boolean(todayRecord),
      };
    });
  }, [attendanceData, entryDraft.date, scopeModel.mode, scopedCampusOptions, studentRollupOverrides]);
  const showSuccess = (message: string) => {
    setPrintError(null);
    setSuccessMessage(message);
    window.setTimeout(() => setSuccessMessage(''), UI_FEEDBACK_CLEAR_DELAY_MS);
  };

  const updateEntryDraft = (patch: Partial<CampusAttendanceEntryDraft>) => {
    setEntryDraft((currentDraft) => ({ ...currentDraft, ...patch }));
    setEntryError(null);
  };

  const updateStaffEntryDraft = (patch: Partial<StaffAttendanceEntryDraft>) => {
    setStaffEntryDraft((currentDraft) => ({ ...currentDraft, ...patch }));
    setStaffEntryError(null);
  };

  const updateStudentAttendanceStatus = (userId: string, status: AttendanceRosterStatus) => {
    setStudentAttendanceStatusOverrides((currentStatuses) => ({ ...currentStatuses, [userId]: status }));
    setEntryError(null);
  };

  const updateStudentRollupDraft = (
    campusIdToUpdate: CampusId,
    patch: Partial<Pick<CampusAttendanceRollupDraft, 'enrolled' | 'present' | 'absent' | 'tardy' | 'notes'>>,
  ) => {
    setStudentRollupOverrides((currentOverrides) => ({
      ...currentOverrides,
      [campusIdToUpdate]: {
        ...currentOverrides[campusIdToUpdate],
        ...patch,
      },
    }));
    setEntryError(null);
  };

  const updateStaffAttendanceStatus = (userId: string, status: AttendanceRosterStatus) => {
    setStaffAttendanceStatusOverrides((currentStatuses) => ({ ...currentStatuses, [userId]: status }));
    setStaffEntryError(null);
  };

  const setEntryFormVisibility = (nextShowEntryForm: boolean) => {
    if (nextShowEntryForm) {
      setEntryDraft((currentDraft) => ({
        ...currentDraft,
        campusId: attendanceCampusId ?? currentDraft.campusId,
      }));
    }
    setEntryError(null);
    setStaffEntryError(null);
    setShowEntryForm(nextShowEntryForm);
  };

  const handleSaveLink = async (targetCampusId: CampusId) => {
    setPrintError(null);
    await saveConfigMutation.mutateAsync({
      campusKey: targetCampusId,
      attendanceLink: linkValue.trim() || null,
    });
    showSuccess('Link saved successfully!');
    setEditingLink(null);
  };

  const saveStudentAttendance = async (): Promise<boolean> => {
    if (scopeModel.mode !== 'campus') {
      const rowsToSave: CampusAttendanceEntryInput[] = [];
      let hasInvalidRow = false;

      for (const row of studentRollupRows) {
        if (isBlankRollupRow(row)) {
          continue;
        }

        const input = toRollupEntryInput(row, entryDraft.date);
        if (!input) {
          hasInvalidRow = true;
          break;
        }
        rowsToSave.push(input);
      }

      if (hasInvalidRow) {
        setEntryError('Each campus row needs enrolled, present, and absent counts before saving.');
        return false;
      }

      if (rowsToSave.length === 0) {
        setEntryError('Enter at least one campus attendance row before saving.');
        return false;
      }

      for (const input of rowsToSave) {
        await saveSummaryMutation.mutateAsync(input);
      }

      setStudentRollupOverrides({});
      return true;
    }

    const targetCampusId = attendanceCampusId ?? entryDraft.campusId;

    if (!targetCampusId) {
      setEntryError('Select a campus before saving attendance.');
      return false;
    }

    const input = attendanceStudents.length > 0
      ? {
          campusId: targetCampusId,
          date: entryDraft.date,
          totalEnrolled: attendanceStudents.length,
          totalPresent: attendanceStudents.filter((student) => (
            (studentAttendanceStatuses[student.id] ?? 'present') !== 'absent'
          )).length,
          totalAbsent: attendanceStudents.filter((student) => (
            (studentAttendanceStatuses[student.id] ?? 'present') === 'absent'
          )).length,
          totalTardy: attendanceStudents.filter((student) => (
            (studentAttendanceStatuses[student.id] ?? 'present') === 'late'
          )).length,
          notes: entryDraft.notes.trim() || null,
        }
      : buildAttendanceEntryInput(entryDraft, targetCampusId);

    if (!input) {
      setEntryError('Enter enrolled, present, and absent counts before saving.');
      return false;
    }

    await saveSummaryMutation.mutateAsync(input);
    setEntryDraft(emptyEntryDraft(today, attendanceCampusId ?? targetCampusId));
    return true;
  };

  const saveStaffBatchAttendance = async (
    requireStaff: boolean,
    input: Pick<StaffAttendanceEntryDraft, 'date' | 'note'> = staffEntryDraft,
  ): Promise<boolean> => {
    if (officeStaffUsers.length === 0) {
      if (requireStaff) {
        setStaffEntryError('No office staff are available for this scope.');
      }
      return !requireStaff;
    }

    for (const staffUser of officeStaffUsers) {
      await saveStaffAttendanceMutation.mutateAsync({
        date: input.date,
        userId: staffUser.id,
        status: staffAttendanceStatuses[staffUser.id] ?? 'present',
        note: input.note,
      });
    }

    setStaffEntryDraft(emptyStaffEntryDraft(today));
    return true;
  };

  const handleSubmitEntry = async () => {
    setPrintError(null);

    const saved = await saveStudentAttendance();
    if (!saved) {
      return;
    }

    showSuccess('Student attendance saved!');
    setShowEntryForm(false);
  };

  const handleSubmitStaffEntry = async () => {
    setPrintError(null);

    if (!staffEntryDraft.userId) {
      setStaffEntryError('Select an office staff member before saving attendance.');
      return;
    }

    await saveStaffAttendanceMutation.mutateAsync(staffEntryDraft);
    showSuccess('Office staff attendance saved!');
    setStaffEntryDraft(emptyStaffEntryDraft(today));
  };

  const handleSubmitStaffBatch = async () => {
    setPrintError(null);

    const saved = await saveStaffBatchAttendance(true);
    if (!saved) {
      return;
    }

    showSuccess('Staff attendance saved!');
  };

  const handleSubmitAttendanceForm = async () => {
    setPrintError(null);

    const studentSaved = await saveStudentAttendance();
    if (!studentSaved) {
      return;
    }

    const staffSaved = await saveStaffBatchAttendance(false, {
      date: entryDraft.date,
      note: staffEntryDraft.note,
    });
    if (!staffSaved) {
      return;
    }

    showSuccess('Attendance saved!');
    setShowEntryForm(false);
  };

  const handlePrint = () => {
    const campusesToPrint = roleAccess.canSeeAllCampuses
      ? visibleCampusStats
      : campusStats.filter((campus) => campus.id === attendanceCampusId);
    const reportTitle = roleAccess.canSeeAllCampuses
      ? `${scopeModel.reportLabel} Attendance Report`
      : `${campusInfo?.fullName || userCampus} Attendance Report`;
    const printTodayRecords = roleAccess.canSeeAllCampuses
      ? overallStats.todayRecords
      : attendanceData.filter((record) => record.campus_id === attendanceCampusId && record.date === today);
    const printWeekRecords = roleAccess.canSeeAllCampuses
      ? overallStats.weekRecords
      : attendanceData.filter((record) => record.campus_id === attendanceCampusId && record.date >= weekStart && record.date <= weekEnd);

    const printResult = openCampusAttendancePrintReport({
      input: {
        reportTitle,
        generatedByName: userName,
        generatedByRole: `${userRole.charAt(0).toUpperCase()}${userRole.slice(1)}`,
        today,
        weekStart,
        campusesToPrint,
        printTodayRecords,
        printWeekRecords,
        staffSummary,
      },
    });

    if (!printResult.ok) {
      setPrintError(CAMPUS_ATTENDANCE_PRINT_POPUP_BLOCKED_MESSAGE);
      return;
    }

    setPrintError(null);
  };

  return {
    state: {
      roleAccess,
      scopeModel,
      campusInfo,
      campusId: attendanceCampusId,
      today,
      weekStart,
      weekEnd,
      configs,
      attendanceData,
      staffRecords,
      loading,
      saving,
      errorMessage,
      successMessage,
      editingLink,
      linkValue,
      showEntryForm,
      expandedCampus,
      entryDraft,
      entryError,
      staffEntryDraft,
      staffEntryError,
      officeStaffUsers,
      staffAttendanceStatuses,
      studentRollupRows,
      attendanceStudents,
      studentAttendanceStatuses,
      attendanceStudentsLoading: attendanceStudentsQuery.isLoading,
      scopedCampusOptions,
      campusStats: visibleCampusStats,
      attendanceChildStats,
      overallStats,
      combinedStats,
      staffSummary: {
        summary: staffSummary,
        loading: staffSummaryQuery.isLoading,
        error: staffSummaryQuery.error,
      },
      myCampusConfig,
      myCampusData,
      myStaffData,
      myTodayPct,
      myWeekAvg,
      userCampus,
    },
    actions: {
      setEditingLink,
      setLinkValue,
      setShowEntryForm: setEntryFormVisibility,
      setExpandedCampus,
      updateEntryDraft,
      updateStaffEntryDraft,
      updateStudentAttendanceStatus,
      updateStudentRollupDraft,
      updateStaffAttendanceStatus,
      handleSaveLink,
      handleSubmitEntry,
      handleSubmitStaffEntry,
      handleSubmitStaffBatch,
      handleSubmitAttendanceForm,
      handlePrint,
    },
  };
}
