import {
  buildCombinedAttendanceHistoryRows,
  buildPrintAttendanceStats,
  formatAttendanceDate,
} from '@/business/campus-attendance/selectors';
import { PRINT_DIALOG_OPEN_DELAY_MS } from '@/shared/constants/ui';
import type {
  CampusAttendanceStats,
  CampusAttendancePrintInput,
  CombinedAttendanceHistoryRow,
} from '@/business/campus-attendance/types';

const escapeHtml = (value: string): string => (
  value
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#039;')
);

const percentageClass = (percentage: number | null): string => {
  if (percentage === null) {
    return '';
  }

  if (percentage >= 90) {
    return 'green';
  }

  if (percentage >= 80) {
    return 'amber';
  }

  return 'red';
};

const inlinePercentageClass = (percentage: number | null): string => {
  if (percentage === null) {
    return '';
  }

  if (percentage >= 90) {
    return 'pct-good';
  }

  if (percentage >= 80) {
    return 'pct-warn';
  }

  return 'pct-bad';
};

function buildTodayReportRows(campus: CampusAttendanceStats): readonly CombinedAttendanceHistoryRow[] {
  const date = campus.todayRecord?.date ?? campus.todayStaffRecord?.date ?? '';
  const studentRecord = campus.todayRecord;
  const staffRecord = campus.todayStaffRecord;
  const studentTotal = studentRecord?.total_enrolled ?? 0;
  const staffTotal = staffRecord?.total_staff ?? 0;
  const studentPresent = studentRecord?.total_present ?? 0;
  const staffPresent = staffRecord?.total_present ?? 0;
  const studentAbsent = studentRecord?.total_absent ?? 0;
  const staffAbsent = staffRecord?.total_absent ?? 0;
  const studentLate = studentRecord?.total_tardy ?? 0;
  const staffLate = staffRecord?.total_late ?? 0;
  const combinedTotal = studentTotal + staffTotal;
  const combinedPresent = studentPresent + staffPresent;
  const combinedPercentage = combinedTotal > 0
    ? Number(((combinedPresent / combinedTotal) * 100).toFixed(2))
    : null;
  const notes = [studentRecord?.notes, staffRecord?.notes].filter((note): note is string => Boolean(note));

  return [
    {
      id: `${campus.id}:today:students`,
      date,
      group: 'students',
      label: 'Students',
      total: studentTotal,
      present: studentPresent,
      absent: studentAbsent,
      late: studentLate,
      attendancePercentage: studentRecord?.attendance_percentage ?? null,
      notes: studentRecord?.notes ?? null,
    },
    {
      id: `${campus.id}:today:staff`,
      date,
      group: 'staff',
      label: 'Staff',
      total: staffTotal,
      present: staffPresent,
      absent: staffAbsent,
      late: staffLate,
      attendancePercentage: staffRecord?.attendance_percentage ?? null,
      notes: staffRecord?.notes ?? null,
    },
    {
      id: `${campus.id}:today:total`,
      date,
      group: 'total',
      label: 'Total',
      total: combinedTotal,
      present: combinedPresent,
      absent: studentAbsent + staffAbsent,
      late: studentLate + staffLate,
      attendancePercentage: combinedPercentage,
      notes: notes.length > 0 ? notes.join('; ') : null,
    },
  ];
}

function renderAttendanceRows(rows: readonly CombinedAttendanceHistoryRow[]): string {
  return rows.map((record) => `
    <tr>
      <td>${record.group === 'students' ? formatAttendanceDate(record.date) : ''}</td>
      <td>${record.label}</td>
      <td>${record.total}</td>
      <td>${record.present}</td>
      <td>${record.absent}</td>
      <td>${record.late}</td>
      <td class="${inlinePercentageClass(record.attendancePercentage)}">${record.attendancePercentage !== null ? `${record.attendancePercentage.toFixed(1)}%` : 'N/A'}</td>
      <td>${record.notes ? escapeHtml(record.notes) : '-'}</td>
    </tr>
  `).join('');
}

function renderAttendanceHistoryTable(campus: CampusAttendanceStats): string {
  const historyRows = buildCombinedAttendanceHistoryRows(campus.recentData, campus.recentStaffData);

  if (historyRows.length === 0) {
    return '';
  }

  return `
    <div class="section-label">Attendance history</div>
    <table class="history-table">
      <thead>
        <tr>
          <th>Date</th><th>Group</th><th>Total</th><th>Present</th><th>Absent</th><th>Tardy / Late</th><th>Attendance %</th><th>Notes</th>
        </tr>
      </thead>
      <tbody>
        ${renderAttendanceRows(historyRows)}
      </tbody>
    </table>
  `;
}

export type CampusAttendancePrintResult =
  | { readonly ok: true }
  | { readonly ok: false; readonly reason: 'popup-blocked' };

export interface CampusAttendancePrintWindow {
  readonly document: Pick<Document, 'write' | 'close'>;
  readonly focus: () => void;
  readonly print: () => void;
}

interface OpenCampusAttendancePrintReportOptions {
  readonly input: CampusAttendancePrintInput;
  readonly openWindow?: () => CampusAttendancePrintWindow | null;
  readonly schedulePrint?: (callback: () => void, delayMs: number) => void;
}

export const CAMPUS_ATTENDANCE_PRINT_POPUP_BLOCKED_MESSAGE =
  'The attendance report could not be opened. Please allow pop-ups for this site and try again.';

export function openCampusAttendancePrintReport({
  input,
  openWindow = () => window.open('', '_blank'),
  schedulePrint = (callback, delayMs) => {
    window.setTimeout(callback, delayMs);
  },
}: OpenCampusAttendancePrintReportOptions): CampusAttendancePrintResult {
  const printWindow = openWindow();

  if (!printWindow) {
    return { ok: false, reason: 'popup-blocked' };
  }

  printWindow.document.write(buildCampusAttendancePrintHtml(input));
  printWindow.document.close();
  printWindow.focus();
  schedulePrint(() => {
    printWindow.print();
  }, PRINT_DIALOG_OPEN_DELAY_MS);

  return { ok: true };
}

export function buildCampusAttendancePrintHtml(input: CampusAttendancePrintInput): string {
  const printStats = buildPrintAttendanceStats(input);
  const staffTotal = input.staffSummary
    ? input.staffSummary.present + input.staffSummary.late + input.staffSummary.absent
    : 0;
  const generatedAtDate = new Date().toLocaleDateString('en-US', {
    weekday: 'long',
    year: 'numeric',
    month: 'long',
    day: 'numeric',
  });
  const generatedAtTime = new Date().toLocaleTimeString('en-US', {
    hour: '2-digit',
    minute: '2-digit',
  });

  return `
    <!DOCTYPE html>
    <html>
    <head>
      <title>${escapeHtml(input.reportTitle)} - ${formatAttendanceDate(input.today)}</title>
      <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; padding: 32px; color: #1e293b; }
        .header { text-align: center; margin-bottom: 32px; border-bottom: 3px solid #7c3aed; padding-bottom: 16px; }
        .header h1 { font-size: 24px; color: #7c3aed; margin-bottom: 4px; }
        .header p { font-size: 13px; color: #64748b; }
        .summary-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin-bottom: 32px; }
        .summary-box { border: 2px solid #e2e8f0; border-radius: 12px; padding: 16px; text-align: center; }
        .summary-box .label { font-size: 11px; color: #64748b; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px; }
        .summary-box .value { font-size: 28px; font-weight: 700; }
        .summary-box .value.green { color: #16a34a; }
        .summary-box .value.amber { color: #d97706; }
        .summary-box .value.red { color: #dc2626; }
        .campus-section { margin-bottom: 24px; page-break-inside: avoid; }
        .campus-header { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; padding: 8px 12px; background: #f8fafc; border-radius: 8px; border-left: 4px solid #7c3aed; }
        .campus-header h3 { font-size: 15px; font-weight: 600; }
        .campus-header .stats { margin-left: auto; display: flex; gap: 16px; font-size: 12px; }
        .campus-header .stats span { font-weight: 600; }
        table { width: 100%; border-collapse: collapse; font-size: 12px; margin-bottom: 8px; }
        th { background: #f1f5f9; text-align: left; padding: 8px 10px; font-weight: 600; color: #475569; border-bottom: 2px solid #e2e8f0; }
        td { padding: 6px 10px; border-bottom: 1px solid #f1f5f9; }
        tr:nth-child(even) { background: #fafafa; }
        .pct-good { color: #16a34a; font-weight: 600; }
        .pct-warn { color: #d97706; font-weight: 600; }
        .pct-bad { color: #dc2626; font-weight: 600; }
        .history-table { margin-top: 16px; }
        .history-table th { font-size: 11px; }
        .history-table td { font-size: 11px; }
        .section-label { font-size: 12px; font-weight: 700; color: #334155; margin: 12px 0 6px; }
        .footer { margin-top: 32px; padding-top: 16px; border-top: 2px solid #e2e8f0; text-align: center; font-size: 11px; color: #94a3b8; }
        @media print { body { padding: 16px; } .no-print { display: none; } }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>FRAMEworks ${escapeHtml(input.reportTitle)}</h1>
        <p>Generated on ${generatedAtDate} at ${generatedAtTime}</p>
        <p style="margin-top:4px;font-size:12px;color:#7c3aed;">Printed by: ${escapeHtml(input.generatedByName)} (${escapeHtml(input.generatedByRole)})</p>
      </div>
      <div class="summary-grid">
        <div class="summary-box">
          <div class="label">Today's Attendance</div>
          <div class="value ${percentageClass(printStats.combinedPct)}">${printStats.combinedPct !== null ? `${printStats.combinedPct}%` : 'No data'}</div>
          <div class="label" style="margin-top:4px">Students ${printStats.todayPct !== null ? `${printStats.todayPct}%` : 'N/A'} · Staff ${printStats.staffPct !== null ? `${printStats.staffPct}%` : 'N/A'}</div>
        </div>
        <div class="summary-box">
          <div class="label">People</div>
          <div class="value">${input.printTodayRecords.reduce((sum, record) => sum + record.total_enrolled, 0) + staffTotal}</div>
          <div class="label" style="margin-top:4px">Students ${input.printTodayRecords.reduce((sum, record) => sum + record.total_enrolled, 0)} · Staff ${staffTotal}</div>
        </div>
        <div class="summary-box">
          <div class="label">This Week's Student Average</div>
          <div class="value ${percentageClass(printStats.weekPct)}">${printStats.weekPct !== null ? `${printStats.weekPct}%` : 'No data'}</div>
          <div class="label" style="margin-top:4px">Week of ${formatAttendanceDate(input.weekStart)}</div>
        </div>
      </div>
      ${input.campusesToPrint.map((campus) => `
        <div class="campus-section">
          <div class="campus-header">
            <h3>${escapeHtml(campus.fullName)}</h3>
            <div class="stats">
              <span>Today: <span class="${inlinePercentageClass(campus.todayPct)}">${campus.todayPct !== null ? `${campus.todayPct}%` : 'N/A'}</span></span>
              <span>Week Avg: <span class="${inlinePercentageClass(campus.weekAvg)}">${campus.weekAvg !== null ? `${campus.weekAvg}%` : 'N/A'}</span></span>
            </div>
          </div>
          ${campus.todayRecord || campus.todayStaffRecord ? `
            <div class="section-label">Today's report</div>
            <table class="history-table">
              <thead>
                <tr>
                  <th>Date</th><th>Group</th><th>Total</th><th>Present</th><th>Absent</th><th>Tardy / Late</th><th>Attendance %</th><th>Notes</th>
                </tr>
              </thead>
              <tbody>
                ${renderAttendanceRows(buildTodayReportRows(campus))}
              </tbody>
            </table>
          ` : '<p style="font-size:12px;color:#94a3b8;padding:8px 0;">No attendance data recorded for today.</p>'}
          ${renderAttendanceHistoryTable(campus)}
        </div>
      `).join('')}
      <div class="footer">
        <p>FRAMEworks Education Support Platform &bull; Confidential &bull; Printed by ${escapeHtml(input.generatedByName)}</p>
      </div>
    </body>
    </html>
  `;
}
