import {
  VOCATIONAL_EAST_VALLEY_DISTANCE_OFFSET,
  VOCATIONAL_EAST_VALLEY_ZIP_MAX,
  VOCATIONAL_EAST_VALLEY_ZIP_MIN,
  VOCATIONAL_OTHER_DISTANCE_OFFSET,
  VOCATIONAL_PHOENIX_ZIP_MAX,
  VOCATIONAL_PHOENIX_ZIP_MIN,
} from '@/shared/constants/vocational';
import type {
  VocationalCategory,
  VocationalCategoryFilter,
  VocationalOpportunity,
  VocationalStats,
} from '@/shared/types/vocational';

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

function withDistanceOffset(
  opportunity: VocationalOpportunity,
  offset: number,
): VocationalOpportunity {
  return {
    ...opportunity,
    distance: `${(getDistanceValue(opportunity.distance) + offset).toFixed(1)} mi`,
  };
}

export function normalizeVocationalZipCode(value: string): string {
  return value.replace(/\D/g, '').slice(0, 5);
}

export function listVocationalCategories(
  opportunities: readonly VocationalOpportunity[],
): readonly VocationalCategory[] {
  return [...new Set(opportunities.map((opportunity) => opportunity.category))].sort();
}

export function toVocationalCategoryFilter(
  value: string,
  categories: readonly VocationalCategory[],
): VocationalCategoryFilter {
  if (value === 'all') {
    return 'all';
  }

  const found = categories.find((category) => category === value);
  return found ?? 'all';
}

export function searchVocationalOpportunitiesByZip(
  opportunities: readonly VocationalOpportunity[],
  zipCode: string,
): readonly VocationalOpportunity[] {
  const zipNumber = Number.parseInt(zipCode, 10);

  if (zipNumber >= VOCATIONAL_PHOENIX_ZIP_MIN && zipNumber <= VOCATIONAL_PHOENIX_ZIP_MAX) {
    return [...opportunities].sort((a, b) => getDistanceValue(a.distance) - getDistanceValue(b.distance));
  }

  if (zipNumber >= VOCATIONAL_EAST_VALLEY_ZIP_MIN && zipNumber <= VOCATIONAL_EAST_VALLEY_ZIP_MAX) {
    return opportunities
      .map((opportunity) => withDistanceOffset(opportunity, VOCATIONAL_EAST_VALLEY_DISTANCE_OFFSET))
      .sort((a, b) => getDistanceValue(a.distance) - getDistanceValue(b.distance));
  }

  return opportunities.map((opportunity) => (
    withDistanceOffset(opportunity, VOCATIONAL_OTHER_DISTANCE_OFFSET)
  ));
}

export function filterVocationalOpportunities(
  opportunities: readonly VocationalOpportunity[],
  searchQuery: string,
  categoryFilter: VocationalCategoryFilter,
): readonly VocationalOpportunity[] {
  const normalizedQuery = searchQuery.trim().toLowerCase();

  return opportunities.filter((opportunity) => {
    const matchesSearch = normalizedQuery === ''
      || opportunity.company.toLowerCase().includes(normalizedQuery)
      || opportunity.title.toLowerCase().includes(normalizedQuery)
      || opportunity.category.toLowerCase().includes(normalizedQuery);
    const matchesCategory = categoryFilter === 'all' || opportunity.category === categoryFilter;

    return matchesSearch && matchesCategory;
  });
}

export function calculateVocationalStats(
  opportunities: readonly VocationalOpportunity[],
  savedCount: number,
): VocationalStats {
  return {
    totalPositions: opportunities.reduce((sum, opportunity) => sum + opportunity.spots, 0),
    companies: opportunities.length,
    categories: new Set(opportunities.map((opportunity) => opportunity.category)).size,
    saved: savedCount,
  };
}
