import { getStats, getMemory, getDisk, getTenants, getUsage, getCredentials, getTasks, getServiceLogs, getCaddyConfig, getClaudeUsage, getSettings } from '$lib/api/admin';
import type { Tenant, Credential, Task, GlobalSettings } from '$lib/types';
import { refresh } from './refresh.svelte';

// ─── Raw API response types ───
interface StatsRaw {
	hostname: string; uptime_hours: any; cpu_cores: any; cpu_model: string;
	load_avg: any; mem_total_gb: any; mem_used_gb: any; mem_free_gb: any;
	mem_percent: any; disk_total_gb: any; disk_used_gb: any; disk_free_gb: any;
	disk_percent: any; container_image: string; platform: string;
	tenant_count: any; service_status: string; service_memory_mb: any;
	db?: {
		file_mb?: any; wal_mb?: any; shm_kb?: any;
		page_count?: any; page_size?: any; freelist_count?: any;
		messages?: any; usage_log?: any; chats?: any; tenants?: any;
	};
}

export interface ParsedStats {
	hostname: string; uptime_hours: number; cpu_cores: number; cpu_model: string;
	load_avg: number[]; mem_total_gb: number; mem_used_gb: number; mem_free_gb: number;
	mem_percent: number; disk_total_gb: number; disk_used_gb: number; disk_free_gb: number;
	disk_percent: number; container_image: string; platform: string;
	tenant_count: number; service_status: string; service_memory_mb: number;
	db?: {
		file_mb: number; wal_mb: number; shm_kb: number;
		page_count: number; page_size: number; freelist_count: number;
		messages: number; usage_log: number; chats: number; tenants: number;
	};
}

export interface ParsedMemory {
	host_total_mb: number; host_used_mb: number; host_free_mb: number;
	system_mb: number; nanoclaw_mb: number;
	tenants: { id: string; current_mb: number; limit_mb: number }[];
}

export interface ParsedDisk {
	host_total_gb: number;
	tenants: { id: string; allocated_mb: number; actual_mb: number; used_mb: number; avail_mb: number; limit_mb: number }[];
}

export interface ParsedUsage {
	totals: any[];
	daily: any[];
	channels: any[];
	limits: any[];
}

function parseStats(s: any): ParsedStats {
	return {
		...s,
		load_avg: typeof s.load_avg === 'string'
			? s.load_avg.split(',').map((v: string) => parseFloat(v.trim()))
			: (Array.isArray(s.load_avg) ? s.load_avg.map(Number) : [0, 0, 0]),
		mem_total_gb: parseFloat(s.mem_total_gb) || 0,
		mem_used_gb: parseFloat(s.mem_used_gb) || 0,
		mem_free_gb: parseFloat(s.mem_free_gb) || 0,
		mem_percent: parseFloat(s.mem_percent) || 0,
		disk_total_gb: parseFloat(s.disk_total_gb) || 0,
		disk_used_gb: parseFloat(s.disk_used_gb) || 0,
		disk_free_gb: parseFloat(s.disk_free_gb) || 0,
		disk_percent: parseFloat(s.disk_percent) || 0,
		uptime_hours: parseFloat(s.uptime_hours) || 0,
		cpu_cores: parseInt(s.cpu_cores) || 0,
		tenant_count: parseInt(s.tenant_count) || 0,
		service_memory_mb: parseFloat(s.service_memory_mb) || 0,
		db: s.db ? {
			file_mb: parseFloat(s.db.file_mb) || 0,
			wal_mb: parseFloat(s.db.wal_mb) || 0,
			shm_kb: parseFloat(s.db.shm_kb) || 0,
			page_count: parseInt(s.db.page_count) || 0,
			page_size: parseInt(s.db.page_size) || 0,
			freelist_count: parseInt(s.db.freelist_count) || 0,
			messages: parseInt(s.db.messages) || 0,
			usage_log: parseInt(s.db.usage_log) || 0,
			chats: parseInt(s.db.chats) || 0,
			tenants: parseInt(s.db.tenants) || 0,
		} : undefined,
	};
}

function mapUsage(raw: any): ParsedUsage {
	return {
		totals: (raw.totals || []).map((r: any) => ({
			tenant_id: r.tenant_id,
			requests: r.requests ?? 0,
			duration_ms: r.total_duration_ms ?? r.duration_ms ?? 0,
			input_tokens: r.total_input_tokens ?? r.input_tokens ?? 0,
			output_tokens: r.total_output_tokens ?? r.output_tokens ?? 0,
			cache_creation_tokens: r.total_cache_creation ?? r.cache_creation_tokens ?? 0,
			cache_read_tokens: r.total_cache_read ?? r.cache_read_tokens ?? 0,
		})),
		daily: (raw.daily || []).map((r: any) => ({
			date: r.day ?? r.date,
			tenant_id: r.tenant_id,
			requests: r.requests ?? 0,
			duration_ms: r.total_duration_ms ?? r.duration_ms ?? 0,
			input_tokens: r.total_input_tokens ?? r.input_tokens ?? 0,
			output_tokens: r.total_output_tokens ?? r.output_tokens ?? 0,
		})),
		channels: (raw.channels || []).map((r: any) => ({
			group_folder: r.group_folder,
			tenant_id: r.tenant_id,
			requests: r.requests ?? 0,
			duration_ms: r.total_duration_ms ?? r.duration_ms ?? 0,
		})),
		limits: raw.limits || [],
	};
}

function createDataStore() {
	// ─── State ───
	let stats = $state<ParsedStats | null>(null);
	let settings = $state<GlobalSettings | null>(null);
	let memory = $state<ParsedMemory | null>(null);
	let disk = $state<ParsedDisk | null>(null);
	let tenants = $state<Tenant[]>([]);
	let credentials = $state<Credential[]>([]);
	let tasks = $state<Task[]>([]);
	let usage = $state<ParsedUsage | null>(null);
	let usageDays = $state(7);
	let serviceLogs = $state('');
	let caddyConfig = $state<{ systemConfig: string; tenantFiles: any[] } | null>(null);
	let claudeUsage = $state<any[] | null>(null);
	let claudeUsageLoading = $state(false);

	let initialLoaded = $state(false);
	let fetching = $state(false);

	async function fetchAll() {
		fetching = true;
		if (initialLoaded) refresh.markRefreshing();
		try {
			const [sRaw, setRaw, mRaw, dRaw, t, c, tk, uRaw, logs, caddy] = await Promise.all([
				getStats().catch(() => null) as Promise<any>,
				getSettings().catch(() => null) as Promise<any>,
				getMemory().catch(() => null) as Promise<any>,
				getDisk().catch(() => null) as Promise<any>,
				getTenants().catch(() => []),
				getCredentials().catch(() => []),
				getTasks().catch(() => []),
				getUsage(usageDays).catch(() => null) as Promise<any>,
				getServiceLogs().catch(() => ({ logs: '' })),
				getCaddyConfig().catch(() => null),
			]);

			if (sRaw) stats = parseStats(sRaw);
			if (setRaw) settings = setRaw;
			if (mRaw) {
				memory = {
					host_total_mb: mRaw.host_total_mb,
					host_used_mb: mRaw.host_used_mb,
					host_free_mb: mRaw.host_free_mb,
					system_mb: mRaw.system_mb,
					nanoclaw_mb: mRaw.nanoclaw_mb,
					tenants: mRaw.slices || [],
				};
			}
			if (dRaw) {
				disk = {
					host_total_gb: typeof dRaw.host_total_mb === 'number' ? dRaw.host_total_mb / 1024 : parseFloat(dRaw.host_total_gb) || 0,
					tenants: dRaw.volumes || dRaw.tenants || [],
				};
			}
			tenants = t;
			credentials = c;
			tasks = tk;
			if (uRaw) usage = mapUsage(uRaw);
			serviceLogs = logs.logs || '';
			if (caddy) caddyConfig = caddy;

			refresh.markUpdated();
			initialLoaded = true;
			// Claude usage probe is slow (makes real API calls) — fetch in background
			refetchClaudeUsage();
		} catch (e) {
			console.error('Data fetch error:', e);
		} finally {
			fetching = false;
		}
	}

	async function refetchClaudeUsage() {
		claudeUsageLoading = true;
		try {
			const result = await getClaudeUsage();
			claudeUsage = result.tokens || [];
		} catch {
			claudeUsage = [];
		} finally {
			claudeUsageLoading = false;
		}
	}

	async function refetchUsage(days: number) {
		usageDays = days;
		try {
			const raw = await getUsage(days) as any;
			if (raw) usage = mapUsage(raw);
		} catch {}
	}

	async function refetchLogs() {
		try {
			const result = await getServiceLogs();
			serviceLogs = result.logs || '';
		} catch {}
	}

	async function refetchCaddy() {
		try {
			const result = await getCaddyConfig();
			if (result) caddyConfig = result;
		} catch {}
	}

	// Allow pages to trigger a re-fetch of specific data after mutations
	async function refetchTenants() {
		try {
			const [t, c] = await Promise.all([getTenants(), getCredentials()]);
			tenants = t;
			credentials = c;
		} catch {}
	}

	function upsertTenant(tenant: Tenant) {
		const idx = tenants.findIndex((t) => t.id === tenant.id);
		if (idx === -1) {
			tenants = [tenant, ...tenants];
			return;
		}
		tenants = tenants.map((t) => (t.id === tenant.id ? tenant : t));
	}

	function removeTenant(tenantId: string) {
		tenants = tenants.filter((t) => t.id !== tenantId);
	}

	async function refetchTasks() {
		try {
			tasks = await getTasks();
		} catch {}
	}

	function upsertTask(task: Task) {
		const idx = tasks.findIndex((t) => t.id === task.id);
		if (idx === -1) {
			tasks = [task, ...tasks];
			return;
		}
		tasks = tasks.map((t) => (t.id === task.id ? task : t));
	}

	function removeTask(taskId: string) {
		tasks = tasks.filter((t) => t.id !== taskId);
	}

	async function refetchCredentials() {
		try {
			credentials = await getCredentials();
		} catch {}
	}

	function upsertCredential(credential: Credential) {
		const idx = credentials.findIndex((c) => c.id === credential.id);
		if (idx === -1) {
			credentials = [...credentials, credential];
			return;
		}
		credentials = credentials.map((c) => (c.id === credential.id ? credential : c));
	}

	function removeCredential(credentialId: string) {
		credentials = credentials.filter((c) => c.id !== credentialId);
	}

	async function refetchSettings() {
		try {
			settings = await getSettings();
		} catch {}
	}

	return {
		get stats() { return stats; },
		get settings() { return settings; },
		get memory() { return memory; },
		get disk() { return disk; },
		get tenants() { return tenants; },
		get credentials() { return credentials; },
		get tasks() { return tasks; },
		get usage() { return usage; },
		get usageDays() { return usageDays; },
		get serviceLogs() { return serviceLogs; },
		get caddyConfig() { return caddyConfig; },
		get claudeUsage() { return claudeUsage; },
		get claudeUsageLoading() { return claudeUsageLoading; },
		get initialLoaded() { return initialLoaded; },
		get fetching() { return fetching; },
		fetchAll,
		refetchUsage,
		refetchLogs,
		refetchCaddy,
		refetchTenants,
		upsertTenant,
		removeTenant,
		refetchTasks,
		upsertTask,
		removeTask,
		refetchCredentials,
		upsertCredential,
		removeCredential,
		refetchClaudeUsage,
		refetchSettings,
	};
}

export const data = createDataStore();
