// ============================================
// JSON Validation Utilities
// Type-safe parsing with structural validation
// ============================================

import type { GameSettings, Team, Round, FinalRound } from '$lib/types/kuldvillak';

/**
 * Result type for validation operations
 */
export type ValidationResult<T> =
    | { success: true; data: T }
    | { success: false; error: string };

/**
 * Validate that a value is a non-null object
 */
function isObject(value: unknown): value is Record<string, unknown> {
    return typeof value === 'object' && value !== null && !Array.isArray(value);
}

/**
 * Validate that a value is an array
 */
function isArray(value: unknown): value is unknown[] {
    return Array.isArray(value);
}

/**
 * Validate that a value is a string
 */
function isString(value: unknown): value is string {
    return typeof value === 'string';
}

/**
 * Validate that a value is a number
 */
function isNumber(value: unknown): value is number {
    return typeof value === 'number' && !isNaN(value);
}

/**
 * Game data structure for import/export
 */
export interface GameData {
    name?: string;
    settings: GameSettings;
    teams: Team[];
    rounds: Round[];
    finalRound?: FinalRound | null;
}

/**
 * Validate and parse game data from unknown input
 * @param data Unknown data to validate
 * @returns Validation result with typed data or error message
 */
export function validateGameData(data: unknown): ValidationResult<GameData> {
    if (!isObject(data)) {
        return { success: false, error: 'Invalid data format: expected object' };
    }

    // Validate required fields exist
    if (!isObject(data.settings)) {
        return { success: false, error: 'Missing or invalid settings' };
    }

    if (!isArray(data.teams)) {
        return { success: false, error: 'Missing or invalid teams array' };
    }

    if (!isArray(data.rounds)) {
        return { success: false, error: 'Missing or invalid rounds array' };
    }

    // Validate teams structure
    for (let i = 0; i < data.teams.length; i++) {
        const team = data.teams[i];
        if (!isObject(team)) {
            return { success: false, error: `Invalid team at index ${i}` };
        }
        if (!isString(team.id)) {
            return { success: false, error: `Team ${i} missing id` };
        }
        if (!isString(team.name)) {
            return { success: false, error: `Team ${i} missing name` };
        }
    }

    // Validate rounds structure
    for (let i = 0; i < data.rounds.length; i++) {
        const round = data.rounds[i];
        if (!isObject(round)) {
            return { success: false, error: `Invalid round at index ${i}` };
        }
        if (!isArray(round.categories)) {
            return { success: false, error: `Round ${i} missing categories` };
        }
    }

    // Clean up legacy properties from settings
    const settingsObj = data.settings as Record<string, unknown>;
    const { teamColors, ...cleanSettings } = settingsObj;

    // Build validated game data
    const gameData: GameData = {
        name: isString(data.name) ? data.name : undefined,
        settings: cleanSettings as unknown as GameSettings,
        teams: data.teams.map((t) => {
            const team = t as Record<string, unknown>;
            return {
                id: team.id as string,
                name: team.name as string,
                score: isNumber(team.score) ? team.score : 0,
            };
        }),
        rounds: data.rounds as Round[],
        finalRound: isObject(data.finalRound)
            ? (data.finalRound as unknown as FinalRound)
            : null,
    };

    return { success: true, data: gameData };
}

/**
 * Safely parse JSON string with validation
 * @param jsonString JSON string to parse
 * @returns Validation result with parsed data or error
 */
export function parseJSON<T>(jsonString: string): ValidationResult<T> {
    try {
        const data = JSON.parse(jsonString) as T;
        return { success: true, data };
    } catch (error) {
        return {
            success: false,
            error: error instanceof Error ? error.message : 'Failed to parse JSON'
        };
    }
}

/**
 * Parse and validate game data from JSON string
 * @param jsonString JSON string containing game data
 * @returns Validation result with typed game data or error
 */
export function parseGameData(jsonString: string): ValidationResult<GameData> {
    const parseResult = parseJSON<unknown>(jsonString);
    if (!parseResult.success) {
        return parseResult;
    }
    return validateGameData(parseResult.data);
}
