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

async function translateNewItemInBackground(
  restaurantId: string,
  itemId: string,
  name: string,
  description: string | null,
) {
  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; description: string | null }> = {};
  for (const lang of extraLanguages) {
    try {
      const [translatedCat] = await translateMenu(
        [{ id: "single", name: "-", items: [{ id: itemId, name, description }] }],
        lang,
      );
      const translatedItem = translatedCat?.items[0];
      if (translatedItem) translations[lang] = { name: translatedItem.name, description: translatedItem.description };
    } catch (err) {
      console.warn(`Item translation to ${lang} failed:`, err);
    }
  }
  if (Object.keys(translations).length > 0) {
    await supabase.from("menu_items").update({ translations }).eq("id", itemId);
  }
}

const createItemSchema = z.object({
  name: z.string().min(1).max(160),
  description: z.string().max(1000).nullish(),
  price: z.number().nonnegative(),
  imageUrl: z.string().nullish(),
  sortOrder: z.number().int().default(0),
});

const updateItemSchema = z.object({
  name: z.string().min(1).max(160).optional(),
  description: z.string().max(1000).nullish(),
  price: z.number().nonnegative().optional(),
  imageUrl: z.string().nullish(),
  sortOrder: z.number().int().optional(),
  isActive: z.boolean().optional(),
});

export const menuItemsRoutes: FastifyPluginAsync = async (app) => {
  app.post("/menu-categories/:categoryId/items", async (req, reply) => {
    const userId = await requireAuth(req, reply);
    if (!userId || !supabase) return;

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

    const parsed = createItemSchema.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_items")
      .insert({
        category_id: categoryId,
        name: parsed.data.name,
        description: parsed.data.description ?? null,
        price: parsed.data.price,
        image_url: parsed.data.imageUrl ?? null,
        sort_order: parsed.data.sortOrder,
      })
      .select()
      .single();

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

    void translateNewItemInBackground(access.restaurantId, data.id, data.name, data.description);

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

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

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

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

    const { name, description, price, imageUrl, sortOrder, isActive } = parsed.data;
    const { data, error } = await supabase
      .from("menu_items")
      .update({
        ...(name !== undefined ? { name } : {}),
        ...(description !== undefined ? { description } : {}),
        ...(price !== undefined ? { price } : {}),
        ...(imageUrl !== undefined ? { image_url: imageUrl } : {}),
        ...(sortOrder !== undefined ? { sort_order: sortOrder } : {}),
        ...(isActive !== undefined ? { is_active: isActive } : {}),
        updated_at: new Date().toISOString(),
      })
      .eq("id", id)
      .select()
      .single();

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

    return reply.send(data);
  });

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

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

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

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