import type { FastifyPluginAsync } from "fastify";
import { z } from "zod";
import { requireAuth } from "../lib/auth.js";
import { getCategoryIfMember, getMenuIfMember } from "../lib/access.js";
import { supabase } from "../lib/supabase.js";
import { translateMenu } from "../lib/translator.js";

// New categories/items are translated into whatever languages the
// restaurant already has enabled beyond Turkish (bulk-translated once when
// a language is first added — see routes/languages.ts).
async function translateNewCategoryInBackground(restaurantId: string, categoryId: string, name: string) {
  if (!supabase) return;
  const { data: restaurant } = await supabase
    .from("restaurants")
    .select("enabled_languages")
    .eq("id", restaurantId)
    .single();
  const extraLanguages = (restaurant?.enabled_languages ?? []).filter((l: string) => l !== "tr");
  if (extraLanguages.length === 0) return;

  const translations: Record<string, { name: string }> = {};
  for (const lang of extraLanguages) {
    try {
      const [translated] = await translateMenu([{ id: categoryId, name, items: [] }], lang);
      if (translated) translations[lang] = { name: translated.name };
    } catch (err) {
      console.warn(`Category translation to ${lang} failed:`, err);
    }
  }
  if (Object.keys(translations).length > 0) {
    await supabase.from("menu_categories").update({ translations }).eq("id", categoryId);
  }
}

const createCategorySchema = z.object({
  name: z.string().min(1).max(120),
  description: z.string().max(500).nullish(),
  sortOrder: z.number().int().default(0),
});

const updateCategorySchema = z.object({
  name: z.string().min(1).max(120).optional(),
  description: z.string().max(500).nullish(),
  sortOrder: z.number().int().optional(),
  isActive: z.boolean().optional(),
});

export const menuCategoriesRoutes: FastifyPluginAsync = async (app) => {
  app.post("/menus/:menuId/categories", async (req, reply) => {
    const userId = await requireAuth(req, reply);
    if (!userId || !supabase) return;

    const { menuId } = req.params as { menuId: string };
    const access = await getMenuIfMember(userId, menuId);
    if (!access) return reply.code(404).send({ message: "not found" });

    const parsed = createCategorySchema.safeParse(req.body);
    if (!parsed.success) {
      return reply.code(400).send({ message: "invalid body", issues: parsed.error.issues });
    }

    const { data, error } = await supabase
      .from("menu_categories")
      .insert({
        menu_id: menuId,
        name: parsed.data.name,
        description: parsed.data.description ?? null,
        sort_order: parsed.data.sortOrder,
      })
      .select()
      .single();

    if (error || !data) {
      req.log.error(error);
      return reply.code(500).send({ message: "failed to create category" });
    }

    void translateNewCategoryInBackground(access.restaurantId, data.id, data.name);

    return reply.code(201).send(data);
  });

  app.patch("/menu-categories/:id", async (req, reply) => {
    const userId = await requireAuth(req, reply);
    if (!userId || !supabase) return;

    const { id } = req.params as { id: string };
    const access = await getCategoryIfMember(userId, id);
    if (!access) return reply.code(404).send({ message: "not found" });

    const parsed = updateCategorySchema.safeParse(req.body);
    if (!parsed.success) {
      return reply.code(400).send({ message: "invalid body", issues: parsed.error.issues });
    }

    const { name, description, sortOrder, isActive } = parsed.data;
    const { data, error } = await supabase
      .from("menu_categories")
      .update({
        ...(name !== undefined ? { name } : {}),
        ...(description !== undefined ? { description } : {}),
        ...(sortOrder !== undefined ? { sort_order: sortOrder } : {}),
        ...(isActive !== undefined ? { is_active: isActive } : {}),
      })
      .eq("id", id)
      .select()
      .single();

    if (error || !data) {
      req.log.error(error);
      return reply.code(500).send({ message: "failed to update category" });
    }

    return reply.send(data);
  });

  app.delete("/menu-categories/:id", async (req, reply) => {
    const userId = await requireAuth(req, reply);
    if (!userId || !supabase) return;

    const { id } = req.params as { id: string };
    const access = await getCategoryIfMember(userId, id);
    if (!access) return reply.code(404).send({ message: "not found" });

    const { error } = await supabase.from("menu_categories").delete().eq("id", id);
    if (error) {
      req.log.error(error);
      return reply.code(500).send({ message: "failed to delete category" });
    }

    return reply.code(204).send();
  });
};
