import { DataLoader } from '../utils/dataLoader.js';
import { ToolResponse } from '../types/stateData.js';
import {
validateStateName,
validateProjectedRevenue,
validateLicenseType,
handleToolError,
GamblingRegulationsError,
ErrorCode,
logger
} from '../utils/errorHandler.js';
export const calculateFeesTool = {
name: "calculate_fees",
description: "Calculate licensing fees based on projected revenue for a specific state",
inputSchema: {
type: "object",
properties: {
state: {
type: "string",
description: "State jurisdiction for fee calculation"
},
license_type: {
type: "string",
description: "Type of gambling license (e.g., 'sports-betting', 'online-casino', 'interactive-gaming')"
},
projected_revenue: {
type: "number",
description: "Projected annual gross gaming revenue in USD"
}
},
required: ["state", "license_type", "projected_revenue"]
}
};
function formatCurrency(amount: number): string {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
minimumFractionDigits: 0,
maximumFractionDigits: 0,
}).format(amount);
}
export async function handleCalculateFees(
args: { state: string; license_type: string; projected_revenue: number },
dataLoader: DataLoader
): Promise<ToolResponse> {
try {
logger.info('calculate_fees called', args);
validateStateName(args.state);
validateLicenseType(args.license_type);
validateProjectedRevenue(args.projected_revenue);
const stateData = await dataLoader.loadStateData(args.state);
if (!stateData.taxation) {
return {
content: [{
type: "text",
text: JSON.stringify({
state: stateData.state_name,
warning: "LIMITED TAX DATA",
message: `Tax structure information for ${stateData.state_name} is not available in the database.`,
recommendation: "Refer to original research documentation for tax calculations."
}, null, 2)
}]
};
}
const taxation = stateData.taxation as any;
let taxRate = 0;
let taxStructure = "unknown";
let annualTax = 0;
let taxNote = "";
// Enhanced tax rate detection
if (args.license_type.includes('sports') || args.license_type.includes('betting')) {
if (taxation.mobile_sports_betting) {
taxRate = taxation.mobile_sports_betting.rate || 0;
taxNote = taxation.mobile_sports_betting.note || "";
taxStructure = "flat_percentage";
} else if (taxation.retail_sports_betting) {
taxRate = taxation.retail_sports_betting.rate || 0;
taxStructure = "flat_percentage";
} else if (taxation.sports_betting) {
taxRate = taxation.sports_betting.rate || 0;
taxStructure = "flat_percentage";
} else if (taxation.casino_gaming_tax) {
taxRate = taxation.casino_gaming_tax.rates?.[taxation.casino_gaming_tax.rates.length - 1]?.rate || 0;
taxStructure = "graduated";
}
} else if (args.license_type.includes('casino') || args.license_type.includes('gaming')) {
if (taxation.interactive_gaming) {
const igaming = taxation.interactive_gaming;
taxRate = igaming.online_slots?.rate || igaming.rate || 0;
taxStructure = "flat_percentage";
} else if (taxation.interactive_gaming_proposed) {
taxRate = taxation.interactive_gaming_proposed.rate || 0;
taxStructure = "flat_percentage";
taxNote = "Proposed rate - pending legislation";
}
}
if (taxRate > 0) {
annualTax = args.projected_revenue * (taxRate / 100);
}
// Enhanced license fee detection
let applicationFee = 0;
let annualFee = 0;
if (taxation.license_fees) {
const fees = taxation.license_fees;
if (args.license_type.includes('sports')) {
applicationFee = fees.mobile_sports_betting?.platform_provider_fee || 0;
annualFee = fees.mobile_sports_betting?.annual_operator_fee || 0;
} else if (args.license_type.includes('casino')) {
applicationFee = fees.downstate_casino?.license_fee ||
fees.interactive_gaming_proposed?.operator_license || 0;
}
}
if (stateData.license_types && applicationFee === 0) {
const licenseTypes = stateData.license_types as any;
for (const key of Object.keys(licenseTypes)) {
if (key.toLowerCase().includes(args.license_type.toLowerCase().replace('-', '_'))) {
const license = licenseTypes[key];
applicationFee = license.application_fee || license.initial_license_fee ||
license.fees?.initial_certificate_fee || 0;
annualFee = license.annual_fee || license.annual_renewal_fee ||
license.fees?.renewal_fee || 0;
break;
}
}
}
const response = {
state: stateData.state_name,
license_type: args.license_type,
inputs: {
projected_annual_revenue: formatCurrency(args.projected_revenue),
projected_annual_revenue_raw: args.projected_revenue
},
fees: {
application_fee: formatCurrency(applicationFee),
application_fee_raw: applicationFee,
annual_license_fee: formatCurrency(annualFee),
annual_license_fee_raw: annualFee
},
tax_calculation: {
tax_rate: `${taxRate}%`,
tax_structure: taxStructure,
annual_tax: formatCurrency(annualTax),
annual_tax_raw: annualTax,
note: taxNote || undefined
},
total_costs: {
first_year_total: formatCurrency(applicationFee + annualFee + annualTax),
first_year_total_raw: applicationFee + annualFee + annualTax,
subsequent_years_total: formatCurrency(annualFee + annualTax),
subsequent_years_total_raw: annualFee + annualTax
}
};
return {
content: [{
type: "text",
text: JSON.stringify(response, null, 2)
}]
};
} catch (error) {
return handleToolError(error);
}
}