import { isAxiosError } from 'axios' import { apiGet } from '@/lib/api' import { switchLocalePath } from '@/lib/locales' import { fetchTag, fetchTagByName } from '@/lib/tags' import type { LocaleCode } from '@/lib/locales' import type { LocaleSwitchRequest } from '@/lib/routeLocales' import type { Tag, WikiAutolinkCandidate, WikiPage, WikiPageChange, WikiTagReference } from '@/types' export const fetchWikiAutolinkCandidates = ( language: string, locale: LocaleCode, ): Promise => apiGet ('/wiki/autolink_candidates', { locale, params: { language } }) export const fetchWikiChanges = ( params: { id?: string }, locale: LocaleCode = 'ja', ): Promise => apiGet ('/wiki/changes', { locale, params }) export const fetchWikiPages = async ( { title }: { title?: string }, locale: LocaleCode = 'ja', ): Promise => await apiGet ('/wiki', { locale, params: { title } }) export const fetchWikiPage = async ( id: string, { version }: { version?: string }, locale: LocaleCode = 'ja', ): Promise => await apiGet (`/wiki/${ encodeURIComponent (id) }`, { locale, params: version ? { version } : { } }) export const fetchWikiPageByTitle = async ( title: string, { version }: { version?: string }, locale: LocaleCode = 'ja', ): Promise => { try { return await apiGet (`/wiki/title/${ encodeURIComponent (title) }`, { locale, params: { version } }) } catch (error) { if (isAxiosError (error) && error.response?.status === 404) return null throw error } } export const fetchWikiPageByReference = async ( reference: string, params: { version?: string }, locale: LocaleCode, ): Promise => { try { return /^\d+$/.test (reference) ? await fetchWikiPage (reference, params, locale) : await fetchWikiPageByTitle (reference, params, locale) } catch (error) { if (!isAxiosError (error) || error.response?.status !== 404) throw error const tag = await fetchWikiTag ({ wikiId: reference }, locale) return tag == null ? null : fetchWikiPageByTitle (tag.name, params, locale) } } export const fetchWikiTag = async ( reference: WikiTagReference, locale: LocaleCode, ): Promise => { if ('name' in reference) return fetchTagByName (reference.name, locale) try { return await apiGet (`/wiki/${encodeURIComponent (reference.wikiId)}/tag`, { locale }) } catch (error) { if (!isAxiosError (error) || error.response?.status !== 404) throw error return fetchTagByName (reference.wikiId, locale) } } export const switchWikiLocale = async ( { location, params, locale, targetLocale }: LocaleSwitchRequest, view: 'detail' | 'edit' | 'diff' | 'history' = 'detail', ): Promise => { const query = new URLSearchParams (location.search) const reference = params.title ?? params.id ?? query.get ('id') if (reference == null) return switchLocalePath (location, targetLocale) const page = await fetchWikiPageByReference (reference, { }, locale) const sourceTag = page == null ? await fetchWikiTag ( /^\d+$/.test (reference) ? { wikiId: reference } : { name: reference }, locale) : null if (page == null && sourceTag == null) return switchLocalePath (location, targetLocale) const translated = page == null ? null : await fetchWikiPageByReference (String (page.id), { }, targetLocale) const tag = sourceTag != null ? await fetchTag (String (sourceTag.id), targetLocale) : ((translated == null && page?.resourceType === 'tag_description') ? await fetchWikiTag ({ wikiId: String (page.id) }, targetLocale) : null) const destination = tag?.name ?? translated?.id ?? page?.id if (destination == null) throw new Error ('Wiki resource could not be resolved') for (const key of ['version', 'from', 'to']) query.delete (key) const historyId = view === 'history' ? translated?.id : null if (historyId != null) query.set ('id', String (historyId)) else query.delete ('id') const suffix = (translated != null && (view === 'edit' || view === 'diff')) ? `/${view}` : '' return switchLocalePath ({ pathname: view === 'history' ? location.pathname : `/wiki/${encodeURIComponent (destination)}${suffix}`, search: query.size === 0 ? '' : `?${query}`, hash: location.hash }, targetLocale) }