import { PrismaClient, ContentStatus, Visibility, type Prisma } from "@prisma/client";

const prisma = new PrismaClient();

type RichNode = {
  type: string;
  attrs?: Record<string, unknown>;
  content?: RichNode[];
  text?: string;
  marks?: { type: string; attrs?: Record<string, unknown> }[];
};

const text = (value: string, marks?: RichNode["marks"]): RichNode => ({ type: "text", text: value, ...(marks ? { marks } : {}) });
const paragraph = (...content: RichNode[]): RichNode => ({ type: "paragraph", content });
const heading = (value: string, level = 2): RichNode => ({ type: "heading", attrs: { level }, content: [text(value)] });
const list = (items: string[], ordered = false): RichNode => ({
  type: ordered ? "orderedList" : "bulletList",
  content: items.map((item) => ({ type: "listItem", content: [paragraph(text(item))] })),
});
const image = (src: string, alt: string): RichNode => ({ type: "image", attrs: { src, alt, title: alt } });
const code = (value: string, language: string): RichNode => ({ type: "codeBlock", attrs: { language }, content: [text(value)] });
const link = (label: string, href: string): RichNode => text(label, [{ type: "link", attrs: { href, target: "_blank" } }]);

const content: RichNode = {
  type: "doc",
  content: [
    paragraph(text("XAMPP adalah paket server lokal yang membantu kita menjalankan dan menguji aplikasi web berbasis PHP serta database di komputer sendiri. Materi ini membahas konsep, komponen, instalasi, penggunaan, keamanan, dan pemecahan masalahnya secara bertahap.")),
    heading("Tujuan Pembelajaran"),
    list([
      "Menjelaskan pengertian, fungsi, dan komponen utama XAMPP.",
      "Menjalankan Apache dan MariaDB melalui XAMPP Control Panel.",
      "Menyimpan serta membuka proyek PHP dari folder htdocs.",
      "Membuat database dan tabel melalui phpMyAdmin maupun perintah SQL.",
      "Mendiagnosis konflik port dan menerapkan penggunaan XAMPP yang aman.",
    ]),
    heading("1. Apa Itu XAMPP?"),
    paragraph(text("XAMPP adalah distribusi Apache yang mudah dipasang dan berisi MariaDB, PHP, serta Perl. Huruf X berarti cross-platform, sehingga konsep paketnya tersedia untuk beberapa sistem operasi. A berarti Apache, M saat ini merujuk pada MariaDB (versi lama memakai MySQL), sedangkan dua huruf P berarti PHP dan Perl.")),
    paragraph(text("Dengan XAMPP, komputer bertindak sebagai server lokal. Alamat localhost atau 127.0.0.1 menunjuk kembali ke komputer yang sedang digunakan. Karena itu, siswa dapat mengembangkan aplikasi tanpa terlebih dahulu menyewa hosting atau membuka aplikasi ke internet.")),
    image("/uploads/materials/xampp-guide/cover-xampp.png", "Ilustrasi XAMPP sebagai lingkungan server lokal"),
    heading("2. Cara Kerja Server Lokal"),
    paragraph(text("Alur sederhananya adalah: browser mengirim permintaan ke localhost → Apache menerima permintaan → bila berkas berisi PHP, interpreter PHP menjalankan kodenya → PHP dapat membaca atau menulis data melalui MariaDB → Apache mengirimkan hasil HTML kembali ke browser.")),
    list([
      "Browser: antarmuka yang dipakai pengguna untuk mengakses aplikasi.",
      "Apache: web server yang menerima permintaan HTTP/HTTPS.",
      "PHP: bahasa sisi server yang menghasilkan respons dinamis.",
      "MariaDB: sistem manajemen database relasional untuk menyimpan data.",
      "phpMyAdmin: antarmuka web untuk mengelola MariaDB secara visual.",
    ]),
    heading("3. Komponen Penting dalam XAMPP"),
    {
      type: "table",
      content: [
        { type: "tableRow", content: ["Komponen", "Fungsi", "Port umum"].map((v) => ({ type: "tableHeader", content: [paragraph(text(v))] })) },
        ...[
          ["Apache", "Melayani halaman web dan menjalankan aplikasi melalui HTTP/HTTPS.", "80 / 443"],
          ["MariaDB", "Menyimpan data relasional; kompatibel dengan perintah dan alat MySQL yang umum.", "3306"],
          ["PHP", "Memproses logika aplikasi di sisi server.", "Melalui Apache"],
          ["phpMyAdmin", "Mengelola database, tabel, pengguna, impor, ekspor, dan SQL dari browser.", "Melalui Apache"],
          ["FileZilla", "FTP server untuk latihan pemindahan berkas melalui protokol FTP/FTPS.", "21 / 990"],
          ["Mercury", "Mail server untuk pengujian pengiriman dan penerimaan email di lingkungan lokal.", "25 / 110 / 143"],
          ["Tomcat", "Application server untuk menjalankan aplikasi web Java seperti Servlet dan JSP.", "8080"],
          ["Perl", "Bahasa pemrograman yang ikut disertakan dalam paket XAMPP.", "—"],
        ].map((row) => ({ type: "tableRow", content: row.map((v) => ({ type: "tableCell", content: [paragraph(text(v))] })) })),
      ],
    },
    heading("4. Penjelasan Modul pada XAMPP Control Panel"),
    heading("Apache", 3),
    paragraph(text("Apache HTTP Server adalah web server. Modul ini menerima permintaan dari browser, mencari berkas di folder htdocs, menjalankan PHP melalui integrasinya, kemudian mengirim hasilnya kembali ke browser. Apache wajib aktif ketika kita membuka proyek melalui http://localhost. Port bawaannya adalah 80 untuk HTTP dan 443 untuk HTTPS.")),
    heading("MySQL/MariaDB", 3),
    paragraph(text("Tombol MySQL pada Control Panel menjalankan server database. Pada XAMPP versi modern, mesin yang sebenarnya digunakan adalah MariaDB, yaitu sistem database yang sangat kompatibel dengan MySQL. Modul ini diperlukan jika aplikasi menyimpan data pengguna, produk, nilai, artikel, atau data lain. Port bawaannya adalah 3306. Tombol Admin biasanya membuka phpMyAdmin.")),
    heading("FileZilla", 3),
    paragraph(text("FileZilla pada XAMPP adalah FTP server, bukan aplikasi editor kode. FTP digunakan untuk memindahkan berkas antara komputer klien dan server. Modul ini tidak diperlukan untuk menjalankan proyek PHP biasa di localhost. Aktifkan hanya jika sedang mempelajari FTP, lalu buat akun dan kata sandi agar server tidak terbuka tanpa pengamanan.")),
    heading("Mercury", 3),
    paragraph(text("Mercury adalah mail server yang mendukung protokol email seperti SMTP untuk mengirim pesan serta POP3 atau IMAP untuk mengambil pesan. Modul ini dapat dipakai untuk simulasi email lokal, tetapi tidak diperlukan untuk proyek PHP biasa. Konfigurasinya lebih kompleks karena melibatkan akun, domain, port, dan aturan jaringan.")),
    heading("Tomcat", 3),
    paragraph(text("Apache Tomcat adalah application server untuk teknologi Java, terutama Servlet dan JSP. Tomcat berbeda dari Apache HTTP Server: Apache melayani web umum dan PHP, sedangkan Tomcat menjalankan aplikasi Java. Siswa yang hanya belajar PHP tidak perlu mengaktifkannya. Port yang umum digunakan Tomcat adalah 8080.")),
    { type: "blockquote", content: [paragraph(text("Untuk kegiatan PHP dan database dasar, cukup jalankan Apache dan MySQL. FileZilla, Mercury, dan Tomcat dibiarkan berhenti kecuali memang diperlukan oleh latihan."))] },
    heading("5. Instalasi XAMPP di Windows"),
    list([
      "Unduh installer hanya dari situs resmi Apache Friends.",
      "Jalankan installer, pilih komponen yang diperlukan, lalu gunakan lokasi sederhana seperti C:\\xampp.",
      "Selesaikan instalasi dan buka C:\\xampp\\xampp-control.exe.",
      "Pada Control Panel, tekan Start untuk Apache dan MySQL. Baris yang aktif biasanya berubah hijau.",
      "Buka http://localhost/ atau http://127.0.0.1/ untuk menguji Apache.",
    ], true),
    { type: "blockquote", content: [paragraph(text("Catatan: nama modul pada Control Panel dapat tertulis MySQL, tetapi XAMPP modern memakai MariaDB sebagai server databasenya."))] },
    heading("6. Cara Menggunakan XAMPP Control Panel"),
    paragraph(text("XAMPP Control Panel adalah pusat untuk menyalakan, menghentikan, mengatur, dan memeriksa modul server. Buka melalui Start Menu atau jalankan C:\\xampp\\xampp-control.exe. Bila perlu mengelola Windows Service atau mengalami masalah izin, gunakan Run as administrator.")),
    image("/uploads/materials/xampp-guide/xampp-control-panel.png", "Screenshot XAMPP Control Panel dengan Apache dan MySQL aktif"),
    paragraph(text("Perhatikan kolom Actions pada screenshot. Apache dan MySQL berwarna hijau serta tombolnya bertuliskan Stop, artinya keduanya sudah aktif. Ketika belum aktif, tombol pada posisi yang sama bertuliskan Start. Untuk belajar PHP dan database, klik Start pada baris Apache terlebih dahulu, kemudian klik Start pada baris MySQL. Jangan menekan Start pada FileZilla, Mercury, atau Tomcat karena modul tersebut tidak diperlukan untuk latihan ini.")),
    list([
      "Langkah 1 — Buka XAMPP Control Panel dan cari baris Apache paling atas.",
      "Langkah 2 — Klik Start di sebelah kanan baris Apache. Tunggu baris berwarna hijau serta port 80 dan 443 muncul.",
      "Langkah 3 — Klik Start di sebelah kanan baris MySQL. Tunggu baris berwarna hijau serta port 3306 muncul.",
      "Langkah 4 — Klik Admin pada baris Apache untuk membuka Dashboard XAMPP di browser.",
      "Langkah 5 — Klik Admin pada baris MySQL untuk membuka phpMyAdmin dan mengelola database.",
      "Kerjakan dan uji proyek dari folder C:\\xampp\\htdocs melalui alamat http://localhost/nama-folder.",
      "Setelah selesai, klik Stop pada MySQL lalu Apache. Tunggu sampai warna hijau hilang sebelum menutup Control Panel.",
    ], true),
    heading("Arti Tombol dan Indikator Control Panel", 3),
    list([
      "Start: menyalakan modul. Setelah aktif, tombol berubah menjadi Stop.",
      "Stop: menghentikan modul dengan benar agar port dan file yang sedang dipakai dilepaskan.",
      "Admin: membuka alat administrasi modul, misalnya Dashboard untuk Apache dan phpMyAdmin untuk MySQL.",
      "Config pada baris modul: membuka konfigurasi khusus modul, misalnya httpd.conf atau my.ini.",
      "Logs: membuka log modul. Bagian ini pertama kali diperiksa ketika modul gagal berjalan.",
      "Service/checkbox: memasang modul sebagai Windows Service agar dapat berjalan sebagai layanan sistem. Pemula tidak perlu mengaktifkannya.",
      "PID: nomor identitas proses yang sedang berjalan.",
      "Port(s): jalur komunikasi jaringan yang sedang digunakan modul.",
      "Warna hijau: modul aktif. Warna merah atau pesan error: modul gagal dan detailnya perlu dibaca pada panel log.",
      "Config di sisi kanan: pengaturan umum Control Panel; Netstat memeriksa port; Shell membuka command line XAMPP; Explorer membuka folder XAMPP; Quit menutup Control Panel.",
    ]),
    paragraph(text("Urutan yang aman adalah Start Apache dan MySQL sebelum membuka aplikasi, kemudian Stop keduanya setelah pekerjaan selesai. Jangan menutup Control Panel secara paksa ketika database sedang memproses data karena berisiko mengganggu file database.")),
    heading("7. Mengenal Dashboard XAMPP"),
    image("/uploads/materials/xampp-guide/xampp-dashboard.png", "Screenshot halaman Dashboard XAMPP lokal"),
    paragraph(text("Screenshot di atas diambil dari instalasi XAMPP lokal. Jika halaman ini muncul saat membuka localhost, Apache telah bekerja. Dashboard juga menyediakan tautan PHPInfo dan phpMyAdmin. Pesan pada dashboard menegaskan bahwa konfigurasi bawaan XAMPP ditujukan untuk pengembangan, bukan server produksi yang dapat diakses publik.")),
    heading("8. Membuat Proyek PHP di htdocs"),
    paragraph(text("Document root bawaan XAMPP berada di C:\\xampp\\htdocs. Buat folder C:\\xampp\\htdocs\\belajar-xampp, kemudian buat berkas index.php berikut:")),
    code("<?php\n$nama = 'Siswa RPL';\necho '<h1>Halo, ' . htmlspecialchars($nama) . '!</h1>';\necho '<p>PHP di XAMPP berhasil dijalankan.</p>';", "php"),
    paragraph(text("Simpan berkas tersebut lalu buka http://localhost/belajar-xampp/. Jangan membuka index.php dengan klik ganda karena PHP harus diproses melalui Apache.")),
    heading("9. Mengelola Database dengan phpMyAdmin"),
    paragraph(text("Buka http://localhost/phpmyadmin/ atau klik tombol Admin pada modul MySQL di Control Panel. Tampilan instalasi lokal Anda terlihat seperti berikut:")),
    image("/uploads/materials/xampp-guide/phpmyadmin.png", "Screenshot phpMyAdmin pada XAMPP lokal"),
    paragraph(text("Panel kiri menampilkan daftar database. Tab Databases dipakai membuat database, SQL untuk menjalankan perintah, serta Export dan Import untuk pencadangan atau pemindahan data.")),
    paragraph(text("Contoh latihan: buka tab SQL lalu jalankan perintah berikut secara berurutan.")),
    code("CREATE DATABASE latihan_xampp\n  CHARACTER SET utf8mb4\n  COLLATE utf8mb4_unicode_ci;\n\nUSE latihan_xampp;\n\nCREATE TABLE siswa (\n  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,\n  nis VARCHAR(20) NOT NULL UNIQUE,\n  nama VARCHAR(100) NOT NULL,\n  kelas VARCHAR(20) NOT NULL\n);\n\nINSERT INTO siswa (nis, nama, kelas)\nVALUES ('1001', 'Budi Santoso', 'XI-RPL 1');\n\nSELECT * FROM siswa;", "sql"),
    heading("10. Menghubungkan PHP ke MariaDB"),
    paragraph(text("Gunakan PDO dan prepared statement untuk koneksi yang lebih aman. Contoh akun root tanpa kata sandi berikut hanya sesuai konfigurasi pengembangan lokal bawaan; jangan gunakan pola ini di produksi.")),
    code("<?php\n$dsn = 'mysql:host=127.0.0.1;dbname=latihan_xampp;charset=utf8mb4';\n\ntry {\n    $pdo = new PDO($dsn, 'root', '', [\n        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,\n        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,\n    ]);\n\n    $stmt = $pdo->query('SELECT nis, nama, kelas FROM siswa');\n    foreach ($stmt as $siswa) {\n        echo htmlspecialchars($siswa['nama']) . '<br>';\n    }\n} catch (PDOException $error) {\n    exit('Koneksi database gagal. Periksa konfigurasi server.');\n}", "php"),
    heading("11. Lokasi Konfigurasi Penting"),
    list([
      "Apache: C:\\xampp\\apache\\conf\\httpd.conf",
      "PHP: C:\\xampp\\php\\php.ini",
      "MariaDB/MySQL: C:\\xampp\\mysql\\bin\\my.ini",
      "Log Apache: C:\\xampp\\apache\\logs\\error.log",
      "Folder proyek web: C:\\xampp\\htdocs",
    ]),
    paragraph(text("Setelah mengubah konfigurasi Apache atau PHP, restart Apache agar perubahan dimuat. Buat cadangan sebelum mengubah file konfigurasi.")),
    heading("12. Masalah Umum dan Solusinya"),
    list([
      "Apache tidak bisa Start: periksa log dan pastikan port 80/443 tidak digunakan IIS, aplikasi server lain, atau proses lain.",
      "MariaDB/MySQL tidak bisa Start: periksa apakah port 3306 sudah dipakai layanan database lain dan baca log MySQL.",
      "localhost tidak dapat dibuka: pastikan Apache berstatus aktif dan gunakan http://localhost, bukan membuka file PHP secara langsung.",
      "Database tidak ditemukan: pastikan modul MySQL aktif serta nama database di kode sama persis dengan yang dibuat.",
      "Perubahan php.ini tidak berlaku: simpan file yang benar lalu Stop dan Start kembali Apache.",
      "Akses ditolak: periksa nama pengguna, kata sandi, host, dan hak akses pengguna database.",
    ]),
    heading("13. Keamanan dan Praktik Baik"),
    list([
      "Gunakan XAMPP untuk belajar dan pengembangan lokal; jangan menjadikannya server produksi dengan konfigurasi bawaan.",
      "Jangan membuka phpMyAdmin ke internet. Batasi akses ke komputer lokal.",
      "Gunakan kata sandi database yang kuat bila lingkungan dapat diakses pengguna lain.",
      "Simpan kredensial pada file .env dan jangan memasukkannya ke Git.",
      "Pisahkan setiap proyek dalam foldernya sendiri dan lakukan backup database melalui Export.",
      "Hentikan modul yang tidak dipakai dan selalu baca log saat terjadi masalah.",
      "Gunakan prepared statement untuk data dari pengguna agar terhindar dari SQL injection.",
    ]),
    heading("14. Latihan Mandiri"),
    list([
      "Buat folder proyek profil-siswa di dalam htdocs.",
      "Buat halaman PHP yang menampilkan nama, kelas, dan kompetensi keahlian.",
      "Buat database sekolah dan tabel siswa melalui phpMyAdmin.",
      "Masukkan minimal lima data siswa, lalu tampilkan datanya menggunakan PHP dan PDO.",
      "Uji kondisi ketika Apache atau MariaDB dihentikan, kemudian catat pesan kesalahan dan solusinya.",
    ], true),
    heading("Rangkuman"),
    paragraph(text("XAMPP menyatukan Apache, MariaDB, PHP, Perl, dan alat pendukung dalam lingkungan lokal yang mudah digunakan. Apache melayani permintaan web, PHP menjalankan logika aplikasi, MariaDB menyimpan data, dan phpMyAdmin membantu administrasi database. Pemahaman folder htdocs, port, konfigurasi, log, dan keamanan adalah dasar sebelum membangun aplikasi PHP yang lebih besar.")),
    heading("Referensi Resmi"),
    paragraph(link("Apache Friends — XAMPP FAQs for Windows", "https://www.apachefriends.org/faq_windows.html"), text(" (diakses sebagai rujukan komponen, lokasi konfigurasi, port, dan keamanan XAMPP).")),
  ],
};

const materialContent = content as unknown as Prisma.InputJsonObject;

async function main() {
  const targetClass = await prisma.class.findFirst({ where: { name: "XI-RPL 1" }, orderBy: { createdAt: "desc" } });
  const subject = await prisma.subject.findFirst({ where: { OR: [{ code: "DB-XI" }, { name: "Basis Data" }] } });
  const category = await prisma.category.findFirst({ where: { slug: "basis-data" } });
  const teacher = await prisma.user.findFirst({ where: { role: "TEACHER", status: "ACTIVE" } });

  if (!targetClass || !subject || !category || !teacher) {
    throw new Error("Kelas XI-RPL 1, mapel Basis Data, kategori basis-data, atau akun guru belum tersedia.");
  }

  const slug = "mengenal-xampp-local-web-server";
  const material = await prisma.material.upsert({
    where: { slug },
    create: {
      title: "Mengenal XAMPP: Local Web Server untuk PHP dan Database",
      slug,
      description: "Panduan lengkap memahami XAMPP, Apache, MariaDB, PHP, phpMyAdmin, htdocs, konfigurasi, keamanan, dan troubleshooting disertai screenshot nyata.",
      thumbnail: "/uploads/materials/xampp-guide/cover-xampp.png",
      semester: 1,
      content: materialContent,
      status: ContentStatus.PUBLISHED,
      visibility: Visibility.STUDENT_ONLY,
      publishedAt: new Date(),
      authorId: teacher.id,
      classId: targetClass.id,
      subjectId: subject.id,
      categoryId: category.id,
    },
    update: {
      title: "Mengenal XAMPP: Local Web Server untuk PHP dan Database",
      description: "Panduan lengkap memahami XAMPP, Apache, MariaDB, PHP, phpMyAdmin, htdocs, konfigurasi, keamanan, dan troubleshooting disertai screenshot nyata.",
      thumbnail: "/uploads/materials/xampp-guide/cover-xampp.png",
      semester: 1,
      content: materialContent,
      status: ContentStatus.PUBLISHED,
      visibility: Visibility.STUDENT_ONLY,
      publishedAt: new Date(),
      authorId: teacher.id,
      classId: targetClass.id,
      subjectId: subject.id,
      categoryId: category.id,
    },
  });

  const href = `/materi/${slug}`;
  await prisma.notification.deleteMany({ where: { type: "MATERIAL", href } });
  const students = await prisma.student.findMany({ where: { classId: targetClass.id, status: "ACTIVE", userId: { not: null } }, select: { userId: true } });
  if (students.length) {
    await prisma.notification.createMany({
      data: students.flatMap(({ userId }) => userId ? [{ userId, title: "Materi baru tersedia", message: material.title, type: "MATERIAL", href }] : []),
    });
  }

  console.log(`Materi terbit: ${material.title}`);
  console.log(`URL: ${href}`);
  console.log(`Notifikasi siswa: ${students.length}`);
}

main()
  .catch((error) => {
    console.error(error);
    process.exitCode = 1;
  })
  .finally(async () => prisma.$disconnect());
