import {
    IWebhookFunctions,
    INodeExecutionData,
} from 'n8n-workflow';
import {
    INodeType,
    INodeTypeDescription,
    NodeConnectionType,
} from 'n8n-workflow';

export class _HTTPIn implements INodeType {
    description: INodeTypeDescription = {
        displayName: 'HTTPInput',
        name: 'httpInput',

        group: ['trigger'],
        version: 1,
        description: 'Receive HTTP requests like DemoHttpTransport',
        defaults: {
            name: 'HTTPInput',
        },
        inputs: [],
        outputs: [NodeConnectionType.Main],
        properties: [],
    };

    async execute(): Promise<INodeExecutionData[][]> {
        return [[]];
    }

    async webhook(this: IWebhookFunctions): Promise<{ workflowData: INodeExecutionData[][]; rawResponse: boolean }> {
        const req = this.getRequestObject();
        const res = this.getResponseObject();

        res.setHeader('Access-Control-Allow-Origin', '*');
        res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
        res.setHeader('Access-Control-Allow-Headers', '*');

        if (req.method === 'OPTIONS') {
            res.statusCode = 200;
            res.end();
            return { workflowData: [[]], rawResponse: true };
        }

        const query = req.query || {};
        const chain = query.chain as string;

        if (!chain) {
            res.statusCode = 400;
            res.end("Error. Require param 'chain=chainName'");
            return { workflowData: [[]], rawResponse: true };
        }

        let body: any = null;
        try {
            const contentType = req.headers['content-type'] || '';
            if (contentType.includes('application/json')) {
                body = await new Promise((resolve, reject) => {
                    let data = '';
                    req.on('data', (chunk: any) => { data += chunk; });
                    req.on('end', () => {
                        try {
                            resolve(JSON.parse(data));
                        } catch (e) {
                            reject(e);
                        }
                    });
                    req.on('error', (err: any) => reject(err));
                });
            } else {
                body = await new Promise<string>((resolve) => {
                    let data = '';
                    req.on('data', (chunk: any) => { data += chunk; });
                    req.on('end', () => resolve(data));
                });
            }
        } catch (e) {
            res.statusCode = 400;
            res.end('Invalid body: ' + (e as Error).message);
            return { workflowData: [[]], rawResponse: true };
        }


        const nodeInfo = this.getNode();
        const workflowName = this.getWorkflow().name;

        const metadata = {
            ...(body && body.METADATA ? body.METADATA : {}), // если тело уже имеет METADATA
            from: nodeInfo.name,           // имя текущего узла
            id: nodeInfo.name,             // можно использовать nodeInfo.type для типа
            chain: chain,
            workflow: workflowName,
            time: Date.now(),
            date: new Date().toLocaleDateString('ru-RU'),
        };

        const item: INodeExecutionData = {
            json: {
                METADATA: metadata,
                DATA: body,
            },
        };

        res.statusCode = 200;
        res.end('OK');

        return {
            workflowData: [[item]],
            rawResponse: true, // мы сами ответили клиенту
        };
    }
}
