"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildGovernanceUploadPayload = buildGovernanceUploadPayload;
exports.buildGovernanceUploadPayloadForWorkspace = buildGovernanceUploadPayloadForWorkspace;
const path = __importStar(require("node:path"));
const node_fs_1 = require("node:fs");
const governanceContracts_1 = require("./governanceContracts");
const governanceGitMetadata_1 = require("./governanceGitMetadata");
const architectureConfigPathRelative = '.archpilot/architecture.json';
const validationStatusPathRelative = '.archpilot/validation-status.json';
const architectureSummaryPathRelative = '.archpilot/reports/architecture-summary.json';
const architectureReviewReportPathRelative = '.archpilot/reports/architecture-review-report.json';
const architectureMapPathRelative = '.archpilot/reports/architecture-map.json';
function asRecord(value) {
    return value && typeof value === 'object' && !Array.isArray(value)
        ? value
        : undefined;
}
function asNumber(value, fallback = 0) {
    return typeof value === 'number' && Number.isFinite(value) ? value : fallback;
}
function asCount(value) {
    return typeof value === 'number' && Number.isFinite(value) && value >= 0
        ? Math.floor(value)
        : undefined;
}
function asString(value) {
    return typeof value === 'string' && value.trim().length > 0 ? value.trim() : undefined;
}
function asStringArray(value) {
    if (!Array.isArray(value)) {
        return [];
    }
    return value
        .filter((entry) => typeof entry === 'string' && entry.trim().length > 0)
        .map((entry) => entry.trim())
        .sort((left, right) => left.localeCompare(right));
}
function normalizeSeverity(value) {
    return value?.toLowerCase() ?? 'info';
}
function normalizeFindingStatus(value) {
    if (!value) {
        return 'open';
    }
    const normalized = value.toLowerCase();
    return normalized === 'active' ? 'open' : normalized;
}
function normalizeConfigCollection(value) {
    if (Array.isArray(value)) {
        const entries = value
            .map((entry) => asRecord(entry))
            .filter((entry) => !!entry)
            .map((entry) => ({ ...entry }));
        return entries.length > 0 ? entries : undefined;
    }
    const record = asRecord(value);
    if (!record) {
        return undefined;
    }
    const entries = [];
    for (const [id, entry] of Object.entries(record)) {
        const normalized = asRecord(entry);
        if (normalized) {
            entries.push({ ...normalized, id });
        }
    }
    entries.sort((left, right) => String(left.id ?? '').localeCompare(String(right.id ?? '')));
    return entries.length > 0 ? entries : undefined;
}
function normalizeComponents(architectureConfig) {
    return normalizeConfigCollection(architectureConfig?.components);
}
function normalizeResources(architectureConfig) {
    return normalizeConfigCollection(architectureConfig?.resources);
}
function normalizeLowercase(value) {
    const normalized = asString(value);
    return normalized ? normalized.toLowerCase() : null;
}
function normalizeRequiredString(value, fallback) {
    const normalized = value?.trim();
    return normalized && normalized.length > 0 ? normalized : fallback;
}
function normalizeOrganizationName(slug) {
    return slug
        .split(/[-_]/u)
        .filter((part) => part.length > 0)
        .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
        .join(' ');
}
function deriveOrganizationSlug(input) {
    const configured = asString(input.projectIdentity?.organizationId);
    if (configured) {
        return configured;
    }
    const repositorySlug = input.gitMetadata?.repositorySlug;
    if (repositorySlug) {
        const parts = repositorySlug.split('/');
        if (parts.length >= 2) {
            return parts[1];
        }
    }
    return `${path.basename(input.workspaceRoot)}-org`;
}
function isCiEnvironment(environment) {
    return environment.CI === 'true' || typeof environment.GITHUB_ACTIONS === 'string';
}
function resolveRequestedUploadMode(environment) {
    const explicit = asString(environment.ARCHPILOT_UPLOAD_MODE);
    if (explicit) {
        return explicit.toLowerCase();
    }
    return undefined;
}
function readEnvironmentIdentity(environment) {
    const branch = asString(environment.GITHUB_REF_NAME) ??
        asString(environment.CI_COMMIT_REF_NAME) ??
        asString(environment.BRANCH_NAME) ??
        null;
    const commitSha = asString(environment.GITHUB_SHA) ??
        asString(environment.CI_COMMIT_SHA) ??
        asString(environment.COMMIT_SHA) ??
        null;
    return { branch, commitSha };
}
function countConfiguredModules(architectureConfig) {
    const modules = asRecord(architectureConfig?.modules);
    return modules ? Object.keys(modules).length : 0;
}
function countMappedModules(architectureMap) {
    const summaryCounts = asRecord(architectureMap?.summaryCounts);
    const moduleCount = summaryCounts?.moduleCount;
    return typeof moduleCount === 'number' && Number.isFinite(moduleCount)
        ? moduleCount
        : 0;
}
function normalizeOrganization(input) {
    const slug = deriveOrganizationSlug(input);
    return {
        slug,
        name: normalizeOrganizationName(slug),
    };
}
function resolveRepositoryContract(input) {
    const repositorySlug = input.gitMetadata?.repositorySlug ??
        input.projectIdentity?.repositoryId ??
        path.basename(input.workspaceRoot);
    const repositoryName = input.gitMetadata?.repositoryName ??
        path.basename(repositorySlug) ??
        path.basename(input.workspaceRoot);
    return {
        externalRepositoryId: repositorySlug,
        repositoryId: repositorySlug,
        name: repositoryName,
        url: normalizeRequiredString(input.projectIdentity?.repositoryUrl ?? input.gitMetadata?.repositoryUrl, `https://${repositorySlug}`),
        defaultBranch: normalizeRequiredString(input.projectIdentity?.defaultBranch ?? input.gitMetadata?.defaultBranch, 'main'),
    };
}
function normalizeFindings(value) {
    const findings = Array.isArray(value) ? value : [];
    const severityRank = {
        error: 0,
        warning: 1,
        info: 2,
    };
    return findings
        .map((entry) => asRecord(entry))
        .filter((entry) => !!entry)
        .map((entry) => {
        const metadata = {};
        for (const [key, value] of Object.entries(entry)) {
            if (key === 'id' ||
                key === 'category' ||
                key === 'severity' ||
                key === 'status' ||
                key === 'kind' ||
                key === 'module' ||
                key === 'target' ||
                key === 'filePath' ||
                key === 'table' ||
                key === 'api' ||
                key === 'message' ||
                key === 'sourceFile' ||
                key === 'title' ||
                key === 'sourceComponentId' ||
                key === 'sourceComponentName' ||
                key === 'targetComponentId' ||
                key === 'targetComponentName' ||
                key === 'dependencyType') {
                continue;
            }
            metadata[key] = value;
        }
        return {
            ruleId: asString(entry.id) ?? 'UNKNOWN',
            category: asString(entry.category) ?? 'unknown',
            severity: normalizeSeverity(asString(entry.severity)),
            status: normalizeFindingStatus(asString(entry.status)),
            findingType: asString(entry.kind) ?? 'violation',
            ...(asString(entry.module) ? { module: asString(entry.module) } : {}),
            ...(asString(entry.target) ? { target: asString(entry.target) } : {}),
            ...(asString(entry.filePath) ? { filePath: asString(entry.filePath) } : {}),
            ...(asString(entry.table) ? { tableName: asString(entry.table) } : {}),
            ...(asString(entry.api) ? { apiName: asString(entry.api) } : {}),
            message: asString(entry.message) ?? '',
            ...(asString(entry.sourceComponentId)
                ? { sourceComponentId: asString(entry.sourceComponentId) }
                : {}),
            ...(asString(entry.sourceComponentName)
                ? { sourceComponentName: asString(entry.sourceComponentName) }
                : {}),
            ...(entry.targetComponentId === null
                ? { targetComponentId: null }
                : asString(entry.targetComponentId)
                    ? { targetComponentId: asString(entry.targetComponentId) }
                    : {}),
            ...(entry.targetComponentName === null
                ? { targetComponentName: null }
                : asString(entry.targetComponentName)
                    ? { targetComponentName: asString(entry.targetComponentName) }
                    : {}),
            ...(asString(entry.dependencyType) ? { dependencyType: asString(entry.dependencyType) } : {}),
            ...(Object.keys(metadata).length > 0 ? { metadata } : {}),
        };
    })
        .sort((left, right) => {
        const leftSeverity = severityRank[left.severity] ?? 3;
        const rightSeverity = severityRank[right.severity] ?? 3;
        if (leftSeverity !== rightSeverity) {
            return leftSeverity - rightSeverity;
        }
        const ruleCompare = left.ruleId.localeCompare(right.ruleId);
        if (ruleCompare !== 0) {
            return ruleCompare;
        }
        const fileCompare = (left.filePath ?? '').localeCompare(right.filePath ?? '');
        if (fileCompare !== 0) {
            return fileCompare;
        }
        return left.message.localeCompare(right.message);
    });
}
function buildGovernanceUploadPayload(input) {
    const validationSummary = asRecord(input.validationStatus.summary) ?? {};
    const architectureSummary = input.architectureSummary;
    const architectureConfig = input.architectureConfig;
    const components = normalizeComponents(architectureConfig);
    const resources = normalizeResources(architectureConfig);
    const findings = normalizeFindings(architectureSummary.findings);
    const changeRisk = asRecord(architectureSummary.changeRisk) ?? {};
    const governanceRisk = asRecord(architectureSummary.risk) ?? {};
    const enforcement = asRecord(architectureSummary.enforcement) ?? {};
    const environment = input.environment ?? process.env;
    const requestedUploadMode = resolveRequestedUploadMode(environment);
    const environmentIdentity = readEnvironmentIdentity(environment);
    const repository = resolveRepositoryContract({
        workspaceRoot: input.workspaceRoot,
        projectIdentity: input.projectIdentity,
        gitMetadata: input.gitMetadata,
    });
    const moduleCount = countMappedModules(input.architectureMap) || countConfiguredModules(architectureConfig);
    const errorCount = asCount(validationSummary.errors) ??
        findings.filter((finding) => finding.severity === 'error').length;
    const warningCount = asCount(validationSummary.warnings) ??
        findings.filter((finding) => finding.severity === 'warning').length;
    const infoCount = asCount(validationSummary.info) ??
        findings.filter((finding) => finding.severity === 'info').length;
    const totalFindings = findings.length > 0 ? findings.length : errorCount + warningCount + infoCount;
    const snapshot = {
        commitSha: normalizeRequiredString(environmentIdentity.commitSha ?? input.gitMetadata?.commitSha, 'unknown'),
        branch: normalizeRequiredString(environmentIdentity.branch ?? input.gitMetadata?.branch, repository.defaultBranch),
        source: requestedUploadMode === 'ci' || isCiEnvironment(environment) ? 'ci' : 'cli',
        architectureScore: asNumber(validationSummary.healthScore, asNumber(architectureSummary.healthScore, 0)),
        setupReadinessScore: asNumber(validationSummary.readinessScore, asNumber(architectureSummary.readinessScore, 0)),
        changeRisk: normalizeRequiredString(normalizeLowercase(changeRisk.riskLevel) ?? undefined, 'low'),
        governanceRisk: normalizeRequiredString(normalizeLowercase(governanceRisk.level) ?? undefined, 'low'),
        enforcement: normalizeRequiredString(normalizeLowercase(enforcement.policyLevel) ??
            normalizeLowercase(enforcement.enforcementDecision) ??
            normalizeLowercase(enforcement.action) ??
            undefined, 'advisory'),
        summary: {
            modules: moduleCount,
            violations: totalFindings,
        },
        findingsCount: {
            total: totalFindings,
            warning: warningCount,
            error: errorCount,
        },
        artifactMeta: {
            cliVersion: input.archpilotVersion,
        },
    };
    const uploadMode = requestedUploadMode ?? (snapshot.source === 'ci' ? 'ci' : 'manual');
    const payload = {
        schemaVersion: 1,
        uploadMode: uploadMode,
        organization: normalizeOrganization({
            projectIdentity: input.projectIdentity,
            gitMetadata: input.gitMetadata,
            workspaceRoot: input.workspaceRoot,
        }),
        repository,
        snapshot,
        findings,
        ...(components ? { components } : {}),
        ...(resources ? { resources } : {}),
        rawPayload: {
            ...(input.architectureConfig ? { architectureConfig: input.architectureConfig } : {}),
            validationStatus: input.validationStatus,
            architectureSummary: input.architectureSummary,
            ...(input.architectureReviewReport
                ? { architectureReviewReport: input.architectureReviewReport }
                : {}),
            ...(input.architectureMap ? { architectureMap: input.architectureMap } : {}),
        },
    };
    const validationErrors = (0, governanceContracts_1.validateGovernanceUploadPayload)(payload);
    if (validationErrors.length > 0) {
        throw new Error(`Governance upload payload is invalid: ${validationErrors.join(' ')}`);
    }
    return payload;
}
async function readJsonFile(filePath) {
    let contents;
    try {
        contents = await node_fs_1.promises.readFile(filePath, { encoding: 'utf8' });
    }
    catch (error) {
        if (error.code === 'ENOENT') {
            return { kind: 'missing' };
        }
        return {
            kind: 'invalid',
            details: error instanceof Error ? error.message : 'Unable to read JSON file.',
        };
    }
    try {
        return { kind: 'ok', value: JSON.parse(contents) };
    }
    catch {
        return { kind: 'invalid', details: 'Invalid JSON.' };
    }
}
async function buildGovernanceUploadPayloadForWorkspace(input) {
    const architectureConfigPath = path.join(input.workspaceRoot, ...architectureConfigPathRelative.split('/'));
    const validationStatusPath = path.join(input.workspaceRoot, ...validationStatusPathRelative.split('/'));
    const architectureSummaryPath = path.join(input.workspaceRoot, ...architectureSummaryPathRelative.split('/'));
    const architectureReviewReportPath = path.join(input.workspaceRoot, ...architectureReviewReportPathRelative.split('/'));
    const architectureMapPath = path.join(input.workspaceRoot, ...architectureMapPathRelative.split('/'));
    const [architectureConfigLoaded, architectureMapLoaded, validationStatusLoaded, architectureSummaryLoaded, reviewReportLoaded, gitMetadata,] = await Promise.all([
        readJsonFile(architectureConfigPath),
        readJsonFile(architectureMapPath),
        readJsonFile(validationStatusPath),
        readJsonFile(architectureSummaryPath),
        readJsonFile(architectureReviewReportPath),
        (0, governanceGitMetadata_1.resolveGovernanceGitMetadata)(input.workspaceRoot),
    ]);
    if (validationStatusLoaded.kind === 'missing' || architectureSummaryLoaded.kind === 'missing') {
        return {
            kind: 'missing-artifact',
            message: 'Required governance artifacts are missing. Run `archpilot validate` first to generate .archpilot/validation-status.json and .archpilot/reports/architecture-summary.json.',
        };
    }
    if (validationStatusLoaded.kind === 'invalid') {
        return {
            kind: 'invalid-artifact',
            message: `Validation status artifact is invalid. ${validationStatusLoaded.details}`,
        };
    }
    if (architectureSummaryLoaded.kind === 'invalid') {
        return {
            kind: 'invalid-artifact',
            message: `Architecture summary artifact is invalid. ${architectureSummaryLoaded.details}`,
        };
    }
    const validationStatus = asRecord(validationStatusLoaded.value);
    const architectureSummary = asRecord(architectureSummaryLoaded.value);
    const architectureConfig = architectureConfigLoaded.kind === 'ok' ? asRecord(architectureConfigLoaded.value) : undefined;
    const architectureMap = architectureMapLoaded.kind === 'ok' ? asRecord(architectureMapLoaded.value) : undefined;
    if (!validationStatus || !architectureSummary) {
        return {
            kind: 'invalid-artifact',
            message: 'Governance artifact JSON shape is invalid. Run `archpilot validate` to regenerate artifacts.',
        };
    }
    const reviewReport = reviewReportLoaded.kind === 'ok' ? asRecord(reviewReportLoaded.value) : undefined;
    return {
        kind: 'ok',
        payload: buildGovernanceUploadPayload({
            workspaceRoot: input.workspaceRoot,
            projectIdentity: input.projectIdentity,
            ...(architectureConfig ? { architectureConfig } : {}),
            ...(architectureMap ? { architectureMap } : {}),
            validationStatus,
            architectureSummary,
            ...(reviewReport ? { architectureReviewReport: reviewReport } : {}),
            uploadedAt: input.uploadedAt ?? new Date().toISOString(),
            archpilotVersion: input.archpilotVersion ?? 'unknown',
            environment: input.environment,
            gitMetadata,
        }),
    };
}
//# sourceMappingURL=governanceUploadPayload.js.map