// #region GitUtils [C:2] [TYPE Module] [SEMANTICS git, utils, helper, normalize, parse]
// @BRIEF Shared utility functions extracted from GitManager.svelte.

/**
 * Normalize environment stage with legacy fallback.
 * Returns DEV/PREPROD/PROD.
 */
export function normalizeEnvStage(env: Record<string, unknown> | null | undefined): string {
    if (env?.is_production) return 'PROD';
    const stage = String(env?.stage || '').trim().toUpperCase();
    if (stage === 'PROD' || stage === 'PREPROD') return stage;
    return 'DEV';
}

/**
 * Return visual class for environment stage badges.
 */
export function stageBadgeClass(stage: string): string {
    if (stage === 'PROD') return 'bg-red-100 text-red-800 border-red-200';
    if (stage === 'PREPROD') return 'bg-amber-100 text-amber-800 border-amber-200';
    return 'bg-blue-100 text-blue-800 border-blue-200';
}

/**
 * Resolve active environment id for current dashboard session.
 */
export function resolveCurrentEnvironmentId(envId: string | null | undefined): string | null {
    if (envId) return String(envId);
    if (typeof window === 'undefined') return null;
    return localStorage.getItem('selected_env_id');
}

/**
 * Apply GitFlow defaults by current environment stage.
 */
export function applyGitflowStageDefaults(stage: string): {
    promoteFromBranch: string;
    promoteToBranch: string;
    preferredDeployTargetStage: string;
} {
    const normalizedStage = String(stage || '').toUpperCase();
    if (normalizedStage === 'DEV') {
        return { promoteFromBranch: 'dev', promoteToBranch: 'preprod', preferredDeployTargetStage: 'PREPROD' };
    }
    if (normalizedStage === 'PREPROD') {
        return { promoteFromBranch: 'preprod', promoteToBranch: 'main', preferredDeployTargetStage: 'PROD' };
    }
    return { promoteFromBranch: 'main', promoteToBranch: 'main', preferredDeployTargetStage: '' };
}

/**
 * Checks whether current dashboard reference is numeric ID.
 */
export function isNumericDashboardRef(dashboardId: string | number | null | undefined): boolean {
    return /^\d+$/.test(String(dashboardId || '').trim());
}

/**
 * Return currently selected git server config.
 */
export function getSelectedConfig<T extends { id: string }>(configs: T[], selectedConfigId: string | null | undefined): T | null {
    return configs.find((item) => item.id === selectedConfigId) || null;
}

/**
 * Resolve default git config for current session.
 */
export function resolveDefaultConfig<T extends { id: string; is_default?: boolean; status?: string }>(
    configList: T[], selectedConfigId: string | null | undefined
): T | null {
    if (!Array.isArray(configList) || configList.length === 0) return null;
    const selected = configList.find((item) => item.id === selectedConfigId);
    if (selected) return selected;
    const explicitDefault = configList.find((item) => item?.is_default);
    if (explicitDefault) return explicitDefault;
    const connected = configList.find((item) => item?.status === 'CONNECTED');
    return connected || configList[0];
}

/**
 * Resolve lower-case provider label for auto-push checkbox.
 */
export function resolvePushProviderLabel<T extends { id: string; provider?: string; is_default?: boolean; status?: string }>(
    configs: T[], selectedConfigId: string | null | undefined, repositoryProvider: string
): string {
    const config = getSelectedConfig(configs, selectedConfigId) || resolveDefaultConfig(configs, selectedConfigId);
    const provider = String(config?.provider || repositoryProvider || '').trim().toLowerCase();
    return provider || 'git';
}

/**
 * Extract comparable host[:port] from URL string.
 */
export function extractHttpHost(urlValue: string | null | undefined): string {
    const normalized = String(urlValue || '').trim();
    if (!normalized) return '';
    try {
        const parsed = new URL(normalized);
        if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') return '';
        return String(parsed.host || '').toLowerCase();
    } catch (_e) {
        return '';
    }
}

/**
 * Build deterministic repository name from dashboard title/id.
 */
export function buildSuggestedRepoName(dashboardTitle: string, dashboardId: string | number): string {
    const source = (dashboardTitle || `dashboard-${dashboardId}`).toLowerCase();
    const slug = source
        .replace(/[^a-z0-9]+/g, '-')
        .replace(/^-+|-+$/g, '')
        .slice(0, 48);
    return `${slug || 'dashboard'}-${dashboardId}`;
}

/**
 * Attempt to parse a JSON object from a string.
 */
export function tryParseJsonObject(value: string): Record<string, unknown> | null {
    const source = String(value || '').trim();
    if (!source.startsWith('{') || !source.endsWith('}')) return null;
    try {
        const parsed = JSON.parse(source);
        return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed as Record<string, unknown> : null;
    } catch (_e) {
        return null;
    }
}

/**
 * Extract unfinished merge context from a 409 error.
 */
export function extractUnfinishedMergeContext(error: Record<string, unknown> | null | undefined): {
    message: string;
    repositoryPath: string;
    gitDir: string;
    currentBranch: string;
    mergeHead: string;
    mergeMessagePreview: string;
    nextSteps: string[];
    commands: string[];
} | null {
    if (!error || Number(error?.status) !== 409) return null;
    const parsedMessage = tryParseJsonObject(error?.message as string);
    const detail = error?.detail && typeof error.detail === 'object' ? error.detail as Record<string, unknown> : null;
    const payload = detail || parsedMessage;
    if (!payload || payload.error_code !== 'GIT_UNFINISHED_MERGE') return null;

    const commands = Array.isArray(payload.manual_commands)
        ? (payload.manual_commands as unknown[]).filter(Boolean).map((item) => String(item))
        : [];

    const nextSteps = Array.isArray(payload.next_steps)
        ? (payload.next_steps as unknown[]).filter(Boolean).map((item) => String(item))
        : [];

    return {
        message: String(payload.message || ''),
        repositoryPath: String(payload.repository_path || ''),
        gitDir: String(payload.git_dir || ''),
        currentBranch: String(payload.current_branch || ''),
        mergeHead: String(payload.merge_head || ''),
        mergeMessagePreview: String(payload.merge_message_preview || ''),
        nextSteps,
        commands,
    };
}
// #endregion GitUtils
