import { describe, expect, it } from 'vitest';
import {
  buildAttendanceEntryInput,
  buildCampusAttendanceScopeModel,
  buildCampusAttendanceStats,
  buildCombinedAttendanceHistoryRows,
  buildCombinedAttendanceStats,
  buildOverallAttendanceStats,
  buildStaffAttendanceDailySummaries,
  getWeekEnd,
  getWeekStart,
} from '@/business/campus-attendance/selectors';
import type {
  CampusAttendanceChildStats,
  CampusAttendanceEntryDraft,
  CampusAttendanceSummaryViewModel,
} from '@/business/campus-attendance/types';
import type { CampusInfo } from '@/shared/types/app';
import type { StaffAttendanceRecordViewModel } from '@/business/staff-attendance/types';

const summaries: readonly CampusAttendanceSummaryViewModel[] = [
  {
    id: 'summary-1',
    campus_id: 'tigers',
    date: '2026-06-08',
    total_enrolled: 100,
    total_present: 90,
    total_absent: 10,
    total_tardy: 3,
    attendance_percentage: 90,
    recorded_by: 'director-1',
    notes: null,
  },
  {
    id: 'summary-2',
    campus_id: 'gators',
    date: '2026-06-08',
    total_enrolled: 50,
    total_present: 40,
    total_absent: 10,
    total_tardy: 1,
    attendance_percentage: 80,
    recorded_by: 'director-1',
    notes: null,
  },
  {
    id: 'summary-3',
    campus_id: 'tigers',
    date: '2026-06-09',
    total_enrolled: 100,
    total_present: 95,
    total_absent: 5,
    total_tardy: 2,
    attendance_percentage: 95,
    recorded_by: 'director-1',
    notes: null,
  },
];

const staffRecords: readonly StaffAttendanceRecordViewModel[] = [
  {
    id: 'staff-1',
    userId: 'user-1',
    date: '2026-06-08',
    status: 'present',
    note: null,
    userName: 'Sarah Williams',
    userRole: 'Director',
    campusId: 'tenant-tigers',
  },
  {
    id: 'staff-2',
    userId: 'user-2',
    date: '2026-06-08',
    status: 'late',
    note: 'Traffic',
    userName: 'Lisa Park',
    userRole: 'Office Manager',
    campusId: 'tenant-tigers',
  },
  {
    id: 'staff-3',
    userId: 'user-3',
    date: '2026-06-08',
    status: 'absent',
    note: null,
    userName: 'Marcus Davis',
    userRole: 'Support Staff',
    campusId: 'tenant-tigers',
  },
];

const campusInfo: readonly CampusInfo[] = [
  {
    id: 'tigers',
    tenantId: 'tenant-tigers',
    mascot: 'Tigers',
    fullName: 'Tigers Campus',
    color: 'bg-orange-500',
    bgGradient: 'from-orange-500 to-amber-500',
    borderColor: 'border-orange-500/30',
    textColor: 'text-orange-400',
    bgLight: 'bg-orange-500/10',
    description: 'Tigers campus',
    isOnline: true,
  },
];

describe('campus attendance selectors', () => {
  it('calculates Monday and Friday boundaries for a midweek date', () => {
    const date = new Date('2026-06-10T12:00:00Z');

    expect(getWeekStart(date)).toBe('2026-06-08');
    expect(getWeekEnd(date)).toBe('2026-06-12');
  });

  it('builds validated attendance input and normalizes optional notes', () => {
    const draft: CampusAttendanceEntryDraft = {
      date: '2026-06-08',
      campusId: 'tigers',
      enrolled: '25',
      present: '21',
      absent: '4',
      tardy: '',
      notes: '  ',
    };

    expect(buildAttendanceEntryInput(draft, 'tigers')).toEqual({
      campusId: 'tigers',
      date: '2026-06-08',
      totalEnrolled: 25,
      totalPresent: 21,
      totalAbsent: 4,
      totalTardy: 0,
      notes: null,
    });
  });

  it('rejects attendance input without a positive enrollment count', () => {
    const draft: CampusAttendanceEntryDraft = {
      date: '2026-06-08',
      campusId: 'tigers',
      enrolled: '0',
      present: '0',
      absent: '0',
      tardy: '0',
      notes: 'Closed',
    };

    expect(buildAttendanceEntryInput(draft, 'tigers')).toBeNull();
  });

  it('aggregates daily and weekly attendance percentages across campuses', () => {
    expect(
      buildOverallAttendanceStats(summaries, '2026-06-08', '2026-06-08', '2026-06-12'),
    ).toMatchObject({
      todayEnrolled: 150,
      todayPresent: 130,
      todayPct: 86.67,
      weekPct: 90.83,
    });
  });

  it('builds scope-aware attendance titles and descriptions', () => {
    expect(
      buildCampusAttendanceScopeModel(
        'organization',
        { level: 'organization', id: 'org-1', name: 'Demo Academy', logo: null },
        null,
        'Tigers Campus',
      ),
    ).toMatchObject({
      mode: 'organization',
      title: 'Organization Attendance',
      reportLabel: 'Organization',
    });

    expect(
      buildCampusAttendanceScopeModel(
        'school',
        { level: 'school', id: 'school-1', name: 'Demo Academy North', logo: null },
        null,
        'Tigers Campus',
      ),
    ).toMatchObject({
      mode: 'school',
      title: 'School Attendance',
      reportLabel: 'School',
    });

    expect(
      buildCampusAttendanceScopeModel('campus', null, 'campus-1', 'Tigers Campus'),
    ).toMatchObject({
      mode: 'campus',
      title: 'Campus Attendance',
      reportLabel: 'Campus',
      campusId: 'campus-1',
    });

    expect(
      buildCampusAttendanceScopeModel(
        'class',
        { level: 'class', id: 'class-1', name: 'Tigers Homeroom 1', logo: null },
        'campus-1',
        'Tigers Campus',
      ),
    ).toMatchObject({
      mode: 'campus',
      title: 'Classroom Attendance',
      reportLabel: 'Classroom',
      campusId: 'campus-1',
    });
  });

  it('combines student attendance aggregates with staff attendance summary', () => {
    const overallStats = buildOverallAttendanceStats(summaries, '2026-06-08', '2026-06-08', '2026-06-12');

    expect(
      buildCombinedAttendanceStats(overallStats, {
        staffCount: 12,
        recordsCount: 10,
        present: 8,
        late: 1,
        absent: 1,
      }),
    ).toEqual({
      studentTodayPct: 86.67,
      studentWeekPct: 90.83,
      staffTodayPct: 75,
      combinedTodayPct: 85.8,
    });
  });

  it('counts missing child attendance reports as incomplete in aggregate percentages', () => {
    const overallStats = buildOverallAttendanceStats(summaries, '2026-06-08', '2026-06-08', '2026-06-12');
    const childStats: readonly CampusAttendanceChildStats[] = [
      {
        id: 'school-1',
        level: 'school',
        mascot: 'North',
        fullName: 'Demo Academy North',
        bgGradient: 'from-emerald-500 to-green-500',
        todayPct: 100,
        weekAvg: 100,
        recentData: [],
        todayRecord: null,
        childCampusIds: ['tigers'],
        recentStaffData: [],
        todayStaffRecord: null,
      },
      {
        id: 'school-2',
        level: 'school',
        mascot: 'South',
        fullName: 'Demo Academy South',
        bgGradient: 'from-orange-600 to-amber-500',
        todayPct: null,
        weekAvg: null,
        recentData: [],
        todayRecord: null,
        childCampusIds: ['gators'],
        recentStaffData: [],
        todayStaffRecord: null,
      },
    ];

    expect(buildCombinedAttendanceStats(overallStats, null, childStats)).toEqual({
      studentTodayPct: 50,
      studentWeekPct: 50,
      staffTodayPct: null,
      combinedTodayPct: 50,
    });
  });

  it('builds daily staff attendance summaries by campus and date', () => {
    expect(buildStaffAttendanceDailySummaries(staffRecords)).toEqual([
      {
        id: 'staff:tenant-tigers:2026-06-08',
        campus_id: 'tenant-tigers',
        date: '2026-06-08',
        total_staff: 3,
        total_present: 2,
        total_absent: 1,
        total_late: 1,
        attendance_percentage: 66.67,
        notes: 'Traffic',
      },
    ]);
  });

  it('attaches staff attendance history to campus attendance stats', () => {
    const [campus] = buildCampusAttendanceStats(
      campusInfo,
      [],
      summaries,
      '2026-06-08',
      '2026-06-08',
      '2026-06-12',
      staffRecords,
    );

    expect(campus?.todayRecord?.total_enrolled).toBe(100);
    expect(campus?.todayStaffRecord).toMatchObject({
      total_staff: 3,
      total_present: 2,
      total_absent: 1,
      attendance_percentage: 66.67,
    });
    expect(campus?.recentStaffData).toHaveLength(1);
  });

  it('builds combined attendance history with students, staff, and total rows per date', () => {
    expect(buildCombinedAttendanceHistoryRows([summaries[0]], buildStaffAttendanceDailySummaries(staffRecords))).toEqual([
      {
        id: '2026-06-08:students',
        date: '2026-06-08',
        group: 'students',
        label: 'Students',
        total: 100,
        present: 90,
        absent: 10,
        late: 3,
        attendancePercentage: 90,
        notes: null,
      },
      {
        id: '2026-06-08:staff',
        date: '2026-06-08',
        group: 'staff',
        label: 'Staff',
        total: 3,
        present: 2,
        absent: 1,
        late: 1,
        attendancePercentage: 66.67,
        notes: 'Traffic',
      },
      {
        id: '2026-06-08:total',
        date: '2026-06-08',
        group: 'total',
        label: 'Total',
        total: 103,
        present: 92,
        absent: 11,
        late: 4,
        attendancePercentage: 89.32,
        notes: 'Traffic',
      },
    ]);
  });
});
