import { z } from 'zod';
import { CompanyDatabase } from '../database/db.js';
import { BrregClient } from '../apis/brreg.js';
import { SSBClient } from '../apis/ssb.js';
const MarketLandscapeSchema = z.object({
industry: z.string().describe("NACE-kode for bransje (f.eks. '62' for IT)"),
region: z.string().optional().describe("Region/fylke"),
include_stats: z.boolean().default(true).describe("Inkluder statistikk"),
limit: z.number().default(100).describe("Maksimalt antall selskaper")
});
export async function analyzeMarketLandscape(args: unknown, db: CompanyDatabase, brreg: BrregClient, ssb: SSBClient) {
const params = MarketLandscapeSchema.parse(args);
// Check cache first
const cached = await db.getMarketAnalysis(params.industry, 'landscape', params.region);
if (cached) {
return {
content: [{
type: "text" as const,
text: `📊 MARKEDSANALYSE (fra cache):\n\n${JSON.stringify(cached.data, null, 2)}`
}]
};
}
// Fetch companies in the industry
let companies = await db.searchCompanies({
nace_code: params.industry,
municipality: params.region,
limit: params.limit,
exclude_bankrupt: true
});
// If not enough data, fetch from Brønnøysund
if (companies.length < 10) {
const brregResults = await brreg.searchByNACE(params.industry, params.limit);
for (const company of brregResults) {
await db.insertOrUpdateCompany({
org_nr: company.organisasjonsnummer,
name: company.navn,
organization_form: company.organisasjonsform?.beskrivelse,
nace_code: company.naeringskode1?.kode,
nace_description: company.naeringskode1?.beskrivelse,
employees_count: company.antallAnsatte,
business_municipality: company.forretningsadresse?.kommune,
business_municipality_number: company.forretningsadresse?.kommunenummer,
bankrupt: company.konkurs,
last_updated: new Date().toISOString()
} as any);
}
companies = await db.searchCompanies({
nace_code: params.industry,
municipality: params.region,
limit: params.limit,
exclude_bankrupt: true
});
}
// Calculate market statistics
const totalCompanies = companies.length;
const totalEmployees = companies.reduce((sum, c) => sum + (c.employees_count || 0), 0);
const avgEmployees = totalEmployees / totalCompanies;
// Company size distribution
const sizeDistribution = {
micro: companies.filter(c => !c.employees_count || c.employees_count < 10).length,
small: companies.filter(c => (c.employees_count || 0) >= 10 && (c.employees_count || 0) < 50).length,
medium: companies.filter(c => (c.employees_count || 0) >= 50 && (c.employees_count || 0) < 250).length,
large: companies.filter(c => (c.employees_count || 0) >= 250).length
};
// Top players
const topCompanies = companies
.filter(c => c.employees_count)
.sort((a, b) => (b.employees_count || 0) - (a.employees_count || 0))
.slice(0, 10);
const naceDescription = companies[0]?.nace_description || 'Ukjent bransje';
// Fetch SSB statistics for industry context
let ssbStats = null;
if (params.include_stats) {
try {
ssbStats = await ssb.getIndustryContext(params.industry);
} catch (error) {
console.error('Error fetching SSB stats:', error);
}
}
const report = `
🏭 MARKEDSLANDSKAP: ${naceDescription} (NACE ${params.industry})
${params.region ? `📍 Region: ${params.region}` : '🌍 Hele Norge'}
📊 MARKEDSOVERSIKT:
- Totalt antall aktører: ${totalCompanies}
- Totalt antall ansatte: ${totalEmployees.toLocaleString()}
- Gjennomsnittlig størrelse: ${avgEmployees.toFixed(0)} ansatte
${ssbStats ? `
📈 SSB STATISTIKK:
${ssbStats.employment ? `- ${ssbStats.employment.description} (${ssbStats.employment.period})` : ''}
${ssbStats.production ? `- ${ssbStats.production.description}` : ''}
${ssbStats.highGrowth ? `- ${ssbStats.highGrowth.description} (${ssbStats.highGrowth.period})` : ''}
${ssbStats.newEnterprises ? `- ${ssbStats.newEnterprises.description}` : ''}
` : ''}
📈 STØRRELSESFORDELING:
- 👤 Mikrobedrifter (<10 ans): ${sizeDistribution.micro} (${((sizeDistribution.micro/totalCompanies)*100).toFixed(0)}%)
- 🏢 Små bedrifter (10-49): ${sizeDistribution.small} (${((sizeDistribution.small/totalCompanies)*100).toFixed(0)}%)
- 🏭 Mellomstore (50-249): ${sizeDistribution.medium} (${((sizeDistribution.medium/totalCompanies)*100).toFixed(0)}%)
- 🌟 Store bedrifter (250+): ${sizeDistribution.large} (${((sizeDistribution.large/totalCompanies)*100).toFixed(0)}%)
🏆 TOPP 10 AKTØRER (etter ansatte):
${topCompanies.map((c, idx) =>
`${idx + 1}. ${c.name}
👥 ${c.employees_count} ansatte
📍 ${c.business_municipality || 'Ukjent'}
📋 ${c.org_nr}`
).join('\n\n')}
💡 Bruk 'analyze_growth' for å se hvilke aktører vokser raskest.
`;
// Cache the analysis
await db.cacheMarketAnalysis({
nace_code: params.industry,
analysis_type: 'landscape',
region: params.region || null,
data: {
totalCompanies,
totalEmployees,
avgEmployees,
sizeDistribution,
topCompanies: topCompanies.map(c => ({ name: c.name, org_nr: c.org_nr, employees: c.employees_count }))
}
});
return {
content: [{
type: "text" as const,
text: report
}]
};
}