/**
 * POST /api/offers/contract/send
 * Body: contract payload incl. email { to, cc?, subject, message },
 *       attachments { offer, agb, adsp, logistikagb, avv } (false = leave out),
 *       signing { enabled, expiryDays, expiresAt }.
 *
 * Builds the branded Fulfillment-Rahmenvertrag PDF ONCE, assembles the annex
 * package (contractPackage.ts), e-mails everything to the recipient (from
 * info@logyou.de) and attaches the contract PDF to the triggering record
 * (partner → C_BPartner, lead → Lead_User). With digital signing enabled a
 * signing request is created (contractSigningDb.ts), the exact PDFs are stored
 * for the portal and the mail carries the /sign/<token> CTA (valid N days,
 * default 7; every new send supersedes the record's older pending links).
 */
import refreshTokenHelper from '../../../utils/refreshTokenHelper'
import errorHandlingHelper from '../../../utils/errorHandlingHelper'
import forceLogoutHelper from '../../../utils/forceLogoutHelper'
import { BRAND, LEGAL_FOOTER_LINES } from '../../../utils/offers/quotePdf'
import { generateContractPdf } from '../../../utils/offers/contractPdf'
import { attachToStrapi } from '../../../utils/inbox/strapiAttach'
import { saveOfferConditions, conditionsFromContractPayload } from '../../../utils/offers/offerConditions'
import { assembleContractPackage } from '../../../utils/offers/contractPackage'
import { createSigningRequest, isSigningAvailable, writeSigningFile } from '../../../utils/offers/contractSigningDb'
import { buildDocumentMeta, mailTransport, resolveSigningExpiry, signingCtaHtml, signingCtaText, signingLink, escapeHtml, formatDateHuman } from '../../../utils/offers/contractSigning'
import { logContactActivity, strapiPublicFileUrl } from '../../../utils/offers/contactActivity'
import { APP_BASE_URL } from '../../../utils/emailVerification'

const EMAIL_TEXTS: any = {
  de: {
    headline: 'Ihr Fulfillment-Vertrag',
    attachmentBox: 'Der Vertrag liegt dieser E-Mail als PDF-Anhang bei. Bitte senden Sie uns ein unterschriebenes Exemplar zurück.',
    attachmentBoxSigning: 'Der Vertrag und alle Anlagen liegen dieser E-Mail als PDF bei. Über den Button oben können Sie die Dokumente auch online einsehen und den Vertrag dort — wenn Sie möchten — in einem separaten Schritt digital unterschreiben, oder uns alternativ ein unterschriebenes Exemplar zurücksenden.',
    linkOnlyBox: 'Alle Dokumente stehen über den Button oben zum Lesen und Herunterladen bereit — der Klick ist unverbindlich. Falls Sie den Vertrag dort unterschreiben, erhalten Sie automatisch eine Kopie aller Dokumente per E-Mail.',
    documents: 'Enthaltene Dokumente',
    auto: 'Diese E-Mail wurde automatisch versendet.'
  },
  en: {
    headline: 'Your fulfillment agreement',
    attachmentBox: 'The agreement is attached to this email as a PDF. Please return a signed copy to us.',
    attachmentBoxSigning: 'The agreement and all annexes are attached to this email as PDFs. Via the button above you can also review the documents online and — if you wish — sign the agreement there in a separate step, or alternatively return a signed copy to us.',
    linkOnlyBox: 'All documents are available for reading and download via the button above — clicking it is non-binding. If you sign the agreement there, you will automatically receive a copy of every document by e-mail.',
    documents: 'Included documents',
    auto: 'This email was sent automatically.'
  }
}

const generateContractEmailHtml = (message: string, language: string, docs: Array<{ title: string; filename: string }>, signing: { link: string; expiresAt: string } | null, attachDocs: boolean) => {
  const T = EMAIL_TEXTS[language === 'en' ? 'en' : 'de']
  const messageHtml = escapeHtml(message).replace(/\n/g, '<br>')
  const docList = docs.length > 1
    ? `<div style="margin-top:10px;font-size:12px;color:#5a6b7c;"><strong>${T.documents}:</strong><ul style="margin:6px 0 0 18px;padding:0;">${docs.map((d) => `<li>${escapeHtml(d.title)}</li>`).join('')}</ul></div>`
    : ''
  return `<!DOCTYPE html>
<html>
<body style="margin:0;padding:0;background-color:#f0f2f5;font-family:Arial,Helvetica,sans-serif;">
  <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background-color:#f0f2f5;padding:24px 0;">
    <tr><td align="center">
      <table role="presentation" width="600" cellpadding="0" cellspacing="0" style="max-width:600px;width:100%;background-color:#ffffff;border-radius:8px;overflow:hidden;box-shadow:0 1px 4px rgba(0,0,0,0.08);">
        <tr>
          <td style="background-color:${BRAND.navy};border-bottom:4px solid ${BRAND.orange};padding:26px 32px;">
            <div style="color:#ffffff;font-size:20px;font-weight:bold;">${T.headline}</div>
            <div style="color:${BRAND.headerSub};font-size:12px;margin-top:6px;">LogYou GmbH &middot; logyou.de</div>
          </td>
        </tr>
        <tr>
          <td style="padding:30px 32px;color:#33414E;font-size:14px;line-height:1.6;">
            ${messageHtml}
          </td>
        </tr>
        ${signing ? `<tr><td style="padding:0 32px 18px 32px;">${signingCtaHtml(language, signing.link, signing.expiresAt)}</td></tr>` : ''}
        <tr>
          <td style="padding:0 32px 28px 32px;">
            <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background-color:#F6F8FA;border-left:4px solid ${BRAND.orange};border-radius:4px;">
              <tr>
                <td style="padding:14px 18px;color:#33414E;font-size:13px;">
                  &#128196;&nbsp; ${signing ? (attachDocs ? T.attachmentBoxSigning : T.linkOnlyBox) : T.attachmentBox}
                  ${docList}
                </td>
              </tr>
            </table>
          </td>
        </tr>
        <tr>
          <td style="background-color:#f7f8fa;border-top:1px solid #e3e7ec;padding:16px 32px;color:#8a97a5;font-size:10px;line-height:1.6;text-align:center;">
            ${LEGAL_FOOTER_LINES.join('<br>')}
            <br><br>${T.auto}
          </td>
        </tr>
      </table>
    </td></tr>
  </table>
</body>
</html>`
}

const handleFunc = async (event: any, authToken: string | null = null) => {
  const token = authToken ?? await getTokenHelper(event)
  if (!token) return { status: 401, message: 'Not authenticated' }

  const body = await readBody(event)
  if (!body?.customer?.company || !body?.customer?.contactName) {
    return { status: 400, message: 'Company and contact name are required' }
  }
  const toEmail = String(body?.email?.to || '').trim()
  if (!/.+@.+\..+/.test(toEmail)) {
    return { status: 400, message: 'A valid recipient email is required' }
  }
  const language = body?.meta?.language === 'en' ? 'en' : 'de'
  const source = body.source === 'lead' ? 'lead' : 'partner'
  const recordId = Number(body.recordId)
  const warnings: string[] = []

  // 1) Contract PDF once — e-mail attachment, record attachment, portal copy.
  const contract = await generateContractPdf(body)

  // 2) Annex package (last offer, AGB, ADSp, Logistik-AGB, AVV) per the flags.
  const pkg = await assembleContractPackage(event, token, { source, recordId, language, attachments: body.attachments || {}, contract })
  warnings.push(...pkg.warnings)

  // 3) Digital signing request (fail-soft: without the store we still send the mail).
  let signing: { token: string; link: string; expiresAt: string } | null = null
  const signingWanted = body?.signing?.enabled !== false
  if (signingWanted) {
    if (!isSigningAvailable()) {
      warnings.push(language === 'en' ? 'Digital signing unavailable (store) — sent without signing link' : 'Digitale Unterschrift nicht verfügbar (Speicher) — ohne Signatur-Link versendet')
    } else {
      try {
        const expiresAt = resolveSigningExpiry(body.signing)
        const docsMeta = pkg.documents.map((d) => buildDocumentMeta(d.key, d.filename, d.buffer, language, d.version))
        const { email: _e, ...payloadWithoutEmail } = body
        const req = createSigningRequest({
          source,
          recordId: recordId > 0 ? recordId : 0,
          recordUu: body.recordUu || undefined,
          company: String(body.customer.company),
          contactName: String(body.customer.contactName),
          email: toEmail,
          language,
          payload: payloadWithoutEmail,
          documents: docsMeta,
          createdBy: Number(getCookie(event, 'logship_user_id')) || null,
          expiresAt
        })
        for (const d of pkg.documents) writeSigningFile(req.token, d.filename, d.buffer)
        signing = { token: req.token, link: signingLink(req.token), expiresAt }
      } catch (err: any) {
        console.error('Signing request creation failed:', err)
        warnings.push(language === 'en' ? 'Signing link could not be created — sent without it' : 'Signatur-Link konnte nicht erstellt werden — ohne Link versendet')
      }
    }
  }

  // 4) Mail.
  const ccList = String(body?.email?.cc || '')
    .split(/[,;]/)
    .map((s: string) => s.trim())
    .filter((s: string) => s.length > 0)
  const message = String(body?.email?.message || '')
  // With a signing link the PDFs are opt-in (body.signing.attachDocuments); without a
  // link they are always attached — the mail is the only way to get them.
  const attachDocs = !signing || body?.signing?.attachDocuments === true
  try {
    await mailTransport().sendMail({
      from: 'info@logyou.de',
      to: toEmail,
      cc: ccList.length > 0 ? ccList : undefined,
      subject: body?.email?.subject || contract.filename.replace(/\.pdf$/, ''),
      text: message + (signing ? signingCtaText(language, signing.link, signing.expiresAt) : ''),
      html: generateContractEmailHtml(message, language, pkg.documents, signing, attachDocs),
      attachments: attachDocs ? pkg.documents.map((d) => ({ filename: d.filename, content: d.buffer, contentType: 'application/pdf' })) : []
    })
  } catch (err: any) {
    console.error('Contract email send error:', err)
    return { status: 500, message: `Failed to send email: ${err.message}` }
  }

  // 5) Attach the contract PDF to the triggering record — own try/catch so an
  //    attachment failure never reverts the successful send.
  let attached = false
  let attachedUrl = ''
  try {
    if (recordId > 0) {
      const up = await attachToStrapi(event, token, {
        tableName: source === 'lead' ? 'Lead_User' : 'C_BPartner',
        recordId,
        recordUu: body.recordUu || undefined,
        buffer: contract.buffer,
        filename: contract.filename,
        mimeType: 'application/pdf'
      })
      attached = true
      attachedUrl = strapiPublicFileUrl(up.fileUrl)
    } else {
      warnings.push('No record id — attachment skipped')
    }
  } catch (err: any) {
    console.error('Contract attachment error:', err)
    warnings.push('Email sent, but attaching the PDF to the record failed')
  }

  // 6) Persist the just-sent conditions (sections, attachments, signing prefs)
  //    on the record — fail-soft, the offer_conditions column may not exist yet.
  let conditionsSaved = false
  try {
    if (recordId > 0) {
      await saveOfferConditions(event, token, source, recordId, 'contract', {
        ...conditionsFromContractPayload(body),
        lastSend: { at: new Date().toISOString(), to: toEmail, documents: pkg.documents.map((d) => ({ key: d.key, filename: d.filename, version: d.version })), signingToken: signing?.token || null, signingExpiresAt: signing?.expiresAt || null }
      })
      conditionsSaved = true
    }
  } catch (err: any) {
    console.error('Contract conditions save skipped:', err?.message || err)
  }

  // 7) Activity on the record: "Vertrag gesendet" with every document as a button
  //    (contract → Strapi attachment; annexes → portal copies while a signing link
  //    exists). Fail-soft.
  let activityLogged = false
  try {
    if (recordId > 0) {
      const en = language === 'en'
      const docTitles = pkg.documents.map((d) => d.title).join(', ')
      const lines = [
        en ? `Contract ${contract.filename} e-mailed to ${toEmail}${ccList.length ? ` (CC: ${ccList.join(', ')})` : ''}.` : `Vertrag ${contract.filename} per E-Mail an ${toEmail}${ccList.length ? ` (CC: ${ccList.join(', ')})` : ''} gesendet.`,
        en ? `Package: ${docTitles}.` : `Paket: ${docTitles}.`,
        signing
          ? (en ? `Digital signing link (valid until ${formatDateHuman(signing.expiresAt, 'en')}${attachDocs ? ', PDFs also attached' : ', PDFs in portal only'}): ${signing.link}` : `Signatur-Link (gültig bis ${formatDateHuman(signing.expiresAt, 'de')}${attachDocs ? ', PDFs zusätzlich angehängt' : ', PDFs nur im Portal'}): ${signing.link}`)
          : (en ? 'No signing link — customer asked to return a signed copy.' : 'Ohne Signatur-Link — Kunde soll unterschriebenes Exemplar zurücksenden.')
      ]
      const docs: Array<{ title: string; url: string }> = []
      if (attachedUrl) docs.push({ title: en ? 'Contract (PDF)' : 'Vertrag (PDF)', url: attachedUrl })
      if (signing) {
        for (const d of pkg.documents) {
          if (d.key === 'contract' && attachedUrl) continue
          docs.push({ title: d.title, url: `${APP_BASE_URL}/api/public/sign/${signing.token}/document/${d.key}` })
        }
      }
      const created = await logContactActivity(event, token, {
        source,
        recordId,
        type: 'EM',
        contactEmail: toEmail,
        description: en ? `Contract sent: ${contract.filename}` : `Vertrag gesendet: ${contract.filename}`,
        comments: lines.join('\n'),
        documents: docs
      })
      activityLogged = !!created
    }
  } catch (err: any) {
    console.error('Contract activity skipped:', err?.message || err)
  }

  return {
    status: 200,
    message: 'Contract sent successfully',
    filename: contract.filename,
    attached,
    conditionsSaved,
    activityLogged,
    documents: pkg.documents.map((d) => ({ key: d.key, title: d.title, filename: d.filename, version: d.version })),
    signing,
    attachedToMail: attachDocs,
    warning: warnings.length ? warnings.join(' · ') : undefined
  }
}

export default defineEventHandler(async (event) => {
  let data: any = {}
  try {
    data = await handleFunc(event)
  } catch (err: any) {
    try {
      let authToken: any = await refreshTokenHelper(event)
      data = await handleFunc(event, authToken)
    } catch (error: any) {
      data = errorHandlingHelper(err?.data ?? err, error?.data ?? error)
      forceLogoutHelper(event, data)
    }
  }
  return data
})
