import { createServerFn } from "@tanstack/react-start";
import { z } from "zod";
import { requireSupabaseAuth } from "@/integrations/supabase/auth-middleware";

export interface MailAttachment {
  name: string;
  size: number;
  type: string;
  path: string;
}

export interface MailRow {
  id: string;
  folder: "inbox" | "sent";
  from_email: string;
  to_emails: string[];
  subject: string;
  body: string;
  attachments: MailAttachment[];
  read: boolean;
  starred: boolean;
  created_at: string;
}

const attachmentSchema = z.object({
  name: z.string().max(200),
  size: z.number().nonnegative(),
  type: z.string().max(120),
  path: z.string().max(400),
});

const sendSchema = z.object({
  to: z.string().trim().min(3).max(600),
  subject: z.string().trim().max(200).default(""),
  body: z.string().trim().max(20000).default(""),
  attachments: z.array(attachmentSchema).max(10).default([]),
});

export const listMail = createServerFn({ method: "GET" })
  .middleware([requireSupabaseAuth])
  .handler(async ({ context }) => {
    const { data, error } = await context.supabase
      .from("mail_messages")
      .select("*")
      .eq("user_id", context.userId)
      .order("created_at", { ascending: false })
      .limit(200);
    if (error) throw new Error(error.message);
    return {
      messages: (data ?? []) as unknown as MailRow[],
      email: (context.claims as { email?: string })?.email ?? "",
    };
  });

export const sendMail = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((input: unknown) => sendSchema.parse(input))
  .handler(async ({ data, context }) => {
    const recipients = data.to
      .split(/[,;\s]+/)
      .map((v) => v.trim().toLowerCase())
      .filter((v) => /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(v));
    if (!recipients.length) throw new Error("Add at least one valid recipient address.");

    const from = (context.claims as { email?: string })?.email ?? "unknown@gatavase.com";

    const { error } = await context.supabase.from("mail_messages").insert({
      user_id: context.userId,
      folder: "sent",
      from_email: from,
      to_emails: recipients,
      subject: data.subject,
      body: data.body,
      attachments: data.attachments,
      read: true,
    });
    if (error) throw new Error(error.message);

    // Deliver into the inbox of any recipient that already has a Gatavase account.
    let delivered = 0;
    try {
      const { supabaseAdmin } = await import("@/integrations/supabase/client.server");
      const { data: userList } = await supabaseAdmin.auth.admin.listUsers({
        page: 1,
        perPage: 1000,
      });
      const byEmail = new Map(
        (userList?.users ?? []).map((u) => [(u.email ?? "").toLowerCase(), u.id]),
      );
      const rows = recipients
        .map((email) => byEmail.get(email))
        .filter((id): id is string => Boolean(id) && id !== context.userId)
        .map((id) => ({
          user_id: id,
          folder: "inbox" as const,
          from_email: from,
          to_emails: recipients,
          subject: data.subject,
          body: data.body,
          attachments: data.attachments,
          read: false,
        }));
      if (rows.length) {
        await supabaseAdmin.from("mail_messages").insert(rows);
        delivered = rows.length;
      }
    } catch (err) {
      console.error("gatamail delivery failed", err);
    }

    return { ok: true as const, recipients: recipients.length, delivered };
  });

export const markMailRead = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((input: unknown) =>
    z.object({ id: z.string().uuid(), read: z.boolean().default(true) }).parse(input),
  )
  .handler(async ({ data, context }) => {
    await context.supabase
      .from("mail_messages")
      .update({ read: data.read })
      .eq("id", data.id)
      .eq("user_id", context.userId);
    return { ok: true as const };
  });

export const toggleMailStar = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((input: unknown) =>
    z.object({ id: z.string().uuid(), starred: z.boolean() }).parse(input),
  )
  .handler(async ({ data, context }) => {
    await context.supabase
      .from("mail_messages")
      .update({ starred: data.starred })
      .eq("id", data.id)
      .eq("user_id", context.userId);
    return { ok: true as const };
  });

export const deleteMail = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((input: unknown) => z.object({ id: z.string().uuid() }).parse(input))
  .handler(async ({ data, context }) => {
    await context.supabase
      .from("mail_messages")
      .delete()
      .eq("id", data.id)
      .eq("user_id", context.userId);
    return { ok: true as const };
  });

export const attachmentUrl = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((input: unknown) => z.object({ path: z.string().max(400) }).parse(input))
  .handler(async ({ data, context }) => {
    const { data: signed, error } = await context.supabase.storage
      .from("mail-attachments")
      .createSignedUrl(data.path, 300);
    if (error) throw new Error(error.message);
    return { url: signed?.signedUrl ?? "" };
  });
