import type { FastifyPluginAsync } from "fastify";
import { z } from "zod";
import { requireAuth, requireRestaurantMember } from "../lib/auth.js";
import { extractMenuFromImage } from "../lib/ai-scanner.js";
import { supabase } from "../lib/supabase.js";
import type { AiExtractedCategory, AiImportResponse } from "@menulio/shared";

const importAiSchema = z.object({
  image: z.string().min(1, "Görsel verisi zorunludur"),
});

const applyAiImportSchema = z.object({
  menuId: z.string().uuid(),
  categories: z.array(
    z.object({
      name: z.string().min(1),
      items: z.array(
        z.object({
          name: z.string().min(1),
          description: z.string().nullable().optional(),
          price: z.number().min(0),
        }),
      ),
    }),
  ),
});

export const aiImportsRoutes: FastifyPluginAsync = async (app) => {
  /**
   * POST /menus/:id/import-ai
   * Runs the AI Menu Scanner pipeline on an uploaded menu photo
   */
  app.post("/menus/:id/import-ai", async (req, reply) => {
    const userId = await requireAuth(req, reply);
    if (!userId || !supabase) return;

    const { id: menuId } = req.params as { id: string };

    // Resolve restaurant from menu
    const { data: menuRow, error: menuError } = await supabase
      .from("menus")
      .select("id, location_id, locations!inner(restaurant_id)")
      .eq("id", menuId)
      .single();

    if (menuError || !menuRow) {
      return reply.code(404).send({ message: "Menü bulunamadı" });
    }

    const restaurantId = (menuRow.locations as unknown as { restaurant_id: string }).restaurant_id;
    const isMember = await requireRestaurantMember(userId, restaurantId);
    if (!isMember) return reply.code(403).send({ message: "Bu menü için yetkiniz yok" });

    const parsed = importAiSchema.safeParse(req.body);
    if (!parsed.success) {
      return reply.code(400).send({ message: "Geçersiz istek", issues: parsed.error.issues });
    }

    const { image } = parsed.data;

    // 1. Create audit record in ai_imports
    const { data: importRecord, error: insertError } = await supabase
      .from("ai_imports")
      .insert({
        restaurant_id: restaurantId,
        source_image: image.length > 200 ? `${image.slice(0, 100)}...[base64_data]` : image,
        status: "processing",
      })
      .select()
      .single();

    if (insertError || !importRecord) {
      req.log.error(insertError);
      return reply.code(500).send({ message: "AI import kaydı oluşturulamadı" });
    }

    try {
      // 2. Run AI extraction engine
      const extraction = await extractMenuFromImage(image);

      // 3. Save extracted items to ai_import_items
      const itemsToInsert: {
        ai_import_id: string;
        category_name: string;
        item_name: string;
        description: string | null;
        price: number;
      }[] = [];

      for (const cat of extraction.categories) {
        for (const item of cat.items) {
          itemsToInsert.push({
            ai_import_id: importRecord.id,
            category_name: cat.name,
            item_name: item.name,
            description: item.description ?? null,
            price: item.price,
          });
        }
      }

      if (itemsToInsert.length > 0) {
        await supabase.from("ai_import_items").insert(itemsToInsert);
      }

      // 4. Update import status to completed
      await supabase
        .from("ai_imports")
        .update({
          status: "completed",
          model: extraction.model,
          raw_response: extraction.rawResponse as Record<string, unknown>,
          processed_at: new Date().toISOString(),
        })
        .eq("id", importRecord.id);

      let totalItems = 0;
      for (const cat of extraction.categories) {
        totalItems += cat.items.length;
      }

      const response: AiImportResponse = {
        importId: importRecord.id,
        status: "completed",
        model: extraction.model,
        categories: extraction.categories,
        totalItems,
      };

      return reply.code(200).send(response);
    } catch (err) {
      req.log.error(err);
      await supabase
        .from("ai_imports")
        .update({
          status: "failed",
          error: err instanceof Error ? err.message : "AI analizi sırasında hata oluştu",
        })
        .eq("id", importRecord.id);

      return reply.code(500).send({
        message: "Menü fotoğrafı analiz edilirken bir hata oluştu",
        error: err instanceof Error ? err.message : String(err),
      });
    }
  });

  /**
   * GET /ai-imports/:id
   * Fetch an existing AI import and its extracted items
   */
  app.get("/ai-imports/:id", async (req, reply) => {
    const userId = await requireAuth(req, reply);
    if (!userId || !supabase) return;

    const { id } = req.params as { id: string };

    const { data: importRecord, error: importError } = await supabase
      .from("ai_imports")
      .select("*")
      .eq("id", id)
      .single();

    if (importError || !importRecord) {
      return reply.code(404).send({ message: "Import kaydı bulunamadı" });
    }

    const isMember = await requireRestaurantMember(userId, importRecord.restaurant_id);
    if (!isMember) return reply.code(403).send({ message: "Yetkiniz yok" });

    const { data: rawItems } = await supabase
      .from("ai_import_items")
      .select("*")
      .eq("ai_import_id", id);

    // Group items into categories
    const categoryMap = new Map<string, AiExtractedCategory>();
    let totalItems = 0;

    for (const item of rawItems ?? []) {
      totalItems++;

      const catName = item.category_name || "Genel";
      if (!categoryMap.has(catName)) {
        categoryMap.set(catName, {
          id: `cat-${categoryMap.size + 1}`,
          name: catName,
          items: [],
        });
      }

      categoryMap.get(catName)!.items.push({
        id: item.id,
        name: item.item_name,
        description: item.description,
        price: Number(item.price ?? 0),
      });
    }

    const response: AiImportResponse = {
      importId: importRecord.id,
      status: importRecord.status,
      model: importRecord.model,
      categories: Array.from(categoryMap.values()),
      totalItems,
    };

    return reply.send(response);
  });

  /**
   * POST /ai-imports/:id/apply
   * Applies approved/edited AI extracted categories & items directly into the restaurant's menu
   */
  app.post("/ai-imports/:id/apply", async (req, reply) => {
    const userId = await requireAuth(req, reply);
    if (!userId || !supabase) return;

    const { id } = req.params as { id: string };

    const parsed = applyAiImportSchema.safeParse(req.body);
    if (!parsed.success) {
      return reply.code(400).send({ message: "Geçersiz veri", issues: parsed.error.issues });
    }

    const { menuId, categories } = parsed.data;

    // Verify restaurant membership
    const { data: menuRow } = await supabase
      .from("menus")
      .select("locations!inner(restaurant_id)")
      .eq("id", menuId)
      .single();

    if (!menuRow) return reply.code(404).send({ message: "Menü bulunamadı" });
    const restaurantId = (menuRow.locations as unknown as { restaurant_id: string }).restaurant_id;

    const isMember = await requireRestaurantMember(userId, restaurantId);
    if (!isMember) return reply.code(403).send({ message: "Yetkiniz yok" });

    // Fetch existing category sort orders
    const { data: existingCategories } = await supabase
      .from("menu_categories")
      .select("id, name, sort_order")
      .eq("menu_id", menuId)
      .order("sort_order", { ascending: false });

    let currentSortOrder = (existingCategories?.[0]?.sort_order ?? -1) + 1;
    let totalCategoriesInserted = 0;
    let totalItemsInserted = 0;

    for (const cat of categories) {
      // Find or create category
      let categoryId: string;
      const existing = existingCategories?.find((c) => c.name.toLowerCase() === cat.name.toLowerCase());

      if (existing) {
        categoryId = existing.id;
      } else {
        const { data: newCat, error: catError } = await supabase
          .from("menu_categories")
          .insert({
            menu_id: menuId,
            name: cat.name,
            sort_order: currentSortOrder++,
          })
          .select()
          .single();

        if (catError || !newCat) {
          req.log.error(catError);
          continue;
        }
        categoryId = newCat.id;
        totalCategoriesInserted++;
      }

      // Insert items under category
      const itemsToInsert = cat.items.map((itm, idx) => ({
        category_id: categoryId,
        name: itm.name,
        description: itm.description || null,
        price: itm.price,
        sort_order: idx,
      }));

      if (itemsToInsert.length > 0) {
        const { error: itemsError } = await supabase.from("menu_items").insert(itemsToInsert);
        if (!itemsError) {
          totalItemsInserted += itemsToInsert.length;
        } else {
          req.log.error(itemsError);
        }
      }
    }

    return reply.send({
      success: true,
      categoriesCount: totalCategoriesInserted,
      itemsCount: totalItemsInserted,
    });
  });
};
