import { defineEndpoint } from "@directus/extensions-sdk"; import { AcquisitionService, PdfEngine } from "@mintel/pdf/server"; import { render, SiteAuditTemplate, ProjectEstimateTemplate, } from "@mintel/mail"; import { createElement } from "react"; import * as path from "path"; import * as fs from "fs"; export default defineEndpoint((router, { services, env }) => { const { ItemsService, MailService } = services; router.get("/ping", (req, res) => res.send("pong")); router.post("/audit/:id", async (req: any, res: any) => { const { id } = req.params; const leadsService = new ItemsService("leads", { schema: req.schema, accountability: req.accountability, }); try { const lead = await leadsService.readOne(id); if (!lead) return res.status(404).send({ error: "Lead not found" }); await leadsService.updateOne(id, { status: "auditing" }); const acqService = new AcquisitionService(env.OPENROUTER_API_KEY); const result = await acqService.runFullSequence( lead.website_url, lead.briefing, lead.comments, ); await leadsService.updateOne(id, { status: "audit_ready", ai_state: result.state, audit_context: JSON.stringify(result.usage), }); res.send({ success: true, result }); } catch (error: any) { console.error("Audit failed:", error); await leadsService.updateOne(id, { status: "new", comments: `Audit failed: ${error.message}`, }); res.status(500).send({ error: error.message }); } }); router.post("/audit-email/:id", async (req: any, res: any) => { const { id } = req.params; const { ItemsService, MailService } = services; const leadsService = new ItemsService("leads", { schema: req.schema, accountability: req.accountability, }); const _peopleService = new ItemsService("people", { schema: req.schema, accountability: req.accountability, }); const companiesService = new ItemsService("companies", { schema: req.schema, accountability: req.accountability, }); const mailService = new MailService({ schema: req.schema, accountability: req.accountability, }); try { const lead = await leadsService.readOne(id, { fields: ["*", "company.*", "contact_person.*"], }); if (!lead || !lead.ai_state) return res.status(400).send({ error: "Lead or Audit not ready" }); let recipientEmail = lead.contact_email; let companyName = lead.company?.name || lead.company_name; if (lead.contact_person) { recipientEmail = lead.contact_person.email || recipientEmail; if (lead.contact_person.company) { const personCompany = await companiesService.readOne( lead.contact_person.company, ); companyName = personCompany?.name || companyName; } } if (!recipientEmail) return res.status(400).send({ error: "No recipient email found" }); const auditHighlights = [ `Projekt-Typ: ${lead.ai_state.projectType === "website" ? "Website" : "Web App"}`, ...(lead.ai_state.sitemap || []) .slice(0, 3) .map((item: any) => `Potenzial in: ${item.category}`), ]; const html = await render( createElement(SiteAuditTemplate, { companyName: companyName, websiteUrl: lead.website_url, auditHighlights, }), ); await mailService.send({ to: recipientEmail, subject: `Analyse Ihrer Webpräsenz: ${companyName}`, html, }); await leadsService.updateOne(id, { status: "contacted", last_contacted_at: new Date().toISOString(), }); res.send({ success: true }); } catch (error: any) { console.error("Audit Email failed:", error); res.status(500).send({ error: error.message }); } }); router.post("/estimate/:id", async (req: any, res: any) => { const { id } = req.params; const leadsService = new ItemsService("leads", { schema: req.schema, accountability: req.accountability, }); try { const lead = await leadsService.readOne(id); if (!lead || !lead.ai_state) return res.status(400).send({ error: "Lead or AI state not found" }); const pdfEngine = new PdfEngine(); const filename = `estimate_${id}_${Date.now()}.pdf`; const storageRoot = env.STORAGE_LOCAL_ROOT || "./storage"; const outputPath = path.join(storageRoot, filename); await pdfEngine.generateEstimatePdf(lead.ai_state, outputPath); await leadsService.updateOne(id, { audit_pdf_path: filename, }); res.send({ success: true, filename }); } catch (error: any) { console.error("PDF Generation failed:", error); res.status(500).send({ error: error.message }); } }); router.post("/estimate-email/:id", async (req: any, res: any) => { const { id } = req.params; const leadsService = new ItemsService("leads", { schema: req.schema, accountability: req.accountability, }); const _peopleService = new ItemsService("people", { schema: req.schema, accountability: req.accountability, }); const companiesService = new ItemsService("companies", { schema: req.schema, accountability: req.accountability, }); const mailService = new MailService({ schema: req.schema, accountability: req.accountability, }); try { const lead = await leadsService.readOne(id, { fields: ["*", "company.*", "contact_person.*"], }); if (!lead || !lead.audit_pdf_path) return res.status(400).send({ error: "PDF not generated" }); let recipientEmail = lead.contact_email; let companyName = lead.company?.name || lead.company_name; if (lead.contact_person) { recipientEmail = lead.contact_person.email || recipientEmail; if (lead.contact_person.company) { const personCompany = await companiesService.readOne( lead.contact_person.company, ); companyName = personCompany?.name || companyName; } } if (!recipientEmail) return res.status(400).send({ error: "No recipient email found" }); const html = await render( createElement(ProjectEstimateTemplate, { companyName: companyName, }), ); const storageRoot = env.STORAGE_LOCAL_ROOT || "./storage"; const attachmentPath = path.join(storageRoot, lead.audit_pdf_path); await mailService.send({ to: recipientEmail, subject: `Ihre Projekt-Schätzung: ${companyName}`, html, attachments: [ { filename: `Angebot_${companyName}.pdf`, content: fs.readFileSync(attachmentPath), }, ], }); await leadsService.updateOne(id, { status: "contacted", last_contacted_at: new Date().toISOString(), }); res.send({ success: true }); } catch (error: any) { console.error("Estimate Email failed:", error); res.status(500).send({ error: error.message }); } }); });