
import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
import { Logger } from '../../utils/logger.js';
import { getJiraV2Client, createBasicHeaders, AtlassianConfig } from '../../utils/atlassian-api-base.js';
import { attachmentSchema } from '../../schemas/jira.js';
import { Config, Resources } from '../../utils/mcp-helpers.js';
import fetch from 'cross-fetch';

const logger = Logger.getLogger('JiraResource:Attachments');

async function getAttachmentMetadata(config: AtlassianConfig, attachmentId: string) {
    const jiraClient = getJiraV2Client(config);
    return await jiraClient.issueAttachments.getAttachment({ id: attachmentId });
}

async function downloadAttachment(config: AtlassianConfig, url: string) {
    const headers = createBasicHeaders(config.email, config.apiToken);
    const response = await fetch(url, { headers });
    if (!response.ok) {
        throw new Error(`Failed to download attachment: ${response.status} ${response.statusText}`);
    }
    return response;
}

export function registerAttachmentResources(server: McpServer) {
    logger.info('Registering Jira attachment resources...');

    server.resource(
        'jira-attachment-content',
        new ResourceTemplate('jira://attachments/{attachmentId}', {
            list: async (_extra) => ({
                resources: [
                    {
                        uri: 'jira://attachments/{attachmentId}',
                        name: 'Jira Attachment Content',
                        description: 'Get content of a Jira attachment. Replace {attachmentId} with the attachment ID.',
                        mimeType: 'application/octet-stream'
                    }
                ]
            })
        }),
        async (uri, params, _extra) => {
            try {
                const config = Config.getAtlassianConfigFromEnv();
                const attachmentId = Array.isArray(params.attachmentId) ? params.attachmentId[0] : params.attachmentId;

                if (!attachmentId) {
                    throw new Error('Missing attachmentId in URI');
                }

                logger.info(`Getting attachment: ${attachmentId}`);
                const metadata = await getAttachmentMetadata(config, attachmentId);

                if (!metadata.content) {
                    throw new Error(`Attachment ${attachmentId} has no content URL`);
                }

                // Filter out media and executable files
                const mimeType = metadata.mimeType || 'application/octet-stream';
                const filename = metadata.filename || '';

                const isMedia = mimeType.startsWith('image/') || mimeType.startsWith('audio/') || mimeType.startsWith('video/');
                const isExecutable = /\.(exe|dll|so|dylib|bin|msi|apk|ipa|app|bat|cmd|sh)$/i.test(filename);

                if (isMedia || isExecutable) {
                    logger.info(`Skipping download for excluded file type: ${mimeType} / ${filename}`);
                    return {
                        contents: [{
                            uri: typeof uri === 'string' ? uri : uri.href,
                            mimeType: 'text/plain',
                            text: `[Content skipped: ${isMedia ? 'Media' : 'Executable'} file (${filename}) not supported for reading]`
                        }]
                    };
                }

                const contentResponse = await downloadAttachment(config, metadata.content);
                const buffer = await contentResponse.arrayBuffer();
                const bufferNode = Buffer.from(buffer);

                const uriString = typeof uri === 'string' ? uri : uri.href;

                // Handle PDF files
                if (mimeType === 'application/pdf') {
                    try {
                        // pdf-parse might be a default export or CJS module
                        const pdfParse = await import('pdf-parse');
                        // Handle potential default export difference in ESM/CJS
                        const parser = (pdfParse as any).default || pdfParse;
                        const data = await parser(bufferNode);
                        return {
                            contents: [{
                                uri: uriString,
                                mimeType: 'text/plain',
                                text: data.text
                            }]
                        };
                    } catch (e) {
                        logger.error(`Error parsing PDF ${attachmentId}:`, e);
                        // Fallback to blob if parsing fails is not ideal for LLM text reading, but standard behavior
                    }
                }

                // Handle DOCX files
                if (mimeType === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document') {
                    try {
                        const mammoth = await import('mammoth');
                        const result = await mammoth.extractRawText({ buffer: bufferNode });
                        return {
                            contents: [{
                                uri: uriString,
                                mimeType: 'text/plain',
                                text: result.value
                            }]
                        };
                    } catch (e) {
                        logger.error(`Error parsing DOCX ${attachmentId}:`, e);
                    }
                }

                // Handle XLSX files
                if (mimeType === 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' || mimeType === 'application/vnd.ms-excel') {
                    try {
                        const XLSX = await import('xlsx');
                        const workbook = XLSX.read(bufferNode, { type: 'buffer' });
                        let text = '';
                        workbook.SheetNames.forEach(sheetName => {
                            const sheet = workbook.Sheets[sheetName];
                            text += `Sheet: ${sheetName}\n`;
                            text += XLSX.utils.sheet_to_csv(sheet);
                            text += '\n\n';
                        });
                        return {
                            contents: [{
                                uri: uriString,
                                mimeType: 'text/plain', // Return as text/csv or plain text
                                text: text
                            }]
                        };
                    } catch (e) {
                        logger.error(`Error parsing Excel ${attachmentId}:`, e);
                    }
                }

                const base64Content = bufferNode.toString('base64');
                const isText = mimeType.startsWith('text/') || mimeType.includes('json') || mimeType.includes('xml') || mimeType.includes('javascript') || mimeType.includes('log');

                if (isText) {
                    const textContent = bufferNode.toString('utf-8');
                    // Return as text resource if it looks like text
                    return {
                        contents: [{
                            uri: uriString,
                            mimeType: mimeType,
                            text: textContent
                        }]
                    };
                } else {
                    // Return as blob resource
                    return {
                        contents: [{
                            uri: uriString,
                            mimeType: mimeType,
                            blob: base64Content
                        }]
                    };
                }

            } catch (error) {
                logger.error(`Error getting attachment ${params.attachmentId}:`, error);
                throw error;
            }
        }
    );

    logger.info('Jira attachment resources registered successfully');
}
