import { PERSONALITY_QUIZ_KINDS } from '@/shared/constants/personality';
import type { PersonalityQuizResultViewModel } from '@/business/personality/types';
import type { PolicyViewModel } from '@/business/policies/types';
import type { SafetyProtocolViewModel } from '@/business/safety-protocols/types';
import type { PolicyAcknowledgmentDto } from '@/shared/types/policyDocuments';
import type { SafetyQuizResultDto } from '@/shared/types/safetyQuiz';
import type { ZoneCheckinTodayDto } from '@/shared/types/zoneCheckins';

export interface ProfileQuizResultRow {
  readonly id: string;
  readonly quiz: string;
  readonly category: string;
  readonly result: string;
  readonly completed: string;
  readonly status: 'complete' | 'pending';
}

export interface ProfileDocumentAcknowledgmentRow {
  readonly id: string;
  readonly title: string;
  readonly category: string;
  readonly version: number;
  readonly acknowledgedAt: string | null;
  readonly status: 'acknowledged' | 'pending';
}

export function buildProfileQuizResultRows(
  safetyQuizResult: SafetyQuizResultDto | null,
  personalityResults: readonly PersonalityQuizResultViewModel[],
  zoneCheckinToday: ZoneCheckinTodayDto | null = null,
  includeZoneCheckin = true,
): readonly ProfileQuizResultRow[] {
  const rows: ProfileQuizResultRow[] = [
    toProfileSafetyQuizRow(safetyQuizResult),
    ...personalityResults.map(toProfilePersonalityQuizRow),
  ];

  if (!hasPersonalityResult(personalityResults, PERSONALITY_QUIZ_KINDS.selfAssessment)) {
    rows.push(toProfilePendingPersonalityQuizRow(PERSONALITY_QUIZ_KINDS.selfAssessment));
  }

  if (!hasPersonalityResult(personalityResults, PERSONALITY_QUIZ_KINDS.personalityType)) {
    rows.push(toProfilePendingPersonalityQuizRow(PERSONALITY_QUIZ_KINDS.personalityType));
  }

  if (includeZoneCheckin) {
    rows.push(toProfileZoneCheckinRow(zoneCheckinToday));
  }

  return rows;
}

export function buildProfileDocumentAcknowledgmentRows(
  handbookPolicies: readonly PolicyViewModel[],
  safetyProtocols: readonly SafetyProtocolViewModel[],
  acknowledgments: readonly PolicyAcknowledgmentDto[],
): readonly ProfileDocumentAcknowledgmentRow[] {
  const rows: ProfileDocumentAcknowledgmentRow[] = [];
  const acknowledgmentByDocumentVersion = new Map(
    acknowledgments.map((acknowledgment) => [
      getDocumentVersionKey(acknowledgment.policyDocumentId, acknowledgment.version),
      acknowledgment,
    ]),
  );

  for (const policy of handbookPolicies) {
    const acknowledgment = acknowledgmentByDocumentVersion.get(
      getDocumentVersionKey(policy.id, policy.version),
    );

    rows.push({
      id: `handbook-${policy.id}`,
      title: policy.title,
      category: `Handbook & Policies · ${policy.category}`,
      version: policy.version,
      acknowledgedAt: acknowledgment?.acknowledgedAt ?? null,
      status: acknowledgment ? 'acknowledged' : 'pending',
    });
  }

  for (const protocol of safetyProtocols) {
    const acknowledgment = acknowledgmentByDocumentVersion.get(
      getDocumentVersionKey(protocol.id, protocol.version),
    );

    rows.push({
      id: `safety-${protocol.id}`,
      title: protocol.title,
      category: 'Safety Protocols',
      version: protocol.version,
      acknowledgedAt: acknowledgment?.acknowledgedAt ?? null,
      status: acknowledgment ? 'acknowledged' : 'pending',
    });
  }

  return rows.sort((left, right) => {
    if (left.status !== right.status) {
      return left.status === 'pending' ? -1 : 1;
    }

    return left.category.localeCompare(right.category)
      || left.title.localeCompare(right.title);
  });
}

function getDocumentVersionKey(documentId: string, version: number): string {
  return `${documentId}:${version}`;
}

function hasPersonalityResult(
  results: readonly PersonalityQuizResultViewModel[],
  quizKind: PersonalityQuizResultViewModel['quizKind'],
): boolean {
  return results.some((result) => result.quizKind === quizKind);
}

function getPersonalityResultSummary(result: PersonalityQuizResultViewModel): string {
  if (result.quizKind === PERSONALITY_QUIZ_KINDS.personalityType) {
    return result.personalityType ?? result.resultLabel ?? 'Completed';
  }

  const label = result.resultLabel ?? 'Completed';
  if (result.score === null) {
    return label;
  }

  return `${label} (${result.score}/${result.totalQuestions * 4})`;
}

function getResultCategoryLabel(result: PersonalityQuizResultViewModel): string {
  return result.quizKind === PERSONALITY_QUIZ_KINDS.personalityType
    ? 'Personality type'
    : 'EI self-assessment';
}

function toProfileSafetyQuizRow(result: SafetyQuizResultDto | null): ProfileQuizResultRow {
  if (!result) {
    return {
      id: 'behavior-management-pending',
      quiz: 'Behavior Management',
      category: 'QBS safety quiz',
      result: 'Pending',
      completed: 'Not completed',
      status: 'pending',
    };
  }

  return {
    id: `${result.id}-behavior-management`,
    quiz: result.quiz_title,
    category: 'QBS safety quiz',
    result: `${result.score}/${result.total_questions}`,
    completed: new Date(result.completed_at).toLocaleDateString(),
    status: 'complete',
  };
}

function toProfilePersonalityQuizRow(result: PersonalityQuizResultViewModel): ProfileQuizResultRow {
  return {
    id: `${result.quizKind}-${result.quizId}-${result.completedAt}`,
    quiz: result.quizTitle,
    category: getResultCategoryLabel(result),
    result: getPersonalityResultSummary(result),
    completed: new Date(result.completedAt).toLocaleDateString(),
    status: 'complete',
  };
}

function toProfilePendingPersonalityQuizRow(
  quizKind: typeof PERSONALITY_QUIZ_KINDS.selfAssessment | typeof PERSONALITY_QUIZ_KINDS.personalityType,
): ProfileQuizResultRow {
  return {
    id: `${quizKind}-pending`,
    quiz: quizKind === PERSONALITY_QUIZ_KINDS.personalityType
      ? 'Personality Type Quiz'
      : 'EI Self-Assessment',
    category: quizKind === PERSONALITY_QUIZ_KINDS.personalityType
      ? 'Personality type'
      : 'EI self-assessment',
    result: 'Pending',
    completed: 'Not completed',
    status: 'pending',
  };
}

function toProfileZoneCheckinRow(
  checkin: ZoneCheckinTodayDto | null,
): ProfileQuizResultRow {
  if (!checkin?.zone) {
    return {
      id: 'daily-zone-check-in-pending',
      quiz: 'Daily Zone Check-In',
      category: 'Regulation zone',
      result: 'Pending',
      completed: 'Not completed',
      status: 'pending',
    };
  }

  return {
    id: `daily-zone-check-in-${checkin.date}`,
    quiz: 'Daily Zone Check-In',
    category: 'Regulation zone',
    result: `${checkin.zone[0].toUpperCase()}${checkin.zone.slice(1)} Zone`,
    completed: new Date(`${checkin.date}T00:00:00`).toLocaleDateString(),
    status: 'complete',
  };
}
