import { createClient } from "@supabase/supabase-js";
import { DateTime } from "luxon";
import slugify from "slugify";

const sanitizeMediaString = (str) => {
  const sanitizedString = str
    .normalize("NFD")
    .replace(/[\u0300-\u036f\u2010\-\.\?\(\)\[\]\{\}]/g, "")
    .replace(/\.{3}/g, "");
  return slugify(sanitizedString, {
    replacement: "-",
    remove: /[#,&,+()$~%.'":*?<>{}]/g,
    lower: true,
  });
};

const sendEmail = async (subject, text, authHeader, maxRetries = 3) => {
  const emailData = new URLSearchParams({
    from: "coryd.dev <hi@admin.coryd.dev>",
    to: "hi@coryd.dev",
    subject: subject,
    text: text,
  }).toString();

  let attempt = 0;
  let success = false;

  while (attempt < maxRetries && !success) {
    attempt++;
    try {
      const response = await fetch("https://api.forwardemail.net/v1/emails", {
        method: "POST",
        headers: {
          "Content-Type": "application/x-www-form-urlencoded",
          Authorization: authHeader,
        },
        body: emailData,
      });

      if (!response.ok) {
        const responseText = await response.text();
        console.error(
          `Attempt ${attempt}: Email API response error:`,
          response.status,
          responseText
        );
        throw new Error(`Failed to send email: ${responseText}`);
      }

      console.log("Email sent successfully on attempt", attempt);
      success = true;
    } catch (error) {
      console.error(`Attempt ${attempt}: Error sending email:`, error.message);

      if (attempt < maxRetries) {
        console.log(
          `Retrying email send (attempt ${attempt + 1}/${maxRetries})...`
        );
      } else {
        console.error("All attempts to send email failed.");
      }
    }
  }

  return success;
};

export default {
  async fetch(request, env) {
    const supabaseUrl = env.SUPABASE_URL;
    const supabaseKey = env.SUPABASE_KEY;
    const FORWARDEMAIL_API_KEY = env.FORWARDEMAIL_API_KEY;
    const ACCOUNT_ID_PLEX = env.ACCOUNT_ID_PLEX;
    const supabase = createClient(supabaseUrl, supabaseKey);
    const authHeader = "Basic " + btoa(`${FORWARDEMAIL_API_KEY}:`);
    const url = new URL(request.url);
    const params = url.searchParams;
    const id = params.get("id");

    if (!id)
      return new Response(JSON.stringify({ status: "Bad request" }), {
        headers: { "Content-Type": "application/json" },
      });

    if (id !== ACCOUNT_ID_PLEX)
      return new Response(JSON.stringify({ status: "Forbidden" }), {
        headers: { "Content-Type": "application/json" },
      });

    const contentType = request.headers.get("Content-Type") || "";
    if (!contentType.includes("multipart/form-data"))
      return new Response(
        JSON.stringify({
          status: "Bad request",
          message: "Invalid Content-Type. Expected multipart/form-data.",
        }),
        { headers: { "Content-Type": "application/json" } }
      );

    try {
      const data = await request.formData();
      const payload = JSON.parse(data.get("payload"));

      if (payload?.event === "media.scrobble") {
        const artistName = payload["Metadata"]["grandparentTitle"];
        const albumName = payload["Metadata"]["parentTitle"];
        const trackName = payload["Metadata"]["title"];
        const listenedAt = Math.floor(DateTime.now().toSeconds());
        const artistKey = sanitizeMediaString(artistName);
        const albumKey = `${artistKey}-${sanitizeMediaString(albumName)}`;

        let { data: artistData, error: artistError } = await supabase
          .from("artists")
          .select("*")
          .ilike("name_string", artistName)
          .single();

        if (artistError && artistError.code === "PGRST116") {
          const { error: insertArtistError } = await supabase
            .from("artists")
            .insert([
              {
                mbid: null,
                art: "4cef75db-831f-4f5d-9333-79eaa5bb55ee",
                name: artistName,
                slug: "/music",
                tentative: true,
                total_plays: 0,
              },
            ]);

          if (insertArtistError) {
            console.error(
              "Error inserting artist: ",
              insertArtistError.message
            );
            return new Response(
              JSON.stringify({
                status: "error",
                message: insertArtistError.message,
              }),
              { headers: { "Content-Type": "application/json" } }
            );
          }

          await sendEmail(
            "New tentative artist record",
            `A new tentative artist record was inserted:\n\nArtist: ${artistName}\nKey: ${artistKey}`,
            authHeader
          );
          ({ data: artistData, error: artistError } = await supabase
            .from("artists")
            .select("*")
            .ilike("name_string", artistName)
            .single());
        }

        if (artistError) {
          console.error("Error fetching artist:", artistError.message);
          return new Response(
            JSON.stringify({ status: "error", message: artistError.message }),
            { headers: { "Content-Type": "application/json" } }
          );
        }

        let { data: albumData, error: albumError } = await supabase
          .from("albums")
          .select("*")
          .ilike("key", albumKey)
          .single();

        if (albumError && albumError.code === "PGRST116") {
          const { error: insertAlbumError } = await supabase
            .from("albums")
            .insert([
              {
                mbid: null,
                art: "4cef75db-831f-4f5d-9333-79eaa5bb55ee",
                key: albumKey,
                name: albumName,
                tentative: true,
                total_plays: 0,
                artist: artistData.id,
              },
            ]);

          if (insertAlbumError) {
            console.error("Error inserting album:", insertAlbumError.message);
            return new Response(
              JSON.stringify({
                status: "error",
                message: insertAlbumError.message,
              }),
              { headers: { "Content-Type": "application/json" } }
            );
          }

          await sendEmail(
            "New tentative album record",
            `A new tentative album record was inserted:\n\nAlbum: ${albumName}\nKey: ${albumKey}\nArtist: ${artistName}`,
            authHeader
          );
          ({ data: albumData, error: albumError } = await supabase
            .from("albums")
            .select("*")
            .ilike("key", albumKey)
            .single());
        }

        if (albumError) {
          console.error("Error fetching album:", albumError.message);
          return new Response(
            JSON.stringify({ status: "error", message: albumError.message }),
            { headers: { "Content-Type": "application/json" } }
          );
        }

        const { error: listenError } = await supabase.from("listens").insert([
          {
            artist_name: artistData["name_string"] || artistName,
            album_name: albumData["name"] || albumName,
            track_name: trackName,
            listened_at: listenedAt,
            album_key: albumKey,
          },
        ]);

        if (listenError) {
          console.error("Error inserting listen:", listenError.message);
          return new Response(
            JSON.stringify({ status: "error", message: listenError.message }),
            { headers: { "Content-Type": "application/json" } }
          );
        }

        console.log("Listen record inserted successfully");
      }

      return new Response(JSON.stringify({ status: "success" }), {
        headers: { "Content-Type": "application/json" },
      });
    } catch (e) {
      console.error("Error processing request:", e.message);
      return new Response(
        JSON.stringify({ status: "error", message: e.message }),
        { headers: { "Content-Type": "application/json" } }
      );
    }
  },
};