const fs = require("fs");
const path = require("path");
const { exec } = require("child_process");
const { MAILSERVER_CONTAINER, CONFIG_PATH, ROOT_PATH } = process.env;
const { models } = require(path.join(ROOT_PATH, "./db/db"));
const { Mailbox, Domain } = models;

async function generateMailserverConfig() {
  try {
    const mailboxes = await Mailbox.query().select("username", "password");
    const accountLines = mailboxes.map(
      (mailbox) => `${mailbox.username}|${mailbox.password}`
    );
    fs.writeFileSync(
      path.join(CONFIG_PATH, "postfix/postfix-accounts.cf"),
      accountLines.join("\n")
    );

    const domains = await Domain.query().select("domain");
    fs.writeFileSync(
      path.join(CONFIG_PATH, "postfix/postfix-virtual-mailbox-domains.cf"),
      domains.map((d) => d.domain).join("\n")
    );

    await reloadMailserver();

    return true;
  } catch (error) {
    console.error("Error generating mailserver config:", error);
    return false;
  }
}

async function reloadMailserver() {
  return new Promise((resolve, reject) => {
    exec(
      `docker exec ${MAILSERVER_CONTAINER} postfix reload`,
      (error, stdout, stderr) => {
        if (error) {
          console.error(`Error reloading Postfix: ${error.message}`);
          return reject(error);
        }
        console.log("Postfix configuration reloaded successfully");
        resolve(true);
      }
    );
  });
}

async function hashPassword(password) {
  // This is a simple bcrypt hash, for dovecot you might need a different format
  // The docker-mailserver typically uses SHA512-CRYPT
  return new Promise((resolve, reject) => {
    exec(
      `docker exec ${MAILSERVER_CONTAINER} doveadm pw -s SHA512-CRYPT -p "${password}"`,
      (error, stdout, stderr) => {
        if (error) {
          console.error(`Error generating password hash: ${error.message}`);
          return reject(error);
        }
        resolve(stdout.trim());
      }
    );
  });
}

async function cleanupOrphanedMailboxes() {
  try {
    // Get all valid mailboxes from database
    const validMailboxes = await Mailbox.query().select("username");

    // Create a lookup map for quick checking
    const validMailboxMap = {};
    validMailboxes.forEach((username) => {
      const [user, domain] = username.split("@");
      if (!validMailboxMap[domain]) validMailboxMap[domain] = [];
      validMailboxMap[domain].push(user);
    });

    // Scan mail directory
    const mailPath = "/var/mail";
    const domains = await fs.readdir(mailPath);

    for (const domain of domains) {
      const domainPath = path.join(mailPath, domain);
      const stat = await fs.stat(domainPath);

      if (stat.isDirectory()) {
        const users = await fs.readdir(domainPath);

        for (const user of users) {
          const userPath = path.join(domainPath, user);
          const userStat = await fs.stat(userPath);

          if (userStat.isDirectory()) {
            // Check if this is an orphaned mailbox
            const isValid =
              validMailboxMap[domain] && validMailboxMap[domain].includes(user);

            if (!isValid) {
              console.log(`Removing orphaned mailbox: ${user}@${domain}`);
              await fs.rm(userPath, { recursive: true, force: true });
            }
          }
        }
      }
    }

    console.log("Mailbox cleanup completed");
  } catch (error) {
    console.error("Error during mailbox cleanup:", error);
  }
}

module.exports = {
  generateMailserverConfig,
  reloadMailserver,
  hashPassword,
  cleanupOrphanedMailboxes,
};
