import { formatDzdAmount } from "./formatters.js";
import { launchPuppeteerBrowser } from "./puppeteer.js";

const BRAND = {
  background: "#0A0C10",
  surface: "#111827",
  surfaceSoft: "#EAF2FF",
  border: "#CBD5E1",
  accent: "#2563EB",
  accentSoft: "#DBEAFE",
  text: "#0F172A",
  muted: "#475569",
  danger: "#DC2626",
  warning: "#B45309",
};

const escapeHtml = (value) =>
  String(value ?? "")
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#39;");

const formatDateValue = (value) => {
  if (!value) {
    return "—";
  }

  const normalized = String(value);
  const [year, month, day] = normalized.split("-");

  if (year && month && day) {
    return `${day}/${month}/${year}`;
  }

  const date = new Date(normalized);

  if (Number.isNaN(date.getTime())) {
    return normalized;
  }

  return new Intl.DateTimeFormat("fr-FR").format(date);
};

const formatValue = (value, column = {}) => {
  if (value === null || value === undefined || value === "") {
    return "—";
  }

  if (column.type === "amount") {
    return formatDzdAmount(value);
  }

  if (column.type === "date") {
    return formatDateValue(value);
  }

  if (column.type === "boolean") {
    return value ? "Oui" : "Non";
  }

  return String(value);
};

const getColumnAlign = (column = {}) =>
  column.align || (column.type === "amount" ? "right" : "left");

const getWarningToneClass = (tone) => {
  if (tone === "danger") {
    return "danger";
  }

  if (tone === "success") {
    return "success";
  }

  return "warning";
};

const renderCompanyIdentity = (company = {}) => {
  const details = [
    company.nif ? `NIF ${company.nif}` : null,
    company.rc ? `RC ${company.rc}` : null,
    [company.address, company.city].filter(Boolean).join(", ") || null,
  ].filter(Boolean);

  return `
    <div class="company-identity">
      <div class="company-mark">
        ${
          company.logo_url
            ? `<img src="${escapeHtml(company.logo_url)}" alt="Logo ${escapeHtml(
                company.name || "Société",
              )}" />`
            : `<div class="company-mark-fallback">${escapeHtml(
                (company.name || "SCF").slice(0, 2).toUpperCase(),
              )}</div>`
        }
      </div>
      <div class="company-copy">
        <p class="eyebrow">Algérie SCF</p>
        <h1>${escapeHtml(company.name || "Société")}</h1>
        ${
          details.length
            ? `<p class="company-meta">${escapeHtml(details.join(" · "))}</p>`
            : ""
        }
      </div>
    </div>
  `;
};

const renderParameters = (parameters = []) => {
  if (!parameters.length) {
    return "";
  }

  return `
    <div class="parameter-grid">
      ${parameters
        .map(
          (item) => `
            <div class="parameter-card">
              <span class="parameter-label">${escapeHtml(item.label)}</span>
              <span class="parameter-value">${escapeHtml(item.value || "—")}</span>
            </div>
          `,
        )
        .join("")}
    </div>
  `;
};

const renderSummary = (summary = []) => {
  if (!summary.length) {
    return "";
  }

  return `
    <div class="summary-grid">
      ${summary
        .map(
          (item) => `
            <div class="summary-card">
              <span class="summary-label">${escapeHtml(item.label)}</span>
              <span class="summary-value">${escapeHtml(formatValue(item.value, item))}</span>
            </div>
          `,
        )
        .join("")}
    </div>
  `;
};

const renderWarnings = (warnings = []) =>
  warnings
    .map(
      (warning) => `
        <div class="warning warning-${getWarningToneClass(warning.tone)}">
          ${escapeHtml(warning.message)}
        </div>
      `,
    )
    .join("");

const renderTable = ({ columns = [], rows = [], emptyMessage = "Aucune donnée." } = {}) => `
  <table class="report-table">
    <thead>
      <tr>
        ${columns
          .map(
            (column) => `
              <th class="align-${getColumnAlign(column)}">${escapeHtml(column.label)}</th>
            `,
          )
          .join("")}
      </tr>
    </thead>
    <tbody>
      ${
        rows.length
          ? rows
              .map((row) => {
                const rowClass = row.row_type ? `row-${escapeHtml(row.row_type)}` : "";

                return `
                  <tr class="${rowClass}">
                    ${columns
                      .map(
                        (column) => `
                          <td class="align-${getColumnAlign(column)} ${
                            column.type === "amount" ? "amount" : ""
                          }">
                            ${escapeHtml(formatValue(row[column.key], column))}
                          </td>
                        `,
                      )
                      .join("")}
                  </tr>
                `;
              })
              .join("")
          : `
            <tr>
              <td colspan="${columns.length || 1}" class="empty-row">${escapeHtml(emptyMessage)}</td>
            </tr>
          `
      }
    </tbody>
  </table>
`;

const renderSections = (sections = []) =>
  sections
    .map(
      (section) => `
        <section class="section ${section.page_break_after ? "page-break-after" : ""}">
          <div class="section-heading">
            <div>
              <h2>${escapeHtml(section.title || "")}</h2>
              ${
                section.subtitle
                  ? `<p class="section-subtitle">${escapeHtml(section.subtitle)}</p>`
                  : ""
              }
            </div>
          </div>
          ${renderParameters(section.meta || [])}
          ${renderTable({
            columns: section.columns,
            rows: section.rows,
            emptyMessage: section.empty_message,
          })}
          ${renderSummary(section.summary || [])}
        </section>
      `,
    )
    .join("");

const buildHtml = (report) => `
  <!DOCTYPE html>
  <html lang="fr">
    <head>
      <meta charset="utf-8" />
      <title>${escapeHtml(report.title || "Rapport")}</title>
      <style>
        * { box-sizing: border-box; }
        body {
          margin: 0;
          background: #f3f6fb;
          color: ${BRAND.text};
          font-family: Inter, Arial, sans-serif;
          font-size: 12px;
          line-height: 1.45;
        }
        .document {
          padding: 18px 0 0;
        }
        .page {
          padding: 0 8px;
        }
        .hero {
          margin: 0 0 18px;
          padding: 20px 22px;
          border-radius: 24px;
          background:
            radial-gradient(circle at top right, rgba(59,130,246,0.22), transparent 28%),
            linear-gradient(135deg, ${BRAND.background} 0%, ${BRAND.surface} 100%);
          color: #F8FAFC;
        }
        .company-identity {
          display: flex;
          align-items: center;
          gap: 16px;
        }
        .company-mark img,
        .company-mark-fallback {
          width: 56px;
          height: 56px;
          border-radius: 18px;
          object-fit: cover;
          display: flex;
          align-items: center;
          justify-content: center;
          background: rgba(255,255,255,0.08);
          border: 1px solid rgba(255,255,255,0.12);
          font-family: "DM Sans", Arial, sans-serif;
          font-size: 18px;
          font-weight: 700;
        }
        .eyebrow {
          margin: 0;
          color: #93C5FD;
          font-size: 10px;
          letter-spacing: 0.24em;
          text-transform: uppercase;
          font-weight: 700;
        }
        .company-copy h1 {
          margin: 6px 0 0;
          font-family: "DM Sans", Arial, sans-serif;
          font-size: 24px;
        }
        .company-meta {
          margin: 6px 0 0;
          color: rgba(241,245,249,0.82);
        }
        .hero-grid {
          display: grid;
          grid-template-columns: 1.4fr 1fr;
          gap: 18px;
          margin-top: 18px;
        }
        .hero-panel {
          padding: 16px 18px;
          border-radius: 18px;
          background: rgba(255,255,255,0.06);
          border: 1px solid rgba(255,255,255,0.08);
        }
        .hero-panel-label {
          display: block;
          color: rgba(191,219,254,0.88);
          font-size: 10px;
          text-transform: uppercase;
          letter-spacing: 0.18em;
        }
        .hero-panel-value {
          display: block;
          margin-top: 8px;
          font-size: 18px;
          font-weight: 700;
          font-family: "DM Sans", Arial, sans-serif;
        }
        .hero-panel-copy {
          display: block;
          margin-top: 6px;
          color: rgba(241,245,249,0.75);
        }
        .parameter-grid,
        .summary-grid {
          display: grid;
          gap: 10px;
          margin-top: 14px;
          grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
        }
        .parameter-card,
        .summary-card {
          padding: 12px 14px;
          border-radius: 16px;
          border: 1px solid ${BRAND.border};
          background: #FFFFFF;
        }
        .parameter-label,
        .summary-label {
          display: block;
          color: ${BRAND.muted};
          font-size: 10px;
          text-transform: uppercase;
          letter-spacing: 0.12em;
          font-weight: 700;
        }
        .parameter-value {
          display: block;
          margin-top: 7px;
          color: ${BRAND.text};
          font-weight: 700;
        }
        .summary-card {
          background: ${BRAND.surfaceSoft};
          border-color: ${BRAND.accentSoft};
        }
        .summary-value {
          display: block;
          margin-top: 8px;
          color: ${BRAND.text};
          font-weight: 800;
          font-size: 16px;
          font-family: "JetBrains Mono", "Courier New", monospace;
        }
        .warning {
          margin-top: 14px;
          padding: 12px 14px;
          border-radius: 14px;
          border: 1px solid #FDE68A;
          background: #FFFBEB;
          color: ${BRAND.warning};
          font-weight: 600;
        }
        .warning-danger {
          border-color: #FECACA;
          background: #FEF2F2;
          color: ${BRAND.danger};
        }
        .warning-success {
          border-color: #A7F3D0;
          background: #ECFDF5;
          color: #047857;
        }
        .section {
          margin-top: 18px;
          padding: 18px 20px 20px;
          border-radius: 22px;
          background: #FFFFFF;
          border: 1px solid ${BRAND.border};
          box-shadow: 0 20px 40px rgba(15, 23, 42, 0.08);
        }
        .section-heading {
          display: flex;
          align-items: flex-start;
          justify-content: space-between;
          gap: 16px;
          margin-bottom: 8px;
        }
        h2 {
          margin: 0;
          font-family: "DM Sans", Arial, sans-serif;
          font-size: 18px;
        }
        .section-subtitle {
          margin: 6px 0 0;
          color: ${BRAND.muted};
        }
        .report-table {
          width: 100%;
          margin-top: 14px;
          border-collapse: collapse;
        }
        .report-table th,
        .report-table td {
          padding: 10px 12px;
          border-bottom: 1px solid #E2E8F0;
          vertical-align: top;
        }
        .report-table th {
          background: ${BRAND.background};
          color: #F8FAFC;
          font-size: 10px;
          text-transform: uppercase;
          letter-spacing: 0.14em;
          font-weight: 700;
        }
        .report-table td.amount {
          font-family: "JetBrains Mono", "Courier New", monospace;
        }
        .report-table tbody tr:nth-child(even) td {
          background: #F8FAFC;
        }
        .report-table .align-right { text-align: right; }
        .report-table .align-left { text-align: left; }
        .row-class_total td,
        .row-grand_total td {
          font-weight: 800;
          background: ${BRAND.accentSoft} !important;
        }
        .row-cancelled td {
          color: ${BRAND.muted};
          text-decoration: line-through;
        }
        .empty-row {
          text-align: center;
          color: ${BRAND.muted};
          padding: 26px 0;
        }
        .page-break-after {
          page-break-after: always;
        }
      </style>
    </head>
    <body>
      <div class="document">
        <div class="page">
          <section class="hero">
            ${renderCompanyIdentity(report.company || {})}
            <div class="hero-grid">
              <div class="hero-panel">
                <span class="hero-panel-label">Rapport</span>
                <span class="hero-panel-value">${escapeHtml(report.title || "Rapport comptable")}</span>
                ${
                  report.description
                    ? `<span class="hero-panel-copy">${escapeHtml(report.description)}</span>`
                    : ""
                }
              </div>
              <div class="hero-panel">
                <span class="hero-panel-label">Génération</span>
                <span class="hero-panel-value">${escapeHtml(report.generated_at || "—")}</span>
                <span class="hero-panel-copy">Par ${escapeHtml(report.generated_by || "Système")}</span>
              </div>
            </div>
          </section>

          ${renderParameters(report.parameters || [])}
          ${renderWarnings(report.warnings || [])}
          ${renderSummary(report.cards || [])}

          ${
            report.table
              ? `
                <section class="section">
                  ${renderTable(report.table)}
                  ${renderSummary(report.summary || [])}
                </section>
              `
              : ""
          }

          ${renderSections(report.sections || [])}
          ${!report.table ? renderSummary(report.summary || []) : ""}
        </div>
      </div>
    </body>
  </html>
`;

const buildHeaderTemplate = (report) => `
  <style>
    .header {
      width: 100%;
      padding: 0 10px;
      font-family: Inter, Arial, sans-serif;
      color: #0F172A;
      font-size: 9px;
    }
    .header-row {
      width: 100%;
      border-bottom: 1px solid #CBD5E1;
      padding-bottom: 6px;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }
    .header-title {
      font-weight: 700;
      color: #1D4ED8;
      text-transform: uppercase;
      letter-spacing: 0.12em;
    }
    .header-company {
      font-weight: 600;
    }
  </style>
  <div class="header">
    <div class="header-row">
      <span class="header-title">${escapeHtml(report.title || "Rapport")}</span>
      <span class="header-company">${escapeHtml(report.company?.name || "Société")}</span>
    </div>
  </div>
`;

const buildFooterTemplate = (report) => `
  <style>
    .footer {
      width: 100%;
      padding: 0 10px;
      font-family: Inter, Arial, sans-serif;
      color: #475569;
      font-size: 9px;
    }
    .footer-row {
      width: 100%;
      border-top: 1px solid #CBD5E1;
      padding-top: 6px;
      display: flex;
      justify-content: space-between;
      align-items: center;
    }
    .footer-strong {
      color: #0F172A;
      font-weight: 600;
    }
  </style>
  <div class="footer">
    <div class="footer-row">
      <span>Document généré le ${escapeHtml(report.generated_at || "—")} par <span class="footer-strong">${escapeHtml(report.generated_by || "Système")}</span></span>
      <span>Page <span class="pageNumber"></span> de <span class="totalPages"></span></span>
    </div>
  </div>
`;

const normalizeSheetName = (value, fallback) =>
  String(value || fallback || "Rapport")
    .replace(/[\\/?*[\]:]/g, " ")
    .slice(0, 31);

const setSectionTitleRow = (sheet, rowNumber, title) => {
  const row = sheet.getRow(rowNumber);
  row.getCell(1).value = title;
  row.font = { bold: true, size: 14, color: { argb: "FF0F172A" } };
  row.height = 20;
};

const applyTableHeaderStyle = (row) => {
  row.font = { bold: true, color: { argb: "FFFFFFFF" } };
  row.alignment = { vertical: "middle" };
  row.fill = {
    type: "pattern",
    pattern: "solid",
    fgColor: { argb: "FF0A0C10" },
  };
  row.eachCell((cell) => {
    cell.border = {
      top: { style: "thin", color: { argb: "FF0A0C10" } },
      left: { style: "thin", color: { argb: "FF0A0C10" } },
      bottom: { style: "thin", color: { argb: "FF0A0C10" } },
      right: { style: "thin", color: { argb: "FF0A0C10" } },
    };
  });
};

const styleDataRow = (row, columns, rowType) => {
  row.eachCell((cell, columnNumber) => {
    const column = columns[columnNumber - 1];
    const isAmount = column?.type === "amount";

    cell.alignment = {
      vertical: "top",
      horizontal: isAmount ? "right" : "left",
    };

    cell.border = {
      bottom: { style: "thin", color: { argb: "FFE2E8F0" } },
    };

    if (isAmount && typeof cell.value === "number") {
      cell.numFmt = '# ##0.00 "DZD"';
      cell.font = {
        name: "JetBrains Mono",
      };
    }
  });

  if (rowType === "class_total" || rowType === "grand_total") {
    row.font = { bold: true };
    row.fill = {
      type: "pattern",
      pattern: "solid",
      fgColor: { argb: "FFDBEAFE" },
    };
  }
};

const addParameterRows = (sheet, parameters = []) => {
  parameters.forEach((parameter) => {
    const row = sheet.addRow([parameter.label, parameter.value || "—"]);
    row.getCell(1).font = { bold: true, color: { argb: "FF475569" } };
  });
};

const addSummaryRows = (sheet, summary = []) => {
  summary.forEach((item) => {
    const row = sheet.addRow([
      item.label,
      item.type === "amount" ? Number(item.value || 0) : item.value ?? "",
    ]);
    row.getCell(1).font = { bold: true };
    if (item.type === "amount") {
      row.getCell(2).numFmt = '# ##0.00 "DZD"';
      row.getCell(2).font = { name: "JetBrains Mono", bold: true };
    }
  });
};

const addTableBlock = (sheet, table, title = null) => {
  if (!table) {
    return;
  }

  if (title) {
    sheet.addRow([]);
    setSectionTitleRow(sheet, sheet.lastRow.number + 1, title);
  }

  const columns = table.columns || [];
  const headerRow = sheet.addRow(columns.map((column) => column.label));
  applyTableHeaderStyle(headerRow);

  if ((table.rows || []).length) {
    table.rows.forEach((tableRow) => {
      const row = sheet.addRow(
        columns.map((column) =>
          column.type === "amount"
            ? Number(tableRow[column.key] || 0)
            : formatValue(tableRow[column.key], column),
        ),
      );
      styleDataRow(row, columns, tableRow.row_type);
    });
  } else {
    sheet.addRow([table.emptyMessage || "Aucune donnée."]);
  }
};

const autoFitColumns = (sheet) => {
  const widths = [];

  sheet.eachRow((row) => {
    row.eachCell((cell, columnNumber) => {
      const raw = cell.value?.richText
        ? cell.value.richText.map((item) => item.text).join("")
        : cell.value;
      const length = String(raw ?? "").length;
      widths[columnNumber] = Math.max(widths[columnNumber] || 12, Math.min(length + 3, 40));
    });
  });

  widths.forEach((width, index) => {
    sheet.getColumn(index).width = width;
  });
};

export const exportReportAsPdf = async (report) => {
  const browser = await launchPuppeteerBrowser();

  try {
    const page = await browser.newPage();
    await page.setContent(buildHtml(report), {
      waitUntil: "networkidle0",
    });

    return await page.pdf({
      format: "A4",
      landscape: Boolean(report.landscape),
      printBackground: true,
      displayHeaderFooter: true,
      headerTemplate: buildHeaderTemplate(report),
      footerTemplate: buildFooterTemplate(report),
      margin: {
        top: "22mm",
        right: "12mm",
        bottom: "20mm",
        left: "12mm",
      },
    });
  } finally {
    await browser.close();
  }
};

export const exportReportAsExcel = async (report) => {
  const excelJsModule = await import("exceljs");
  const ExcelJS = excelJsModule.default || excelJsModule;
  const workbook = new ExcelJS.Workbook();
  workbook.creator = "Compta Control";
  workbook.created = new Date();

  const sheet = workbook.addWorksheet(
    normalizeSheetName(report.title, "Rapport"),
    {
      views: [{ state: "frozen", ySplit: 6 }],
    },
  );

  sheet.mergeCells("A1:F1");
  sheet.getCell("A1").value = report.company?.name || "Société";
  sheet.getCell("A1").font = { bold: true, size: 18, color: { argb: "FF0F172A" } };

  sheet.mergeCells("A2:F2");
  sheet.getCell("A2").value = report.title || "Rapport";
  sheet.getCell("A2").font = { bold: true, size: 14, color: { argb: "FF2563EB" } };

  sheet.getCell("A3").value = "NIF";
  sheet.getCell("B3").value = report.company?.nif || "—";
  sheet.getCell("C3").value = "RC";
  sheet.getCell("D3").value = report.company?.rc || "—";
  sheet.getCell("E3").value = "Généré le";
  sheet.getCell("F3").value = report.generated_at || "—";

  sheet.getCell("A4").value = "Adresse";
  sheet.getCell("B4").value =
    [report.company?.address, report.company?.city].filter(Boolean).join(", ") || "—";
  sheet.getCell("E4").value = "Par";
  sheet.getCell("F4").value = report.generated_by || "Système";

  if ((report.parameters || []).length) {
    sheet.addRow([]);
    setSectionTitleRow(sheet, 6, "Paramètres");
    addParameterRows(sheet, report.parameters);
  }

  if ((report.cards || []).length) {
    sheet.addRow([]);
    setSectionTitleRow(sheet, sheet.lastRow.number + 1, "Indicateurs");
    addSummaryRows(sheet, report.cards);
  }

  if (report.table) {
    sheet.addRow([]);
    addTableBlock(sheet, report.table, "Données");
    if ((report.summary || []).length) {
      sheet.addRow([]);
      setSectionTitleRow(sheet, sheet.lastRow.number + 1, "Totaux");
      addSummaryRows(sheet, report.summary);
    }
  }

  (report.sections || []).forEach((section) => {
    sheet.addRow([]);
    addTableBlock(
      sheet,
      {
        columns: section.columns,
        rows: section.rows,
        emptyMessage: section.empty_message,
      },
      section.title || "Section",
    );

    if ((section.meta || []).length) {
      addParameterRows(sheet, section.meta);
    }

    if ((section.summary || []).length) {
      addSummaryRows(sheet, section.summary);
    }
  });

  autoFitColumns(sheet);

  return workbook.xlsx.writeBuffer();
};
