import { LMS_API_BASE_URL } from '../../config/appConfig' import type { PlatformControlActionResponse, PlatformOption } from './types' type AuthFetch = (input: RequestInfo | URL, init?: RequestInit, options?: { invalidateOnRefreshFailure?: boolean }) => Promise export type PlatformControlWarningPayload = { type: 'platform.control.warning' sessionId: string platformId?: string | null instructorPlatformId?: string | null endsAt: string warningAt: string } export type PlatformControlGrantedPayload = { type: 'platform.control.granted' sessionId: string startedAt: string endsAt: string warningAt: string } export type PlatformControlTerminatedPayload = { type: 'platform.control.terminated' sessionId: string platformId?: string | null instructorPlatformId?: string | null reason: string message: string endedAt: string } export function isPlatformUnavailable(platform: PlatformOption): boolean { return ( platform.state === 'locked' || platform.action === '연결 불가' || platform.status.includes('연결 불가') || platform.status.includes('연결 끊김') || (platform.connection ? !platform.connection.headscaleOnline || !platform.connection.agentHealthy : false) ) } export function getPlatformDotClass(platform: PlatformOption): string { if (isPlatformUnavailable(platform)) return 'bg-[#ef4444] shadow-[0_0_6px_rgba(239,68,68,0.55)]' if (platform.state === 'reserved' || platform.control?.status === 'QUEUED') return 'bg-[#f59e0b] shadow-[0_0_6px_rgba(245,158,11,0.55)]' return 'bg-[#2fbda0] shadow-[0_0_6px_rgba(47,189,160,0.55)]' } export async function fetchPlatformStatuses(fetchWithFreshAuth: AuthFetch, platformIds: string[]): Promise & { id: string }>> { const response = await fetchWithFreshAuth(`${LMS_API_BASE_URL}/platform-control/platforms/statuses`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ platformIds }) }, { invalidateOnRefreshFailure: false }) if (!response.ok) return [] const payload = await response.json() as { platforms?: Array & { id: string }> } return payload.platforms ?? [] } export async function connectPlatformControl(fetchWithFreshAuth: AuthFetch, platformId: string): Promise<{ environmentConfigOverride?: unknown }> { const response = await fetchWithFreshAuth(`${LMS_API_BASE_URL}/platform-control/platforms/${encodeURIComponent(platformId)}/connect`, { method: 'POST', }) if (!response.ok) throw new Error('platform-connect failed') return response.json() as Promise<{ environmentConfigOverride?: unknown }> } export async function releasePlatformControl(fetchWithFreshAuth: AuthFetch, platformId: string): Promise { const response = await fetchWithFreshAuth(`${LMS_API_BASE_URL}/platform-control/platforms/${encodeURIComponent(platformId)}/release`, { method: 'POST', }) if (!response.ok) throw new Error('platform-release failed') } export async function extendPlatformControl( fetchWithFreshAuth: AuthFetch, platformId: string, ): Promise { const response = await fetchWithFreshAuth(`${LMS_API_BASE_URL}/platform-control/platforms/${encodeURIComponent(platformId)}/extend`, { method: 'POST', }) const payload = await response.json().catch(() => null) as PlatformControlActionResponse | { message?: string } | null if (!response.ok) { throw new Error(payload && 'message' in payload && payload.message ? payload.message : '제어 시간 연장에 실패했습니다.') } return payload as PlatformControlActionResponse } export async function requestOrCancelPlatformControl( fetchWithFreshAuth: AuthFetch, platform: PlatformOption ): Promise<{ method: 'POST' | 'DELETE'; payload: PlatformControlActionResponse | null }> { const controlStatus = platform.control?.status const method = controlStatus === 'QUEUED' ? 'DELETE' : 'POST' const suffix = controlStatus === 'QUEUED' ? 'queue' : 'request' const response = await fetchWithFreshAuth(`${LMS_API_BASE_URL}/platform-control/platforms/${encodeURIComponent(platform.id)}/${suffix}`, { method, }) if (!response.ok) throw new Error('platform-control failed') const payload = await response.json().catch(() => null) as PlatformControlActionResponse | null return { method, payload } }