const prisma = require("../lib/prisma");
const nodemailer = require("nodemailer");
const {
  notifyUser,
  notifyManyUsers,
} = require("../services/notification.service");

// Create salary
exports.createSalary = async (req, res) => {
  try {
    const { teacherId, amount, month } = req.body;
    if (!teacherId || !amount || !month)
      return res.status(400).json({ message: "All fields are required" });

    const teacher = await prisma.user.findUnique({
      where: { id: parseInt(teacherId) },
    });
    if (!teacher || teacher.role !== "teacher")
      return res.status(400).json({ message: "Invalid teacher ID" });

    // Create salary record
    const salary = await prisma.salary.create({
      data: {
        teacherId: parseInt(teacherId),
        amount: parseInt(amount),
        month,
        status: "pending",
      },
    });

    // Send email to teacher
    if (teacher.email) {
      const transporter = nodemailer.createTransport({
        host: process.env.SMTP_HOST,
        port: parseInt(process.env.SMTP_PORT),
        secure: Number(process.env.SMTP_PORT) === 465,
        auth: {
          user: process.env.SMTP_USER,
          pass: process.env.SMTP_PASS,
        },
      });

      // Beautiful premium email HTML
      const mailOptions = {
        from: `"Virtual Education Hub" <${process.env.SMTP_USER}>`,
        to: teacher.email,
        subject: `Your Salary for ${month} has been created`,
        html: `
        <div style="font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color:#f9f9f9; padding:30px;">
          <div style="max-width:600px; margin:auto; background-color:#fff; border-radius:8px; overflow:hidden; box-shadow:0 4px 20px rgba(0,0,0,0.1);">
            <div style="background:linear-gradient(90deg, #4e54c8, #8f94fb); color:#fff; padding:20px; text-align:center;">
              <h2 style="margin:0;">Salary Notification</h2>
              <p style="margin:5px 0 0;">${
                teacher.firstName
              }, your salary details are here!</p>
            </div>
            <div style="padding:30px;">
              <p>Hi <strong>${teacher.firstName}</strong>,</p>
              <p>A new salary record has been created for you:</p>
              <table style="width:100%; border-collapse:collapse; margin-top:15px;">
                <tr>
                  <td style="padding:10px; border:1px solid #ddd;"><strong>Month</strong></td>
                  <td style="padding:10px; border:1px solid #ddd;">${month}</td>
                </tr>
                <tr>
                  <td style="padding:10px; border:1px solid #ddd;"><strong>Amount</strong></td>
                  <td style="padding:10px; border:1px solid #ddd;">NPR ${amount.toLocaleString()}</td>
                </tr>
                <tr>
                  <td style="padding:10px; border:1px solid #ddd;"><strong>Status</strong></td>
                  <td style="padding:10px; border:1px solid #ddd; color:${
                    salary.status === "approved"
                      ? "green"
                      : salary.status === "rejected"
                      ? "red"
                      : "orange"
                  };"><strong>${
          salary.status.charAt(0).toUpperCase() + salary.status.slice(1)
        }</strong></td>
                </tr>
              </table>
              <p style="margin-top:20px;">You can log in to your account to view more details or download your salary slip.</p>
              <a href="${
                process.env.FRONTEND_URL
              }/login" style="display:inline-block; padding:12px 25px; background-color:#4e54c8; color:#fff; border-radius:5px; text-decoration:none; margin-top:10px;">View Salary</a>
            </div>
            <div style="background-color:#f1f1f1; padding:15px; text-align:center; font-size:12px; color:#555;">
              &copy; ${new Date().getFullYear()} Virtual Education Hub. All rights reserved.
            </div>
          </div>
        </div>
        `,
      };
      await transporter.sendMail(mailOptions);
    }

    // 🔔 Notify teacher (system notification)
    const notificationMessage = `⏳ Your salary for ${month} is currently being processed.
Amount: NPR ${amount.toLocaleString()}.

You’ll be notified once the payment is completed.`;
    await notifyUser(req, teacher.id, notificationMessage, null);
    return res.json({ message: "Salary record created", salary });
  } catch (err) {
    console.log(err);
    return res.status(500).json({ message: "Server error" });
  }
};

// Update salary status
exports.updateSalary = async (req, res) => {
  try {
    const salaryId = parseInt(req.params.id);
    const { teacherId, amount, month, status, description } = req.body;

    // Fetch existing salary including teacher info
    const existingSalary = await prisma.salary.findUnique({
      where: { id: salaryId },
      include: { teacher: true },
    });

    if (!existingSalary) {
      return res.status(404).json({ message: "Salary not found" });
    }

    // Validate teacher if provided
    let teacher = existingSalary.teacher;
    if (teacherId && teacherId !== existingSalary.teacherId) {
      teacher = await prisma.user.findUnique({
        where: { id: parseInt(teacherId) },
      });
      if (!teacher || teacher.role !== "teacher") {
        return res.status(400).json({ message: "Invalid teacher ID" });
      }
    }

    // Validate amount
    let numericAmount =
      amount !== undefined ? parseInt(amount) : existingSalary.amount;
    if (isNaN(numericAmount) || numericAmount < 0) {
      return res.status(400).json({ message: "Invalid amount" });
    }

    // Validate status
    const allowedStatuses = ["pending", "paid", "failed"];
    const newStatus = status ? status.toLowerCase() : existingSalary.status;
    if (!allowedStatuses.includes(newStatus)) {
      return res.status(400).json({ message: "Invalid status value" });
    }

    const statusChanged =
      status && status.toLowerCase() !== existingSalary.status;
    const amountChanged =
      amount !== undefined && numericAmount !== existingSalary.amount;
    const monthChanged = month && month !== existingSalary.month;

    // Update salary
    const updatedSalary = await prisma.salary.update({
      where: { id: salaryId },
      data: {
        teacherId: teacher.id,
        amount: numericAmount,
        month: month || existingSalary.month,
        status: newStatus,
        description:
          description !== undefined ? description : existingSalary.description,
      },
    });

    // Send email immediately
    if (teacher.email) {
      const transporter = nodemailer.createTransport({
        host: process.env.SMTP_HOST,
        port: parseInt(process.env.SMTP_PORT),
        secure: Number(process.env.SMTP_PORT) === 465,
        auth: {
          user: process.env.SMTP_USER,
          pass: process.env.SMTP_PASS,
        },
      });

      const mailOptions = {
        from: `"Virtual Education Hub" <${process.env.SMTP_USER}>`,
        to: teacher.email,
        subject: `Your Salary for ${updatedSalary.month} has been updated`,
        html: `
        <div style="font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color:#f9f9f9; padding:30px;">
          <div style="max-width:600px; margin:auto; background-color:#fff; border-radius:8px; overflow:hidden; box-shadow:0 4px 20px rgba(0,0,0,0.1);">
            <div style="background:linear-gradient(90deg, #4e54c8, #8f94fb); color:#fff; padding:20px; text-align:center;">
              <h2 style="margin:0;">Salary Updated</h2>
              <p style="margin:5px 0 0;">Hi ${
                teacher.firstName
              }, your salary details have been updated!</p>
            </div>
            <div style="padding:30px;">
              <p>A salary record has been updated for you:</p>
              <table style="width:100%; border-collapse:collapse; margin-top:15px;">
                <tr>
                  <td style="padding:10px; border:1px solid #ddd;"><strong>Month</strong></td>
                  <td style="padding:10px; border:1px solid #ddd;">${
                    updatedSalary.month
                  }</td>
                </tr>
                <tr>
                  <td style="padding:10px; border:1px solid #ddd;"><strong>Amount</strong></td>
                  <td style="padding:10px; border:1px solid #ddd;">NPR ${updatedSalary.amount.toLocaleString()}</td>
                </tr>
                <tr>
                  <td style="padding:10px; border:1px solid #ddd;"><strong>Status</strong></td>
                  <td style="padding:10px; border:1px solid #ddd; color:${
                    newStatus === "paid"
                      ? "green"
                      : newStatus === "failed"
                      ? "red"
                      : "orange"
                  };"><strong>${
          newStatus.charAt(0).toUpperCase() + newStatus.slice(1)
        }</strong></td>
                </tr>
                ${
                  updatedSalary.description
                    ? `<tr>
                        <td style="padding:10px; border:1px solid #ddd;"><strong>Description</strong></td>
                        <td style="padding:10px; border:1px solid #ddd;">${updatedSalary.description}</td>
                      </tr>`
                    : ""
                }
              </table>
              <p style="margin-top:20px;">You can log in to your account to view more details or download your salary slip.</p>
              <a href="${
                process.env.FRONTEND_URL
              }/login" style="display:inline-block; padding:12px 25px; background-color:#4e54c8; color:#fff; border-radius:5px; text-decoration:none; margin-top:10px;">View Salary</a>
            </div>
            <div style="background-color:#f1f1f1; padding:15px; text-align:center; font-size:12px; color:#555;">
              &copy; ${new Date().getFullYear()} Virtual Education Hub. All rights reserved.
            </div>
          </div>
        </div>
        `,
      };
      await transporter.sendMail(mailOptions);
    }

    let message;

    if (newStatus === "paid") {
      message = `🎉 Your salary for ${
        updatedSalary.month
      } has been successfully processed and marked as PAID.
Amount: NPR ${updatedSalary.amount.toLocaleString()}.`;
    }

    if (newStatus === "failed") {
      message = `⚠️ We’re sorry—your salary payment for ${
        updatedSalary.month
      } could not be processed at this time.
Amount: NPR ${updatedSalary.amount.toLocaleString()}.`;
    }

    await notifyUser(req, teacher.id, message, null);

    return res.json({
      message: "Salary updated successfully and email sent",
      updatedSalary,
    });
  } catch (err) {
    console.error(err);
    return res.status(500).json({ message: "Server error" });
  }
};

exports.getTeacherSalary = async (req, res) => {
  try {
    const { id } = req.params;

    const salary = await prisma.salary.findUnique({
      where: { id: parseInt(id) },
      include: { teacher: true }, // Include teacher info
    });

    if (!salary) return res.status(404).json({ message: "Salary not found" });

    // Return structured data
    return res.json({
      id: salary.id,
      teacherId: salary.teacherId,
      teacherName: salary.teacher?.firstName + " " + salary.teacher?.lastName,
      amount: salary.amount,
      month: salary.month,
      status: salary.status,
      description: salary.description,
      createdAt: salary.createdAt,
      updatedAt: salary.updatedAt,
    });
  } catch (err) {
    console.error(err);
    return res.status(500).json({ message: "Server error" });
  }
};

// Teacher own salary history
exports.getMySalary = async (req, res) => {
  try {
    const page = parseInt(req.query.page) || 1;
    const pageSize = parseInt(req.query.pageSize) || 5;
    const skip = (page - 1) * pageSize;

    const [salaries, total] = await Promise.all([
      prisma.salary.findMany({
        where: { teacherId: req.user.id },
        orderBy: { createdAt: "desc" },
        skip,
        take: pageSize,
      }),
      prisma.salary.count({
        where: { teacherId: req.user.id },
      }),
    ]);

    return res.json({
      data: salaries,
      total,
      page,
      pageSize,
    });
  } catch (err) {
    console.error(err);
    return res.status(500).json({ message: "Server error" });
  }
};

// Admin: get all salaries with pagination, sorting, filtering
exports.getAllSalaries = async (req, res) => {
  try {
    let { page = 0, pageSize = 10, sort = "[]", filter = "{}" } = req.query;

    page = parseInt(page);
    pageSize = parseInt(pageSize);
    filter = JSON.parse(filter);
    sort = JSON.parse(sort);

    // Build where clause
    const AND = [];

    if (filter.items && filter.items.length > 0) {
      filter.items.forEach((f) => {
        const column = f.columnField ?? f.field; // handle both names
        if (!f.value) return;

        switch (column) {
          case "teacherName":
            AND.push({
              OR: [
                {
                  teacher: {
                    firstName: { contains: f.value, mode: "insensitive" },
                  },
                },
                {
                  teacher: {
                    lastName: { contains: f.value, mode: "insensitive" },
                  },
                },
              ],
            });
            break;

          case "month":
            AND.push({ month: { contains: f.value, mode: "insensitive" } });
            break;

          case "status":
            AND.push({ status: { contains: f.value, mode: "insensitive" } });
            break;

          case "amount":
            const num = Number(f.value);
            if (!isNaN(num)) AND.push({ amount: num });
            break;

          default:
            break;
        }
      });
    }

    const whereClause = AND.length > 0 ? { AND } : {};

    // Build orderBy
    let orderByClause = {};
    if (sort.length > 0) {
      const s = sort[0];
      if (s.field === "teacherName") {
        // sort by firstName then lastName
        orderByClause = [
          { teacher: { firstName: s.sort } },
          { teacher: { lastName: s.sort } },
        ];
      } else {
        orderByClause[s.field] = s.sort;
      }
    } else {
      orderByClause = { createdAt: "desc" };
    }

    // Fetch rows with teacher relation
    const [rows, total] = await Promise.all([
      prisma.salary.findMany({
        skip: page * pageSize,
        take: pageSize,
        where: whereClause,
        orderBy: orderByClause,
        include: {
          teacher: {
            select: {
              firstName: true,
              lastName: true,
            },
          },
        },
      }),
      prisma.salary.count({ where: whereClause }),
    ]);

    // Format rows for DataGrid
    const formattedRows = rows.map((r, index) => ({
      id: r.id,
      sno: page * pageSize + index + 1,
      teacherName: `${r.teacher.firstName} ${r.teacher.lastName}`,
      amount: r.amount,
      month: r.month,
      status: r.status,
    }));

    return res.json({ rows: formattedRows, total });
  } catch (err) {
    console.error(err);
    return res.status(500).json({ message: "Server error" });
  }
};
