import { requestUrl } from "obsidian";

import { VALIDATION_CONSTANTS } from "../constants";
import { logger } from "./logger";

export interface ValidationResult {
    reason?: string;
    recommendedDims?: number;
    valid: boolean;
}

interface HFConfig {
    architectures?: string[];
    d_model?: number;
    dim?: number;
    hidden_size?: number;
}

export async function validateModel(modelId: string): Promise<ValidationResult> {
    const baseUrl = `https://huggingface.co/${modelId}/resolve/main`;

    // Step 1: Check for the Config (Architecture)
    const configUrl = `${baseUrl}/config.json`;

    try {
        const configResp = await requestUrl({ url: configUrl });

        if (configResp.status !== 200) {
            return { reason: "Model repository not found or missing config.json", valid: false };
        }

        const config = configResp.json as HFConfig;
        const supportedArchs = VALIDATION_CONSTANTS.SUPPORTED_ARCHITECTURES;
        // config.architectures is an array, e.g. ["NomicBertModel"]
        const architectures = config.architectures || [];
        const isSupportedArch = architectures.some((arch) => supportedArchs.includes(arch));

        if (!isSupportedArch) {
            return {
                reason: `Unsupported architecture: ${architectures.join(', ')}. Currently supporting: BERT, NomicBERT, MPNet, etc.`,
                valid: false
            };
        }

        // Guess dimensions from config
        const dims: number | undefined = config.hidden_size || config.d_model || config.dim;

        // Step 2: Check for ONNX Files
        const filePathsToCheck = VALIDATION_CONSTANTS.ONNX_PATHS;

        let hasOnnx = false;
        for (const path of filePathsToCheck) {
            // We use a HEAD request (or simple GET with Obsidian's requestUrl) to check existence 
            // requestUrl doesn't strictly support HEAD with clean output in all cases, but we can try just checking 404
            try {
                // We just want to know if it exists. 
                // Since we can't easily do a pure HEAD without downloading body in some environments,
                // we'll try to rely on the fact that if we request it, a 200 means it exists.
                // However, downloading 20MB just to check is bad.
                // Obsidian requestUrl supports method 'HEAD'.
                const resp = await requestUrl({ method: 'HEAD', url: `${baseUrl}/${path}` });
                if (resp.status === 200) {
                    hasOnnx = true;
                    break;
                }
            } catch (e) {
                // 404 throws an error in requestUrl? verify behavior.
                // Usually it just returns status.
                logger.debug(`[Validator] Check failed for ${path}`, e);
            }
        }

        if (!hasOnnx) {
            return {
                reason: "No ONNX weights found. Please use a 'Xenova/' version of this model or one with an 'onnx' folder.",
                valid: false
            };
        }

        return { recommendedDims: dims, valid: true };

    } catch (e) {
        logger.error("Validation error", e);
        return { reason: "Network error or invalid model ID.", valid: false };
    }
}
