import { AlmanacService } from './almanacService' import type { Almanac } from '../algorithms/types' import type { SearchCondition, SearchRequest, SearchResult } from '../types/search' import { storage } from '../utils/storage' export interface SearchParams { keyword?: string dateFrom?: string dateTo?: string suitableFilter?: string[] unsuitableFilter?: string[] } export interface SearchHistoryItem { keyword: string timestamp: number resultCount: number } function toSearchParams(request: SearchRequest): SearchParams { const suitableFilter: string[] = [] const unsuitableFilter: string[] = [] for (const cond of request.conditions) { if (cond.type === 'suitable') { suitableFilter.push(...cond.items) } else { unsuitableFilter.push(...cond.items) } } const today = new Date() const dateFrom = today.toISOString().slice(0, 10) const endDate = new Date(today) endDate.setDate(endDate.getDate() + request.days) const dateTo = endDate.toISOString().slice(0, 10) return { suitableFilter, unsuitableFilter, dateFrom, dateTo } } function toSearchResult(almanac: Almanac, conditions: SearchCondition[]): SearchResult { const matchedSuitable = conditions .filter(c => c.type === 'suitable') .flatMap(c => c.items) .filter(item => almanac.suitable.includes(item)) const matchedUnsuitable = conditions .filter(c => c.type === 'unsuitable') .flatMap(c => c.items) .filter(item => almanac.unsuitable.includes(item)) return { date: almanac.solarDate, lunarDate: `${almanac.lunarDate.lunarYear}${almanac.lunarDate.lunarMonth}${almanac.lunarDate.lunarDay}`, weekday: almanac.lunarDate.weekday, matchedItems: { suitable: matchedSuitable, unsuitable: matchedUnsuitable, }, matchCount: matchedSuitable.length + matchedUnsuitable.length, almanacData: almanac, } } export class SearchService { private almanacService = new AlmanacService() private historyKey = 'search_history' async search(request: SearchRequest): Promise { const params = toSearchParams(request) const almanacs = await this.almanacService.searchAlmanacs(params) this.addToHistory( request.conditions.map(c => c.items.join(',')).join(';'), almanacs.length, ) return almanacs.map(a => toSearchResult(a, request.conditions)) } async searchByKeyword(keyword: string): Promise { const params: SearchParams = { keyword } const almanacs = await this.almanacService.searchAlmanacs(params) this.addToHistory(keyword, almanacs.length) return almanacs.map(a => toSearchResult(a, [])) } async getSearchHistory(): Promise { return storage.get(this.historyKey) ?? [] } async clearSearchHistory(): Promise { storage.remove(this.historyKey) } private addToHistory(keyword: string, resultCount: number): void { if (!keyword) return const history = storage.get(this.historyKey) ?? [] history.unshift({ keyword, timestamp: Date.now(), resultCount }) if (history.length > 50) history.length = 50 storage.set(this.historyKey, history) } } const searchService = new SearchService() export default searchService