import assert from "assert";
import logging from '../lib/logging.js';
import { Client, IntentsBitField, Partials, ChannelType } from "discord.js";
import { User } from "../lib/models.js";
import { company } from '../emails/config.js';
import { discord } from "../lib/config.js";
import { send_email, load_templates, debug_templates } from '../lib/email.js';

const log = logging.create("/queues/mail.js");

const client = new Client({
  intents: [
    IntentsBitField.Flags.GuildInvites,
  ],
  partials: [ Partials.GuildMember ],
});

const load_guild_channel = async (client) => {
  const guilds = await client.guilds.fetch();

  let temp = guilds.entries().next().value[1];
  assert(temp, "Can't find any guilds/servers.");

  const guild = await temp.fetch();
  assert(guild, "No guild after fetch.");

  const channels = await guild.channels.fetch();

  for(let chan of channels.entries()) {
    if(chan[1].type === ChannelType.GuildText) {
      log.info(`Found guild text channel ${JSON.stringify(chan[1])}`);
      return [guild, await chan[1].fetch()];
    }
  }

  // fallthrough, no text channels
  return [guild, undefined];
}

log.info("Connecting to discord server...");
await client.login(discord.token);

const [guild, channel] = await load_guild_channel(client);

// if it doesn't exist make it and add it to their account
log.info(`Connected to Sever/Guild ${guild.name}`);
log.info(`!!Sending invites from Channel ${JSON.stringify(channel, null, 4)}`);

const invite_email = await load_templates("discord_email");

export const send_invite = async (job) => {
  try {
    console.log("JOB!", job.data);
    assert(channel !== undefined, "Did not find one text channel.");
    assert(job.data.user_id !== undefined, "user_id is required");

    log.debug(`Discord invite request for ${job.data.user_id}`);

    const user = await User.first({id: job.data.user_id});
    assert(user, "didn't find user");

    // check the user's account to see if a code already exists
    if(user.discord_invite) {
      log.info(`Ignoring user ${ user.id } because they already have invite code ${ user.discord_invite } sent on ${ user.discord_sent }`);
    } else {
      const invite = await channel.createInvite(discord.invites);
      // update the user's account with their invite code and
      const text = invite_email.txt({ user, invite, company, discord });
      const html = invite_email.html({ user, invite, company, discord });

      await User.update({id: user.id}, { discord_invite: invite.code, discord_sent: new Date()});

      await debug_templates({ text, html }, "invite_email");

      // send both txt and html as attachments
      send_email({
        from: company.mail,
        to: user.email,
        subject: `Discord Invite for ${company.website}`,
        text, html
      });

      log.info(`INVITE code ${invite.code} sent to user ${user.id}`);
    }
  } catch (error) {
    log.error(error);
  }
}
