import {
  DIRECTOR_DASHBOARD_COMPLETION_TREND_THRESHOLD,
  DIRECTOR_DASHBOARD_FRAME_PREVIEW_LIMIT,
  DIRECTOR_DASHBOARD_HIGH_INCOMPLETE_STAFF_THRESHOLD,
  DIRECTOR_DASHBOARD_TEXT_PREVIEW_LENGTH,
} from '@/shared/constants/directorDashboard';
import {
  countStaffAttendanceStatus,
  staffAttendanceRate,
} from '@/business/staff-attendance/selectors';
import type { FrameEntryViewModel } from '@/business/frame/types';
import type { StaffAttendanceRecordViewModel } from '@/business/staff-attendance/types';
import type {
  PolicyAcknowledgmentReportDto,
  PolicyAcknowledgmentReportSummaryDto,
} from '@/shared/types/policyDocuments';
import type {
  DirectorAcknowledgmentDocumentRow,
  DirectorFramePreview,
  DirectorOverviewCard,
  DirectorQuizResultDetail,
  DirectorQuizResultRow,
  DirectorRiskArea,
} from '@/business/director-dashboard/types';
import type {
  SafetyQuizCompletionSummary,
  SafetyQuizComplianceRow,
} from '@/business/safety-quiz/types';
import type {
  PersonalityCompletionDto,
  PersonalityQuizResultDto,
} from '@/shared/types/personality';
import type { ZoneCheckinCompletionDto } from '@/shared/types/zoneCheckins';

export function calculateQuizCompletionRate(
  quizSummary: SafetyQuizCompletionSummary,
): number {
  return quizSummary.completionRate;
}

export function buildDirectorOverviewCards(
  attendanceRecords: readonly StaffAttendanceRecordViewModel[],
  quizSummary: SafetyQuizCompletionSummary,
  frameEntries: readonly FrameEntryViewModel[],
  acknowledgmentSummary?: PolicyAcknowledgmentReportSummaryDto | null,
): readonly DirectorOverviewCard[] {
  const attendanceRate = staffAttendanceRate(attendanceRecords);
  const quizCompletionRate = calculateQuizCompletionRate(quizSummary);
  const acknowledgmentRate = acknowledgmentSummary?.completionRate ?? 0;

  return [
    {
      label: 'Staff Attendance',
      value: `${attendanceRate}%`,
      change: `${attendanceRecords.length} records`,
      trend: 'up',
      iconId: 'clock',
      tone: 'orange',
      module: 'attendance',
    },
    {
      label: 'Behavior Management Quiz Completion',
      value: `${quizSummary.completedCount}/${quizSummary.totalStaff}`,
      change: `${quizCompletionRate}%`,
      trend: quizCompletionRate > DIRECTOR_DASHBOARD_COMPLETION_TREND_THRESHOLD ? 'up' : 'down',
      iconId: 'shield',
      tone: 'blue',
      module: 'qbs',
      action: 'openQuizResults',
    },
    {
      label: 'F.R.A.M.E. Entries',
      value: frameEntries.length.toString(),
      change: 'Total entries',
      trend: 'up',
      iconId: 'eye',
      tone: 'amber',
      module: 'frame',
    },
    {
      label: 'Staff Members',
      value: quizSummary.totalStaff.toString(),
      change: 'Active',
      trend: 'up',
      iconId: 'users',
      tone: 'purple',
      module: 'user-admin',
    },
    {
      label: 'Acknowledgments',
      value: `${acknowledgmentRate}%`,
      change: `${acknowledgmentSummary?.missingCount ?? 0} missing`,
      trend: acknowledgmentRate > DIRECTOR_DASHBOARD_COMPLETION_TREND_THRESHOLD ? 'up' : 'down',
      iconId: 'clipboard',
      tone: 'emerald',
      module: 'director',
      action: 'openAcknowledgments',
    },
  ];
}

export function buildDirectorRiskAreas(
  attendanceRecords: readonly StaffAttendanceRecordViewModel[],
  quizSummary: SafetyQuizCompletionSummary,
  emotionalIntelligenceCompletion?: PersonalityCompletionDto | null,
  zoneCheckinCompletion?: ZoneCheckinCompletionDto | null,
  acknowledgmentDocuments: readonly DirectorAcknowledgmentDocumentRow[] = [],
): readonly DirectorRiskArea[] {
  const incompleteStaffCount = quizSummary.pendingCount;
  const absenceCount = countStaffAttendanceStatus(attendanceRecords, 'absent');
  const lateCount = countStaffAttendanceStatus(attendanceRecords, 'late');
  const staffAttendanceExceptionCount = absenceCount + lateCount;
  const selfAssessmentPendingCount = emotionalIntelligenceCompletion?.summary
    ? emotionalIntelligenceCompletion.summary.totalStaff
      - emotionalIntelligenceCompletion.summary.selfAssessmentCompletedCount
    : 0;
  const personalityPendingCount = emotionalIntelligenceCompletion?.summary
    ? emotionalIntelligenceCompletion.summary.totalStaff
      - emotionalIntelligenceCompletion.summary.personalityCompletedCount
    : 0;
  const zonePendingCount = zoneCheckinCompletion?.summary.pendingCount ?? 0;
  const nonGreenZoneNote = getNonGreenZoneNote(zoneCheckinCompletion);

  const risks: DirectorRiskArea[] = [];

  if (incompleteStaffCount > 0) {
    risks.push({
      issue: `${incompleteStaffCount} staff haven't completed Behavior Management quiz`,
      severity: incompleteStaffCount > DIRECTOR_DASHBOARD_HIGH_INCOMPLETE_STAFF_THRESHOLD ? 'high' : 'medium',
      module: 'qbs',
      action: 'openQuizResults',
    });
  }

  if (selfAssessmentPendingCount > 0) {
    risks.push({
      issue: `${selfAssessmentPendingCount} staff haven't completed EI self-assessment`,
      severity: 'low',
      module: 'ei',
      action: 'openQuizResults',
    });
  }

  if (personalityPendingCount > 0) {
    risks.push({
      issue: `${personalityPendingCount} staff haven't completed personality type quiz`,
      severity: 'low',
      module: 'ei',
      action: 'openQuizResults',
    });
  }

  if (zonePendingCount > 0) {
    risks.push({
      issue: `${zonePendingCount} staff haven't completed daily zone check-in`,
      severity: 'medium',
      module: 'zones',
      action: 'openQuizResults',
    });
  }

  if (nonGreenZoneNote) {
    risks.push({
      issue: nonGreenZoneNote,
      severity: 'medium',
      module: 'zones',
    });
  }

  const acknowledgmentRisk = buildAcknowledgmentRisk(acknowledgmentDocuments);
  if (acknowledgmentRisk) {
    risks.push({
      issue: acknowledgmentRisk.issue,
      severity: acknowledgmentRisk.severity,
      module: 'director',
      action: 'openAcknowledgments',
    });
  }

  if (staffAttendanceExceptionCount > 0) {
    risks.push({
      issue: `${staffAttendanceExceptionCount} ${pluralize('staff attendance exception', staffAttendanceExceptionCount)} this period (${lateCount} late, ${absenceCount} absent)`,
      severity: 'high',
      module: 'attendance',
    });
  }

  return risks;
}

function buildAcknowledgmentRisk(
  acknowledgmentDocuments: readonly DirectorAcknowledgmentDocumentRow[],
): Pick<DirectorRiskArea, 'issue' | 'severity'> | null {
  const unresolvedDocuments = acknowledgmentDocuments.filter((document) =>
    document.missingCount > 0,
  );
  if (unresolvedDocuments.length === 0) {
    return null;
  }

  const staffIds = new Set<string>();
  for (const document of unresolvedDocuments) {
    for (const staff of document.missingStaff) {
      staffIds.add(staff.userId);
    }
  }

  const staffCount = staffIds.size || Math.max(
    ...unresolvedDocuments.map((document) => document.missingCount),
  );
  const documentCount = unresolvedDocuments.length;

  return {
    issue: `${staffCount} ${pluralize('staff', staffCount)} haven't acknowledged ${documentCount} ${pluralize('document', documentCount)}`,
    severity: staffCount > DIRECTOR_DASHBOARD_HIGH_INCOMPLETE_STAFF_THRESHOLD
      || documentCount > DIRECTOR_DASHBOARD_HIGH_INCOMPLETE_STAFF_THRESHOLD
      ? 'high'
      : 'medium',
  };
}

export function buildDirectorAcknowledgmentDocuments(
  report?: PolicyAcknowledgmentReportDto | null,
): readonly DirectorAcknowledgmentDocumentRow[] {
  if (!report) {
    return [];
  }

  return report.documents.map((document) => {
    const missingStaff = report.staff
      .filter((staff) =>
        staff.documents.some((status) =>
          status.policyDocumentId === document.id
          && status.version === document.version
          && status.missing,
        ),
      )
      .map((staff) => ({
        userId: staff.userId,
        name: staff.name,
        avatar: staff.avatar,
        tenantName: staff.tenantName,
        tenantLogo: staff.tenantLogo,
        role: formatRoleLabel(staff.role),
        email: staff.email,
      }));

    return {
      id: document.id,
      title: document.title,
      category: document.category,
      categoryLabel: getPolicyCategoryLabel(document.category),
      version: document.version,
      totalStaff: document.totalStaff,
      acknowledgedCount: document.acknowledgedCount,
      missingCount: document.missingCount,
      completionRate: document.completionRate,
      missingStaff,
    };
  });
}

function getNonGreenZoneNote(
  zoneCheckinCompletion?: ZoneCheckinCompletionDto | null,
): string | null {
  const nonGreenRows = zoneCheckinCompletion?.rows
    .filter((row) => row.status === 'complete' && row.zone !== null && row.zone !== 'green')
    ?? [];

  if (nonGreenRows.length === 0) {
    return null;
  }

  const staffNotes = nonGreenRows
    .map((row) => `${row.name} (${row.result})`)
    .join(', ');

  return `Non-green regulation zones: ${staffNotes}`;
}

function getPolicyCategoryLabel(category: string): string {
  if (category === 'safety_protocol') {
    return 'Safety Protocols';
  }
  if (category === 'handbook_policy') {
    return 'Handbook & Policies';
  }
  return category.replace(/_/g, ' ');
}

function formatRoleLabel(role: string | null): string {
  return role ? role.replace(/_/g, ' ') : 'Staff';
}

function pluralize(noun: string, count: number): string {
  if (noun === 'staff') {
    return 'staff';
  }
  return count === 1 ? noun : `${noun}s`;
}

export function buildDirectorQuizResults(
  safetyRows: readonly SafetyQuizComplianceRow[],
  emotionalIntelligenceCompletion?: PersonalityCompletionDto | null,
  zoneCheckinCompletion?: ZoneCheckinCompletionDto | null,
  tenantLabel = 'Current scope',
): readonly DirectorQuizResultRow[] {
  const rowsByUserId = new Map<string, {
    staffName: string;
    avatar: string | null;
    tenantName: string | null;
    tenantLogo: string | null;
    role: string;
    details: DirectorQuizResultDetail[];
  }>();

  const ensureRow = (
    userId: string,
    staffName: string,
    avatar: string | null,
    tenantName: string | null,
    tenantLogo: string | null,
    role: string | null,
  ): {
    staffName: string;
    avatar: string | null;
    tenantName: string | null;
    tenantLogo: string | null;
    role: string;
    details: DirectorQuizResultDetail[];
  } => {
    const existing = rowsByUserId.get(userId);
    if (existing) {
      if (!existing.avatar && avatar) {
        existing.avatar = avatar;
      }
      if (!existing.tenantName && tenantName) {
        existing.tenantName = tenantName;
      }
      if (!existing.tenantLogo && tenantLogo) {
        existing.tenantLogo = tenantLogo;
      }
      return existing;
    }
    const next = {
      staffName,
      avatar,
      tenantName,
      tenantLogo,
      role: role ?? 'Staff',
      details: [],
    };
    rowsByUserId.set(userId, next);
    return next;
  };

  for (const row of safetyRows) {
    ensureRow(row.userId, row.name, row.avatar, row.tenantName, row.tenantLogo, row.role).details.push({
      id: 'behavior-management',
      quiz: 'Behavior Management',
      result: row.score,
      date: row.date,
      status: row.status,
    });
  }

  for (const row of emotionalIntelligenceCompletion?.rows ?? []) {
    const target = ensureRow(row.userId, row.name, row.avatar, row.tenantName, row.tenantLogo, row.role);
    target.details.push(
      {
        id: 'ei-self-assessment',
        quiz: 'EI Self-Assessment',
        result: formatPersonalityQuizResult(row.selfAssessment, 'Pending'),
        date: formatPersonalityQuizDate(row.selfAssessment),
        status: row.selfAssessment ? 'complete' : 'pending',
      },
      {
        id: 'personality-type',
        quiz: 'Personality Type Quiz',
        result: formatPersonalityQuizResult(row.personality, 'Pending'),
        date: formatPersonalityQuizDate(row.personality),
        status: row.personality ? 'complete' : 'pending',
      },
    );
  }

  for (const row of zoneCheckinCompletion?.rows ?? []) {
    ensureRow(row.userId, row.name, row.avatar, row.tenantName, row.tenantLogo, row.role).details.push({
      id: 'daily-zone-check-in',
      quiz: 'Daily Zone Check-In',
      result: row.result,
      date: row.status === 'complete'
        ? new Date(`${row.date}T00:00:00`).toLocaleDateString('en-US', { month: 'short', day: 'numeric' })
        : 'Not completed',
      status: row.status,
    });
  }

  return [...rowsByUserId.entries()].map(([userId, row]) => ({
    id: userId,
    staffName: row.staffName,
    avatar: row.avatar,
    tenant: row.tenantName ?? tenantLabel,
    tenantLogo: row.tenantLogo,
    role: row.role,
    completedCount: row.details.filter((detail) => detail.status === 'complete').length,
    totalCount: row.details.length,
    details: row.details,
  }));
}

export function buildDirectorFramePreviews(
  frameEntries: readonly FrameEntryViewModel[],
): readonly DirectorFramePreview[] {
  return frameEntries.slice(0, DIRECTOR_DASHBOARD_FRAME_PREVIEW_LIMIT).map((entry) => ({
    id: entry.id,
    week: entry.weekOf,
    sections: [
      { letter: 'F', text: truncatePreview(entry.formal) },
      { letter: 'R', text: truncatePreview(entry.recognition) },
      { letter: 'A', text: truncatePreview(entry.application) },
      { letter: 'M', text: truncatePreview(entry.management) },
      { letter: 'E', text: truncatePreview(entry.emotional) },
    ],
  }));
}

function truncatePreview(value: string): string {
  if (value.length <= DIRECTOR_DASHBOARD_TEXT_PREVIEW_LENGTH) {
    return value;
  }

  return `${value.slice(0, DIRECTOR_DASHBOARD_TEXT_PREVIEW_LENGTH)}...`;
}

function formatPersonalityQuizResult(
  result: PersonalityQuizResultDto | null,
  fallback: string,
): string {
  if (!result) {
    return fallback;
  }

  if (result.personality_type) {
    return result.personality_type;
  }

  if (result.result_label && result.score !== null) {
    return `${result.result_label} (${result.score}/${result.total_questions * 4})`;
  }

  return result.result_label ?? 'Completed';
}

function formatPersonalityQuizDate(result: PersonalityQuizResultDto | null): string {
  if (!result) {
    return 'Not completed';
  }

  return new Date(result.completed_at).toLocaleDateString('en-US', {
    month: 'short',
    day: 'numeric',
  });
}
