import { describe, expect, it } from 'vitest';
import {
  calculatePersonalityQuizProgress,
  formatPersonalitySavedDate,
  getEmotionalIntelligenceLevel,
  getPersonalityCommunicationGrowthArea,
  getPersonalityCommunicationStrengths,
  getPersonalityDirectoryGroup,
  getPersonalityDirectoryGroupDescription,
  getPersonalityDirectoryGroupLabel,
  getPersonalityDimensionProgress,
  getPersonalityGroup,
  getPersonalityRelationshipTips,
  getPersonalityTypeBreakdown,
  filterPersonalityDirectoryTypes,
  groupPersonalityDistribution,
  totalPersonalityDistribution,
} from '@/business/personality/selectors';
import type { PersonalityType, QuizQuestion } from '@/shared/constants/personalityCatalog';
import type { PersonalityDistributionDto } from '@/shared/types/personality';

const quizQuestions: readonly QuizQuestion[] = [
  { id: 1, dimension: 'EI', question: 'Question 1', optionA: { text: 'E', value: 'E' }, optionB: { text: 'I', value: 'I' } },
  { id: 2, dimension: 'EI', question: 'Question 2', optionA: { text: 'E', value: 'E' }, optionB: { text: 'I', value: 'I' } },
  { id: 3, dimension: 'EI', question: 'Question 3', optionA: { text: 'E', value: 'E' }, optionB: { text: 'I', value: 'I' } },
  { id: 4, dimension: 'SN', question: 'Question 4', optionA: { text: 'S', value: 'S' }, optionB: { text: 'N', value: 'N' } },
  { id: 5, dimension: 'SN', question: 'Question 5', optionA: { text: 'S', value: 'S' }, optionB: { text: 'N', value: 'N' } },
  { id: 6, dimension: 'SN', question: 'Question 6', optionA: { text: 'S', value: 'S' }, optionB: { text: 'N', value: 'N' } },
  { id: 7, dimension: 'TF', question: 'Question 7', optionA: { text: 'T', value: 'T' }, optionB: { text: 'F', value: 'F' } },
  { id: 8, dimension: 'TF', question: 'Question 8', optionA: { text: 'T', value: 'T' }, optionB: { text: 'F', value: 'F' } },
  { id: 9, dimension: 'TF', question: 'Question 9', optionA: { text: 'T', value: 'T' }, optionB: { text: 'F', value: 'F' } },
  { id: 10, dimension: 'JP', question: 'Question 10', optionA: { text: 'J', value: 'J' }, optionB: { text: 'P', value: 'P' } },
  { id: 11, dimension: 'JP', question: 'Question 11', optionA: { text: 'J', value: 'J' }, optionB: { text: 'P', value: 'P' } },
  { id: 12, dimension: 'JP', question: 'Question 12', optionA: { text: 'J', value: 'J' }, optionB: { text: 'P', value: 'P' } },
];

const intjType: PersonalityType = {
  code: 'INTJ',
  name: 'The Architect',
  nickname: 'Strategic Visionary',
  description: 'Strategic and independent.',
  strengths: ['Strategic planning'],
  workRelationships: 'Values competence.',
  workplaceLanguage: 'Direct and precise.',
  idealWorkEnvironment: 'Structured autonomy',
  communicationStyle: 'Direct',
  color: 'from-indigo-500 to-purple-600',
  bgColor: 'bg-indigo-500/10',
  borderColor: 'border-indigo-500/20',
  icon: 'architect',
};

const enfpType: PersonalityType = {
  ...intjType,
  code: 'ENFP',
  name: 'The Campaigner',
  nickname: 'Enthusiastic Connector',
};

describe('personality selectors', () => {
  it('totals and groups personality distribution counts', () => {
    const distribution: readonly PersonalityDistributionDto[] = [
      { type: 'INTJ', count: 3 },
      { type: 'ENTJ', count: 2 },
      { type: 'ENFP', count: 4 },
      { type: 'ISFJ', count: 1 },
    ];

    expect(totalPersonalityDistribution(distribution)).toBe(10);
    expect(groupPersonalityDistribution(distribution, getPersonalityGroup)).toEqual({
      Analysts: 5,
      Diplomats: 4,
      Sentinels: 1,
    });
  });

  it('returns expected EI level thresholds', () => {
    expect(getEmotionalIntelligenceLevel(85).label).toBe('Strong EI Foundation');
    expect(getEmotionalIntelligenceLevel(65).label).toBe('Growing EI Skills');
    expect(getEmotionalIntelligenceLevel(45).label).toBe('Developing Awareness');
    expect(getEmotionalIntelligenceLevel(20).label).toBe('Beginning Journey');
  });

  it('formats valid dates and preserves invalid date strings', () => {
    expect(formatPersonalitySavedDate('2026-06-08T12:00:00.000Z')).toBe('Jun 8, 2026');
    expect(formatPersonalitySavedDate('not-a-date')).toBe('not-a-date');
  });

  it('calculates quiz progress and dimension progress', () => {
    const answers: Record<number, string> = {
      1: 'E',
      4: 'N',
      7: 'T',
    };

    expect(calculatePersonalityQuizProgress(2, quizQuestions.length)).toBe(25);
    expect(getPersonalityDimensionProgress(quizQuestions[3], answers, quizQuestions)).toEqual([
      { dimension: 'EI', label: 'E/I', answeredCount: 1, totalCount: 3, current: false },
      { dimension: 'SN', label: 'S/N', answeredCount: 1, totalCount: 3, current: true },
      { dimension: 'TF', label: 'T/F', answeredCount: 1, totalCount: 3, current: false },
      { dimension: 'JP', label: 'J/P', answeredCount: 0, totalCount: 3, current: false },
    ]);
  });

  it('builds type breakdown and communication guidance from the personality code', () => {
    expect(getPersonalityTypeBreakdown(intjType)).toEqual([
      { letter: 'I', label: 'Energy', fullLabel: 'Introversion' },
      { letter: 'N', label: 'Info', fullLabel: 'Intuition' },
      { letter: 'T', label: 'Decisions', fullLabel: 'Thinking' },
      { letter: 'J', label: 'Structure', fullLabel: 'Judging' },
    ]);
    expect(getPersonalityCommunicationGrowthArea(intjType)).toContain('sharing your ideas earlier');
    expect(getPersonalityCommunicationStrengths(enfpType)).toContain('Engaging others in open dialogue and brainstorming');
    expect(getPersonalityRelationshipTips(intjType)).toHaveLength(4);
  });

  it('groups and filters personality directory types', () => {
    const types = [
      intjType,
      enfpType,
      { ...intjType, code: 'ISFJ', name: 'The Defender', nickname: 'Practical Supporter' },
      { ...intjType, code: 'ESTP', name: 'The Entrepreneur', nickname: 'Action-Oriented Problem Solver' },
    ];

    expect(getPersonalityDirectoryGroup('INTJ')).toBe('analysts');
    expect(getPersonalityDirectoryGroup('ENFP')).toBe('diplomats');
    expect(getPersonalityDirectoryGroup('ISFJ')).toBe('sentinels');
    expect(getPersonalityDirectoryGroup('ESTP')).toBe('explorers');
    expect(getPersonalityDirectoryGroupLabel('analysts')).toBe('Analysts (NT)');
    expect(getPersonalityDirectoryGroupDescription('all')).toContain('All 16 personality types');
    expect(filterPersonalityDirectoryTypes(types, 'defender', 'all').map((type) => type.code)).toEqual(['ISFJ']);
    expect(filterPersonalityDirectoryTypes(types, '', 'explorers').map((type) => type.code)).toEqual(['ESTP']);
  });
});
