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

// -------- Overview / lists --------

export const getAdminOverview = createServerFn({ method: "GET" })
  .middleware([requireSupabaseAuth])
  .handler(async ({ context }) => {
    const { supabase, userId } = context;
    let { data: roles } = await supabase
      .from("user_roles")
      .select("role")
      .eq("user_id", userId);
    let roleList = (roles ?? []).map((r: any) => r.role);
    let isStaff = roleList.some((r: string) =>
      ["super_admin", "admin", "operator"].includes(r),
    );

    // Bootstrap: if no super_admin exists yet in the whole system, promote the
    // first signed-in user to super_admin so the console is never locked out.
    if (!isStaff) {
      const { supabaseAdmin } = await import("@/integrations/supabase/client.server");
      const { count } = await supabaseAdmin
        .from("user_roles")
        .select("*", { count: "exact", head: true })
        .eq("role", "super_admin");
      if ((count ?? 0) === 0) {
        await supabaseAdmin
          .from("user_roles")
          .insert({ user_id: userId, role: "super_admin" });
        roleList = [...roleList, "super_admin"];
        isStaff = true;
      }
    }

    if (!isStaff) {
      return { isStaff: false as const, roles: roleList };
    }

    const { supabaseAdmin } = await import("@/integrations/supabase/client.server");
    const [plans, subs, payments, routers] = await Promise.all([
      supabaseAdmin.from("plans").select("*").order("sort_order", { ascending: true }),
      supabaseAdmin
        .from("subscriptions")
        .select("id,phone,mac_address,status,starts_at,expires_at,created_at,plan:plan_id(name,price_kes)")
        .order("created_at", { ascending: false })
        .limit(50),
      supabaseAdmin
        .from("payments")
        .select("id,phone,amount_kes,status,mpesa_receipt,created_at,paid_at,subscription_id")
        .order("created_at", { ascending: false })
        .limit(50),
      supabaseAdmin.from("routers").select("*").order("created_at", { ascending: false }),
    ]);

    const now = new Date().toISOString();
    const activeSubsCount = (subs.data ?? []).filter(
      (s: any) => s.status === "active" && s.expires_at && s.expires_at > now,
    ).length;
    const successPayments = (payments.data ?? []).filter((p: any) => p.status === "success");
    const totalRevenue = successPayments.reduce(
      (sum: number, p: any) => sum + Number(p.amount_kes ?? 0),
      0,
    );

    return {
      isStaff: true,
      roles: roleList,
      plans: plans.data ?? [],
      subscriptions: subs.data ?? [],
      payments: payments.data ?? [],
      routers: routers.data ?? [],
      stats: {
        activeSubsCount,
        totalRevenue,
        paymentsCount: (payments.data ?? []).length,
        successCount: successPayments.length,
      },
    };
  });

// -------- Plans CRUD --------

const planInput = z.object({
  id: z.string().uuid().optional(),
  name: z.string().min(1),
  price_kes: z.number().int().nonnegative(),
  duration_minutes: z.number().int().positive(),
  download_kbps: z.number().int().nonnegative().optional(),
  upload_kbps: z.number().int().nonnegative().optional(),
  device_limit: z.number().int().positive().optional(),
  description: z.string().optional(),
  sort_order: z.number().int().optional(),
  is_active: z.boolean().optional(),
});

async function assertStaff(supabase: any, userId: string) {
  const { data } = await supabase.rpc("is_staff", { _user_id: userId });
  if (!data) throw new Error("Forbidden");
}

export const upsertPlan = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((d: unknown) => planInput.parse(d))
  .handler(async ({ data, context }) => {
    await assertStaff(context.supabase, context.userId);
    const { supabaseAdmin } = await import("@/integrations/supabase/client.server");
    const row = { ...data };
    if (row.id) {
      const { error } = await supabaseAdmin.from("plans").update(row).eq("id", row.id);
      if (error) return { ok: false, error: error.message };
    } else {
      const { error } = await supabaseAdmin.from("plans").insert(row);
      if (error) return { ok: false, error: error.message };
    }
    return { ok: true };
  });

export const deletePlan = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((d: unknown) => z.object({ id: z.string().uuid() }).parse(d))
  .handler(async ({ data, context }) => {
    await assertStaff(context.supabase, context.userId);
    const { supabaseAdmin } = await import("@/integrations/supabase/client.server");
    const { error } = await supabaseAdmin.from("plans").delete().eq("id", data.id);
    if (error) return { ok: false, error: error.message };
    return { ok: true };
  });

// -------- Routers CRUD --------

const routerInput = z.object({
  id: z.string().uuid().optional(),
  name: z.string().min(1),
  location: z.string().nullable().optional(),
  agent_secret: z.string().min(8).optional(),
});

function randomSecret(len = 32) {
  const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
  let out = "";
  for (let i = 0; i < len; i++) out += chars[Math.floor(Math.random() * chars.length)];
  return out;
}

export const upsertRouter = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((d: unknown) => routerInput.parse(d))
  .handler(async ({ data, context }) => {
    await assertStaff(context.supabase, context.userId);
    const { supabaseAdmin } = await import("@/integrations/supabase/client.server");
    if (data.id) {
      const { error } = await supabaseAdmin
        .from("routers")
        .update({ name: data.name, location: data.location ?? null })
        .eq("id", data.id);
      if (error) return { ok: false, error: error.message };
      return { ok: true };
    }
    const secret = data.agent_secret || randomSecret(40);
    const identifier = `${data.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, 40)}-${randomSecret(6).toLowerCase()}`;
    const { data: row, error } = await supabaseAdmin
      .from("routers")
      .insert({
        name: data.name,
        location: data.location ?? null,
        agent_secret: secret,
        identifier,
        owner_id: context.userId,
      })
      .select("id")
      .single();
    if (error || !row) return { ok: false, error: error?.message ?? "Failed" };
    return { ok: true, id: row.id, agent_secret: secret };
  });

export const deleteRouter = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((d: unknown) => z.object({ id: z.string().uuid() }).parse(d))
  .handler(async ({ data, context }) => {
    await assertStaff(context.supabase, context.userId);
    const { supabaseAdmin } = await import("@/integrations/supabase/client.server");
    const { error } = await supabaseAdmin.from("routers").delete().eq("id", data.id);
    if (error) return { ok: false, error: error.message };
    return { ok: true };
  });

export const rotateRouterSecret = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((d: unknown) => z.object({ id: z.string().uuid() }).parse(d))
  .handler(async ({ data, context }) => {
    await assertStaff(context.supabase, context.userId);
    const { supabaseAdmin } = await import("@/integrations/supabase/client.server");
    const secret = randomSecret(40);
    const { error } = await supabaseAdmin
      .from("routers")
      .update({ agent_secret: secret })
      .eq("id", data.id);
    if (error) return { ok: false, error: error.message };
    return { ok: true, agent_secret: secret };
  });

// -------- Manual payment reconciliation --------

export const markPaymentPaid = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((d: unknown) => z.object({ payment_id: z.string().uuid() }).parse(d))
  .handler(async ({ data, context }) => {
    await assertStaff(context.supabase, context.userId);
    const { supabaseAdmin } = await import("@/integrations/supabase/client.server");
    await supabaseAdmin
      .from("payments")
      .update({ status: "success" })
      .eq("id", data.payment_id);
    const { activateSubscriptionForPayment } = await import("@/lib/subscription.server");
    const res = await activateSubscriptionForPayment(supabaseAdmin, data.payment_id);
    return res.ok ? { ok: true } : { ok: false, error: res.error };
  });

// -------- Promote user --------

export const promoteUser = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((d: unknown) =>
    z.object({
      email: z.string().email(),
      role: z.enum(["admin", "operator", "customer"]),
    }).parse(d),
  )
  .handler(async ({ data, context }) => {
    // Only super_admin can promote
    const { data: isSuper } = await context.supabase.rpc("has_role", {
      _user_id: context.userId,
      _role: "super_admin",
    });
    if (!isSuper) return { ok: false, error: "Only super_admin can promote users" };

    const { supabaseAdmin } = await import("@/integrations/supabase/client.server");
    // Find user by email
    const { data: list } = await supabaseAdmin.auth.admin.listUsers({ perPage: 1000 });
    const user = list.users.find((u) => u.email?.toLowerCase() === data.email.toLowerCase());
    if (!user) return { ok: false, error: "User not found" };
    // remove other elevated roles then add
    await supabaseAdmin
      .from("user_roles")
      .delete()
      .eq("user_id", user.id)
      .in("role", ["admin", "operator", "customer"]);
    const { error } = await supabaseAdmin
      .from("user_roles")
      .insert({ user_id: user.id, role: data.role });
    if (error) return { ok: false, error: error.message };
    return { ok: true };
  });
