import { describe, expect, it } from 'vitest';
import {
  calculateVocationalStats,
  filterVocationalOpportunities,
  listVocationalCategories,
  normalizeVocationalZipCode,
  searchVocationalOpportunitiesByZip,
  toVocationalCategoryFilter,
} from '@/business/vocational/selectors';
import {
  VOCATIONAL_EAST_VALLEY_DISTANCE_OFFSET,
  VOCATIONAL_OTHER_DISTANCE_OFFSET,
} from '@/shared/constants/vocational';
import type { VocationalOpportunity } from '@/shared/types/vocational';

const opportunities: readonly VocationalOpportunity[] = [
  {
    id: 'garden',
    company: 'Green Thumb Nursery',
    title: 'Horticulture Assistant',
    category: 'Agriculture & Gardening',
    description: 'Plant care.',
    address: '100 Garden Way',
    zipCode: '85001',
    phone: '(602) 555-0100',
    email: 'garden@example.org',
    website: 'garden.example.org',
    distance: '1.5 mi',
    schedule: 'Mon-Wed',
    compensation: 'Stipend',
    skills: ['Plant care'],
    requirements: ['Outdoor comfort'],
    accommodations: ['Visual checklist'],
    ageGroup: '14-18',
    spots: 4,
    featured: true,
  },
  {
    id: 'bakery',
    company: 'Sunrise Bakery',
    title: 'Kitchen Prep Assistant',
    category: 'Food Service',
    description: 'Food prep.',
    address: '200 Main St',
    zipCode: '85003',
    phone: '(602) 555-0200',
    email: 'bakery@example.org',
    website: 'bakery.example.org',
    distance: '2.8 mi',
    schedule: 'Tue-Thu',
    compensation: 'Minimum Wage',
    skills: ['Food safety'],
    requirements: ['Food handler card'],
    accommodations: ['Visual recipes'],
    ageGroup: '16-22',
    spots: 3,
    featured: true,
  },
  {
    id: 'studio',
    company: 'Creative Sparks Art Studio',
    title: 'Studio Assistant',
    category: 'Arts & Creative',
    description: 'Art supply organization.',
    address: '300 Art St',
    zipCode: '85004',
    phone: '(602) 555-0300',
    email: 'studio@example.org',
    website: 'studio.example.org',
    distance: '3.9 mi',
    schedule: 'Wed-Fri',
    compensation: 'Stipend',
    skills: ['Supply organization'],
    requirements: ['Interest in art'],
    accommodations: ['Quiet prep time'],
    ageGroup: '14-22',
    spots: 2,
    featured: false,
  },
];

function getDistance(distance: string): number {
  return Number.parseFloat(distance);
}

describe('vocational selectors', () => {
  it('normalizes zip code input to five digits', () => {
    expect(normalizeVocationalZipCode('AZ 85001-1234')).toBe('85001');
    expect(normalizeVocationalZipCode('abc')).toBe('');
  });

  it('lists unique categories in sorted order and normalizes filters', () => {
    const categories = listVocationalCategories(opportunities);

    expect(categories).toEqual(['Agriculture & Gardening', 'Arts & Creative', 'Food Service']);
    expect(toVocationalCategoryFilter('Food Service', categories)).toBe('Food Service');
    expect(toVocationalCategoryFilter('Unknown', categories)).toBe('all');
    expect(toVocationalCategoryFilter('all', categories)).toBe('all');
  });

  it('searches by Phoenix, East Valley, and other zip ranges with expected distance offsets', () => {
    const phoenixResults = searchVocationalOpportunitiesByZip(opportunities, '85001');
    const eastValleyResults = searchVocationalOpportunitiesByZip(opportunities, '85283');
    const otherResults = searchVocationalOpportunitiesByZip(opportunities, '85301');

    expect(phoenixResults[0].id).toBe('garden');
    expect(getDistance(eastValleyResults[0].distance)).toBe(
      getDistance(opportunities[0].distance) + VOCATIONAL_EAST_VALLEY_DISTANCE_OFFSET,
    );
    expect(getDistance(otherResults[0].distance)).toBe(
      getDistance(opportunities[0].distance) + VOCATIONAL_OTHER_DISTANCE_OFFSET,
    );
  });

  it('filters opportunities by trimmed search query and category', () => {
    expect(filterVocationalOpportunities(opportunities, '  bakery ', 'all')).toEqual([opportunities[1]]);
    expect(filterVocationalOpportunities(opportunities, 'assistant', 'Arts & Creative')).toEqual([opportunities[2]]);
    expect(filterVocationalOpportunities(opportunities, 'assistant', 'Technology')).toEqual([]);
  });

  it('calculates display-result stats', () => {
    expect(calculateVocationalStats(opportunities, 2)).toEqual({
      totalPositions: 9,
      companies: 3,
      categories: 3,
      saved: 2,
    });
  });
});
