import { NextRequest, NextResponse } from "next/server";
import { verifyToken, getTokenFromRequest } from "@/lib/jwt";
import { prisma } from "@/lib/prisma";
import bcrypt from "bcryptjs";
import * as XLSX from "xlsx";
import { z } from "zod";

// Schema untuk validasi data guru dari Excel
const GuruExcelSchema = z.object({
  NIP: z.string().min(1, "NIP tidak boleh kosong"),
  Nama: z.string().min(1, "Nama tidak boleh kosong"),
  Username: z.string().min(3, "Username minimal 3 karakter").max(20, "Username maksimal 20 karakter"),
  Password: z.string().min(6, "Password minimal 6 karakter"),
  Email: z.string().optional().or(z.literal("")),
  "No WA": z.string().optional(),
});

export async function POST(request: NextRequest) {
  try {
    const token = getTokenFromRequest(request);

    if (!token) {
      return NextResponse.json({ success: false, message: "Token tidak ditemukan" }, { status: 401 });
    }

    const payload = verifyToken(token);
    if (!payload) {
      return NextResponse.json({ success: false, message: "Token tidak valid" }, { status: 401 });
    }

    // Check if user is admin
    if (payload.role !== "ADMIN") {
      return NextResponse.json(
        { success: false, message: "Hanya admin yang dapat mengimpor data guru" },
        { status: 403 },
      );
    }

    const formData = await request.formData();
    const file = formData.get("file") as File;

    if (!file) {
      return NextResponse.json({ success: false, message: "File tidak ditemukan" }, { status: 400 });
    }

    // Validate file type
    if (!file.name.endsWith(".xlsx") && !file.name.endsWith(".xls")) {
      return NextResponse.json(
        { success: false, message: "File harus berformat Excel (.xlsx atau .xls)" },
        { status: 400 },
      );
    }

    // Read Excel file
    const buffer = await file.arrayBuffer();
    const workbook = XLSX.read(buffer, { type: "array" });
    const sheetName = workbook.SheetNames[0];
    const worksheet = workbook.Sheets[sheetName];

    // Convert to JSON with string conversion for all values
    const rawJsonData = XLSX.utils.sheet_to_json(worksheet);

    if (rawJsonData.length === 0) {
      return NextResponse.json(
        { success: false, message: "File Excel kosong atau tidak memiliki data" },
        { status: 400 },
      );
    }

    // Convert all values to strings to handle Excel number formatting
    const jsonData = rawJsonData.map((row) => {
      const convertedRow: Record<string, string> = {};
      const rowData = row as Record<string, unknown>;
      for (const [key, value] of Object.entries(rowData)) {
        // Convert all values to strings, handling null/undefined
        convertedRow[key] = value !== null && value !== undefined ? String(value).trim() : "";
      }
      return convertedRow;
    });

    // Validate and process data
    const validatedData = [];
    const errors = [];

    for (let i = 0; i < jsonData.length; i++) {
      const row = jsonData[i] as Record<string, string>;

      try {
        const validatedRow = GuruExcelSchema.parse(row);

        // Check for duplicate NIP, username, atau email
        const existingGuruByNip = await prisma.guru.findUnique({
          where: { nip: validatedRow.NIP },
        });

        // Only check for email duplicates if email is provided and not empty
        const emailConditions = [];
        if (validatedRow.Email && validatedRow.Email.trim() !== "") {
          emailConditions.push({ email: validatedRow.Email });
        }

        const existingUser = await prisma.user.findFirst({
          where: {
            OR: [{ username: validatedRow.Username }, ...emailConditions],
          },
          select: {
            username: true,
            email: true,
          },
        });

        if (existingGuruByNip) {
          errors.push(`Baris ${i + 2}: NIP ${validatedRow.NIP} sudah ada dalam database`);
          continue;
        }

        if (existingUser) {
          const field = existingUser.username === validatedRow.Username ? "Username" : "Email";
          const value = existingUser.username === validatedRow.Username ? validatedRow.Username : validatedRow.Email;
          errors.push(`Baris ${i + 2}: ${field} ${value} sudah ada dalam database`);
          continue;
        }

        validatedData.push({
          nip: validatedRow.NIP,
          nama: validatedRow.Nama,
          username: validatedRow.Username,
          password: validatedRow.Password,
          email: validatedRow.Email,
          noWa: validatedRow["No WA"] || "",
        });
      } catch (error) {
        if (error instanceof z.ZodError) {
          const errorMessages = error.errors.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ");
          errors.push(`Baris ${i + 2}: ${errorMessages}`);
        } else {
          errors.push(`Baris ${i + 2}: Data tidak valid`);
        }
      }
    }

    // Save valid data to database with auto user registration
    const savedData = [];
    for (const data of validatedData) {
      try {
        // Hash password untuk user
        const hashedPassword = await bcrypt.hash(data.password, 12);

        // Buat user terlebih dahulu dengan role GURU
        // Use username as email if email is not provided
        const userEmail = data.email && data.email.trim() !== "" ? data.email : `${data.username}@sekolah.local`;

        const newUser = await prisma.user.create({
          data: {
            username: data.username,
            email: userEmail,
            password: hashedPassword,
            role: "GURU",
          },
        });

        // Buat data guru yang terhubung dengan user
        const newGuru = await prisma.guru.create({
          data: {
            nip: data.nip,
            nama: data.nama,
            noWa: data.noWa || null,
            userId: newUser.id, // Hubungkan dengan user yang baru dibuat
          },
        });

        savedData.push(newGuru);
      } catch (dbError) {
        console.error("Error saving guru:", dbError);
        errors.push(
          `Gagal menyimpan data guru ${data.nama}: ${dbError instanceof Error ? dbError.message : "Unknown error"}`,
        );
      }
    }

    return NextResponse.json({
      success: true,
      data: {
        imported: savedData.length,
        total: jsonData.length,
        errors: errors.length,
        errorDetails: errors,
      },
      message: `Berhasil mengimpor ${savedData.length} dari ${jsonData.length} data guru`,
    });
  } catch (error) {
    console.error("Error importing guru:", error);
    return NextResponse.json({ success: false, message: "Terjadi kesalahan saat mengimpor data" }, { status: 500 });
  }
}

export async function GET() {
  // Endpoint untuk download template Excel
  try {
    const templateData = [
      {
        NIP: "196812345678901234",
        Nama: "Contoh Nama Guru",
        Username: "guru123",
        Password: "password123",
        Email: "guru123@sekolah.com",
        "No WA": "081234567890",
      },
    ];

    // Create workbook and worksheet
    const workbook = XLSX.utils.book_new();
    const worksheet = XLSX.utils.json_to_sheet(templateData);

    // Add worksheet to workbook
    XLSX.utils.book_append_sheet(workbook, worksheet, "Template Guru");

    // Generate buffer
    const buffer = XLSX.write(workbook, { type: "buffer", bookType: "xlsx" });

    // Return file
    return new NextResponse(buffer, {
      headers: {
        "Content-Type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        "Content-Disposition": "attachment; filename=template-guru.xlsx",
      },
    });
  } catch (error) {
    console.error("Error creating template:", error);
    return NextResponse.json({ success: false, message: "Gagal membuat template" }, { status: 500 });
  }
}
