/**
 * learn.ts — Falah Micro Learning Core Library
 *
 * Certificate serial generation, PDF creation, course helpers.
 */

import { createHash, randomBytes } from "crypto";

// ──────────────────────────────────────
// SERIAL NUMBER GENERATION
// ──────────────────────────────────────

const SERIAL_SECRET = process.env.SERIAL_SECRET || "falah-academy-serial-v1";

/**
 * Generate a unique, verifiable certificate serial number.
 *
 * Format: FAL-ACAD-{COURSE}-{DATE}-{CHECKSUM}
 * Example: FAL-ACAD-ATOMI-20260715-A7X9K
 *
 * The checksum is an HMAC of userId + courseId + date so that
 * forged serials can be detected without a database lookup.
 */
export function generateSerialNumber(
  userId: string,
  courseId: string,
  courseSlug: string,
  date: Date = new Date()
): string {
  const prefix = "FAL";
  const issuer = "ACAD";
  const courseCode = courseSlug
    .toUpperCase()
    .replace(/[^A-Z0-9]/g, "")
    .slice(0, 5)
    .padEnd(5, "X");

  const datePart = date.toISOString().slice(0, 10).replace(/-/g, ""); // YYYYMMDD

  const hashInput = `${userId}:${courseId}:${datePart}:${SERIAL_SECRET}`;
  const checksum = createHash("sha256")
    .update(hashInput)
    .digest("hex")
    .slice(0, 5)
    .toUpperCase();

  return `${prefix}-${issuer}-${courseCode}-${datePart}-${checksum}`;
}

/**
 * Quick validity check — does the serial format and checksum match?
 * Does NOT check revocation status (call the DB for that).
 */
export function verifySerialFormat(serial: string): boolean {
  const pattern = /^FAL-ACAD-[A-Z0-9]{5}-\d{8}-[A-Z0-9]{5}$/;
  if (!pattern.test(serial)) return false;

  // We re-derive the checksum to verify, but need the original inputs.
  // The DB lookup is the authoritative check. This just catches format errors.
  return true;
}

/**
 * Generate a random 6-digit PIN for certificate sharing (optional).
 */
export function generateSharePin(): string {
  return Math.floor(100000 + Math.random() * 900000).toString();
}

// ──────────────────────────────────────
// PDF CERTIFICATE GENERATION
// ──────────────────────────────────────

import PDFDocument from "pdfkit";
import * as fs from "fs";
import * as path from "path";

const CERT_DIR = process.env.CERT_DIR || "/data/certificates";
const ACADEMY_URL = process.env.ACADEMY_URL || "https://academy.falahos.my";

// Falah design tokens
const GOLD = "#C9A84C";
const GOLD_LIGHT = "#E8C97A";
const BG_DARK = "#07090C";
const BG_SURFACE = "#0C1017";
const TEXT_LIGHT = "#E4DFD7";
const TEXT_DIM = "#8A8680";
const GREEN = "#00C48C";

export interface CertificateData {
  serialNumber: string;
  userName: string;
  courseTitle: string;
  courseAuthor: string;
  moduleCount: number;
  score?: number;
  issuedAt: Date;
  verifyUrl: string;
}

/**
 * Generate a PDF certificate and return the file path.
 */
export async function generateCertificatePdf(
  data: CertificateData
): Promise<string> {
  // Ensure output directory exists
  const dir = CERT_DIR;
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir, { recursive: true });
  }

  const filename = `${data.serialNumber}.pdf`;
  const filePath = path.join(dir, filename);

  return new Promise((resolve, reject) => {
    const doc = new PDFDocument({
      size: "A4",
      layout: "landscape",
      margins: { top: 40, bottom: 40, left: 40, right: 40 },
      info: {
        Title: `Falah Academy Certificate - ${data.courseTitle}`,
        Author: "Falah Academy (UK)",
        Subject: data.serialNumber,
      },
    });

    const stream = fs.createWriteStream(filePath);
    stream.on("finish", () => resolve(filePath));
    stream.on("error", reject);

    doc.pipe(stream);

    const pageWidth = doc.page.width;
    const pageHeight = doc.page.height;
    const margin = 40;
    const innerW = pageWidth - margin * 2;
    const innerH = pageHeight - margin * 2;

    // ── Dark background ──
    doc.rect(0, 0, pageWidth, pageHeight).fill(BG_DARK);

    // ── Gold border frame ──
    doc
      .rect(margin, margin, innerW, innerH)
      .lineWidth(2)
      .stroke(GOLD);

    // ── Inner subtle border ──
    doc
      .rect(margin + 8, margin + 8, innerW - 16, innerH - 16)
      .lineWidth(0.5)
      .strokeColor(GOLD)
      .opacity(0.3)
      .stroke()
      .opacity(1);

    // ── Top bar ──
    doc
      .rect(margin + 12, margin + 12, innerW - 24, 2)
      .fill(GOLD)
      .opacity(0.4);

    // ── Falah Academy Logo / Header ──
    doc
      .fontSize(14)
      .font("Helvetica-Bold")
      .fillColor(GOLD)
      .text("FALAH ACADEMY (UK)", margin + 30, margin + 30, {
        width: innerW - 60,
        align: "center",
      });

    // ── Decorative line under header ──
    doc
      .moveTo(pageWidth / 2 - 80, margin + 52)
      .lineTo(pageWidth / 2 + 80, margin + 52)
      .lineWidth(1)
      .strokeColor(GOLD)
      .opacity(0.6)
      .stroke()
      .opacity(1);

    // ── "Certificate of Completion" ──
    doc
      .fontSize(22)
      .font("Helvetica-Bold")
      .fillColor(GOLD_LIGHT)
      .text("Certificate of Completion", margin + 30, margin + 68, {
        width: innerW - 60,
        align: "center",
      });

    // ── "This certifies that" ──
    doc
      .fontSize(11)
      .font("Helvetica")
      .fillColor(TEXT_DIM)
      .text("This certifies that", margin + 30, margin + 110, {
        width: innerW - 60,
        align: "center",
      });

    // ── User name ──
    doc
      .fontSize(28)
      .font("Helvetica-Bold")
      .fillColor(GREEN)
      .text(data.userName, margin + 30, margin + 132, {
        width: innerW - 60,
        align: "center",
      });

    // ── "has successfully completed" ──
    doc
      .fontSize(11)
      .font("Helvetica")
      .fillColor(TEXT_DIM)
      .text("has successfully completed the", margin + 30, margin + 172, {
        width: innerW - 60,
        align: "center",
      });

    // ── Course title ──
    doc
      .fontSize(18)
      .font("Helvetica-Bold")
      .fillColor(TEXT_LIGHT)
      .text(`"${data.courseTitle}"`, margin + 30, margin + 196, {
        width: innerW - 60,
        align: "center",
      });

    // ── Micro Learning Course label ──
    doc
      .fontSize(10)
      .font("Helvetica")
      .fillColor(TEXT_DIM)
      .text("Micro Learning Course", margin + 30, margin + 226, {
        width: innerW - 60,
        align: "center",
      });

    // ── Stats row ──
    const statsY = margin + 256;
    const statsText = `${data.moduleCount} module${
      data.moduleCount !== 1 ? "s" : ""
    } completed`;
    doc.fontSize(10).font("Helvetica").fillColor(TEXT_DIM).text(
      statsText,
      margin + 30,
      statsY,
      { width: innerW - 60, align: "center" }
    );

    if (data.score !== undefined) {
      doc
        .fontSize(10)
        .font("Helvetica")
        .fillColor(GREEN)
        .text(
          `Score: ${Math.round(data.score)}%`,
          margin + 30,
          statsY + 16,
          { width: innerW - 60, align: "center" }
        );
    }

    // ── Serial number ──
    const serialY = pageHeight - margin - 85;
    doc
      .fontSize(8)
      .font("Helvetica")
      .fillColor(TEXT_DIM)
      .text(`Serial: ${data.serialNumber}`, margin + 30, serialY, {
        width: innerW - 60,
        align: "center",
      });

    // ── Issue date ──
    doc
      .fontSize(8)
      .font("Helvetica")
      .fillColor(TEXT_DIM)
      .text(
        `Issued: ${data.issuedAt.toLocaleDateString("en-GB", {
          day: "numeric",
          month: "long",
          year: "numeric",
        })}`,
        margin + 30,
        serialY + 14,
        { width: innerW - 60, align: "center" }
      );

    // ── Verify URL ──
    doc
      .fontSize(7)
      .font("Helvetica")
      .fillColor(TEXT_DIM)
      .text(
        `Verify at: ${data.verifyUrl}`,
        margin + 30,
        serialY + 28,
        { width: innerW - 60, align: "center" }
      );

    // ── Bottom bar ──
    doc
      .rect(margin + 12, pageHeight - margin - 12, innerW - 24, 2)
      .fill(GOLD)
      .opacity(0.4);

    // ── Footer ──
    doc
      .fontSize(7)
      .font("Helvetica")
      .fillColor(TEXT_DIM)
      .opacity(0.6)
      .text(
        "Falah Academy (UK) · academy.falahos.my",
        margin + 30,
        pageHeight - margin - 8,
        { width: innerW - 60, align: "center" }
      );

    doc.end();
  });
}

// ──────────────────────────────────────
// COURSE CONTENT HELPERS
// ──────────────────────────────────────

/**
 * Parse and cache course content from Gitea-hosted markdown.
 * Lightweight — just returns processed markdown with metadata.
 */
export function extractKeyTakeaway(markdown: string): string {
  // First non-empty, non-heading line after the first ## heading
  const lines = markdown.split("\n");
  for (const line of lines) {
    const trimmed = line.trim();
    if (trimmed && !trimmed.startsWith("#") && !trimmed.startsWith("---")) {
      return trimmed.slice(0, 200);
    }
  }
  return "";
}

/**
 * Estimate reading time in minutes from markdown content.
 */
export function estimateReadingTime(markdown: string): number {
  const text = markdown.replace(/[#*`\[\]()>|_-]/g, " ");
  const wordCount = text.split(/\s+/).filter(Boolean).length;
  return Math.max(1, Math.ceil(wordCount / 200)); // 200 wpm
}

/**
 * Build the public verification URL for a certificate.
 */
export function buildVerifyUrl(serialNumber: string): string {
  return `${ACADEMY_URL}/verify/${serialNumber}`;
}
