import { Injectable, inject, signal } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { firstValueFrom } from 'rxjs'; import { StationConfig } from '../interfaces/station-config'; import { getAppConfig } from './app-config.service'; import { ThemeService } from './theme.service'; /** * Hardcoded defaults — used when the API is unavailable (dev fallback). * Rendered immediately on the initial paint so the page is never blank. */ const DEFAULT_CONFIG: StationConfig = { id: 0, key: 'default', callsign: 'KMTN', name_primary: 'KMountain', name_secondary: 'Flower Radio', tagline: 'Community Radio — Est. 1987', frequency: '98.7 FM', founded_year: 1987, nonprofit_type: '501(c)(3)', ein: '84-XXXXXXX', logo_url: 'svg/small-flower.svg', hero_background_url: 'svg/mountain-landscape.svg', hero_icon_url: 'svg/orange-flower.svg', hero_divider_url: 'svg/mountain-divider.svg', address: '42 Pine Street\nMountain View, CO 80424', phone: '(970) 555-0198', email: 'hello@kmountainflower.org', website: 'kmountainflower.org', donation_url: '', stream_url: '', stream_metadata_url: '', play_store_icon_url: '', play_store_url: '', app_store_embed_html: '', // Social media social_facebook: '', social_twitter: '', social_instagram: '', social_youtube: '', // Page content hero_subtitle: 'Your community-powered, nonprofit radio station — bringing music, stories, and connection to the mountain towns and beyond since 1987.', about_intro: 'For nearly four decades, KMountain Flower Radio has been the voice of our community — a nonprofit, listener-supported radio station dedicated to music, local news, and the stories that bind mountain towns together.', about_donation_text: 'As a 501(c)(3) nonprofit, every donation keeps our airwaves free and our signal strong. Members receive exclusive perks and the satisfaction of knowing they helped make this possible.', schedule_intro: 'All times are local (Mountain Time). Every show is free to listen to live at 98.7 FM or via our online stream.', events_intro: 'Come meet the team, enjoy live music, and support public radio in person. All events are open to the community — friends and family of listeners welcome.', // Color theme defaults (match _variables.scss) color_primary: '#1a3a5c', color_primary_light: '#2a5a8c', color_primary_dark: '#0e2440', color_primary_muted: '#3a6a9c', color_accent: '#e87a2e', color_accent_light: '#f09a4e', color_accent_dark: '#c85a1e', color_accent_muted: '#f0a86a', color_background: '#faf6f0', color_text: '#3a3632', color_success: '#4a9e4f', color_danger: '#c83030', color_info: '#3a8abf', color_white: '#ffffff', color_light: '#f0ebe3', color_medium: '#8a8580', color_black: '#1a1816', }; @Injectable({ providedIn: 'root', }) export class StationConfigService { private http = inject(HttpClient); private themeService = inject(ThemeService); private baseUrl = `${getAppConfig().apiBaseUrl}/api/station-config`; readonly config = signal(DEFAULT_CONFIG); /** Load station config from the API. Falls back to defaults on error. */ async load(): Promise { try { const data = await firstValueFrom(this.http.get(this.baseUrl)); this.config.set(data); this.themeService.apply(data); } catch { // Keep the default config if the API is unavailable. console.warn('StationConfigService: Failed to load config, using defaults.'); } } /** Update station config (admin only). */ async updateConfig(payload: Partial): Promise { const data = await firstValueFrom( this.http.put(this.baseUrl, payload), ); this.config.set(data); this.themeService.apply(data); } /** Upload an image file for station branding (admin only). Returns the relative URL. */ async uploadImage(file: File): Promise { const formData = new FormData(); formData.append('file', file); const response = await firstValueFrom( this.http.post<{ url: string }>(`${getAppConfig().apiBaseUrl}/api/storage/upload`, formData), ); return response.url; } }