import { logger } from "../utils/logger.js";
import {
CharityLookupOutput,
PublicCharityCheckOutput,
CharitySearchOutput
} from "../schemas/charity-schemas.js";
export class ResponseFormatter {
/**
* Format charity lookup response for display
*/
static formatCharityLookup(charity: CharityLookupOutput): string {
logger.debug("Formatting charity lookup response", { ein: charity.ein });
const sections: string[] = [];
// Header
sections.push(`# ποΈ Charity Information\n`);
// Basic Information
const basicInfo: string[] = [];
basicInfo.push(`**Name:** ${charity.name}`);
basicInfo.push(`**EIN:** ${charity.ein}`);
if (charity.city || charity.state) {
const location = [charity.city, charity.state].filter(Boolean).join(', ');
const country = charity.country && charity.country !== 'US' ? `, ${charity.country}` : '';
basicInfo.push(`**Location:** ${location}${country}`);
}
sections.push(basicInfo.join('\n'));
// Tax Status Section
if (charity.deductibilityDetail || charity.deductibilityCode || charity.status) {
sections.push(`\n## π° Tax Status`);
const taxInfo: string[] = [];
if (charity.deductibilityDetail) {
taxInfo.push(`**Tax Deductibility:** ${charity.deductibilityDetail}`);
} else if (charity.deductibilityCode) {
taxInfo.push(`**Deductibility Code:** ${charity.deductibilityCode}`);
}
if (charity.status) {
taxInfo.push(`**IRS Status:** ${charity.status}`);
}
sections.push(taxInfo.join('\n'));
}
// Organization Details Section
if (charity.classification || charity.activity || charity.foundation) {
sections.push(`\n## π Organization Details`);
const orgInfo: string[] = [];
if (charity.classification) {
orgInfo.push(`**Classification:** ${charity.classification}`);
}
if (charity.activity) {
orgInfo.push(`**Primary Activity:** ${charity.activity}`);
}
if (charity.foundation) {
orgInfo.push(`**Foundation Type:** ${charity.foundation}`);
}
sections.push(orgInfo.join('\n'));
}
// Legal Information Section
if (charity.ruling) {
sections.push(`\n## βοΈ Legal Information`);
sections.push(`**IRS Ruling:** ${charity.ruling}`);
}
const formatted = sections.join('\n');
logger.debug("Charity lookup formatting completed");
return formatted;
}
/**
* Format public charity check response for display
*/
static formatPublicCharityCheck(result: PublicCharityCheckOutput): string {
logger.debug("Formatting public charity check response", {
ein: result.ein,
isPublicCharity: result.isPublicCharity
});
const status = result.isPublicCharity ? 'β
**Yes**' : 'β **No**';
const deductible = result.deductible ? 'β
**Yes**' : 'β **No**';
let response = `# π Public Charity Status Check\n\n`;
response += `**EIN:** ${result.ein}\n`;
response += `**Public Charity Status:** ${status}\n`;
response += `**Tax-Deductible Donations:** ${deductible}\n\n`;
if (result.isPublicCharity) {
response += `## β
This organization is a public charity\n\n`;
response += `This organization is recognized as a public charity under IRS section 501(c)(3). `;
response += `Donations to this organization are generally **tax-deductible** for donors who itemize deductions.\n\n`;
response += `π‘ **Note:** Always consult with a tax professional for specific advice about deductibility.`;
} else {
response += `## β This organization is not classified as a public charity\n\n`;
response += `This organization is either:\n`;
response += `β’ Not found in the IRS database\n`;
response += `β’ Not a 501(c)(3) organization\n`;
response += `β’ A private foundation rather than a public charity\n\n`;
response += `**β οΈ Important:** Donations may not be tax-deductible.`;
}
logger.debug("Public charity check formatting completed");
return response;
}
/**
* Format charity search response for display
*/
static formatCharitySearch(output: CharitySearchOutput, searchCriteria: any): string {
logger.debug("Formatting charity search response", {
resultCount: output.results.length
});
const { results } = output;
let response = `# π Charity Search Results\n\n`;
// Search summary
const criteria: string[] = [];
if (searchCriteria.query) criteria.push(`Query: "${searchCriteria.query}"`);
if (searchCriteria.city) criteria.push(`City: ${searchCriteria.city}`);
if (searchCriteria.state) criteria.push(`State: ${searchCriteria.state}`);
response += `**Search Criteria:** ${criteria.join(', ')}\n`;
response += `**Results Found:** ${results.length} organizations\n\n`;
if (results.length === 0) {
response += `## π No Results Found\n\n`;
response += `No organizations found matching your search criteria.\n\n`;
response += `### π‘ Try these suggestions:\n`;
response += `β’ **Broaden your search** - Use fewer or more general terms\n`;
response += `β’ **Check spelling** - Verify organization name and location\n`;
response += `β’ **Use different keywords** - Try alternative names or abbreviations\n`;
response += `β’ **Search by location only** - Try just city or state\n`;
return response;
}
// Results listing
response += `## π Search Results\n\n`;
results.forEach((charity, index) => {
response += `### ${index + 1}. ${charity.name}\n`;
response += `**EIN:** \`${charity.ein}\`\n`;
if (charity.city || charity.state) {
response += `**Location:** ${[charity.city, charity.state].filter(Boolean).join(', ')}\n`;
}
if (charity.deductibilityCode) {
const deductibilityStatus = this.interpretDeductibilityCode(charity.deductibilityCode);
response += `**Deductibility:** ${deductibilityStatus}\n`;
}
response += `\n`;
});
logger.debug("Charity search formatting completed");
return response;
}
/**
* Interpret deductibility codes for user-friendly display
*/
private static interpretDeductibilityCode(code: string): string {
const codeMap: { [key: string]: string } = {
'PC': 'β
Public Charity (Tax-deductible)',
'PF': 'β οΈ Private Foundation (Limited deductibility)',
'POF': 'β οΈ Private Operating Foundation',
'SO': 'β
Supporting Organization',
'LODGE': 'β Fraternal Lodge',
'UNKWN': 'β Status Unknown',
};
return codeMap[code.toUpperCase()] || `${code} (Contact organization for details)`;
}
/**
* Format success message with metadata
*/
static formatSuccessMessage(operation: string, metadata?: any): string {
let message = `β
${operation} completed successfully`;
if (metadata) {
const details: string[] = [];
if (metadata.processingTime) {
details.push(`Processing time: ${metadata.processingTime}ms`);
}
if (metadata.resultCount !== undefined) {
details.push(`Results: ${metadata.resultCount}`);
}
if (details.length > 0) {
message += ` (${details.join(', ')})`;
}
}
return message;
}
}