import { createServerFn } from "@tanstack/react-start";
import { z } from "zod";
import { SignJWT, jwtVerify } from "jose";
import { supabaseAdmin } from "@/integrations/supabase/client.server";
import { requireSupabaseAuth } from "@/integrations/supabase/auth-middleware";

// Portal token (same scheme as customer-portal.functions.ts)
const tokenSecret = () => new TextEncoder().encode(process.env.SUPABASE_SERVICE_ROLE_KEY!);
async function verifyToken(token: string): Promise<string> {
  try {
    const { payload } = await jwtVerify(token, tokenSecret());
    if (payload.kind !== "portal" || typeof payload.cid !== "string") throw new Error("Invalid token");
    return payload.cid;
  } catch (error: any) {
    const message = String(error?.message || "");
    if (/jwtexpired|exp.*claim|token.*expired/i.test(message)) {
      throw new Error("Portal session expired");
    }
    throw new Error("Invalid portal session");
  }
}
async function assertAdmin(supabase: any, userId: string) {
  const { data } = await supabase.from("user_roles").select("role").eq("user_id", userId).in("role", ["admin", "staff"]).maybeSingle();
  if (!data) throw new Error("Admin only");
}

const itemInput = z.object({
  product_id: z.string().uuid(),
  quantity: z.number().positive().max(1000000),
});

// ===== Portal: safe product list (NO cost/profit data) =====
export const portalListProducts = createServerFn({ method: "POST" })
  .inputValidator((d) => z.object({
    token: z.string().min(10),
    search: z.string().trim().max(100).optional().default(""),
  }).parse(d))
  .handler(async ({ data }) => {
    await verifyToken(data.token);
    let q = supabaseAdmin
      .from("products")
      .select("id, name, name_bn, image_url, unit, retail_price")
      .eq("is_deleted", false)
      .order("name")
      .limit(300);
    if (data.search) q = q.or(`name.ilike.%${data.search}%,name_bn.ilike.%${data.search}%`);
    const { data: rows, error } = await q;
    if (error) throw error;
    return (rows || []).map((p: any) => ({
      id: p.id,
      name: p.name,
      name_bn: p.name_bn || "",
      image_url: p.image_url || "",
      unit: p.unit || "pcs",
      price: Number(p.retail_price || 0),
    }));
  });

// ===== Portal: list my quotations =====
export const portalListMyQuotations = createServerFn({ method: "POST" })
  .inputValidator((d) => z.object({ token: z.string().min(10) }).parse(d))
  .handler(async ({ data }) => {
    const cid = await verifyToken(data.token);
    const { data: rows, error } = await supabaseAdmin
      .from("quotations" as any)
      .select("id, quote_no, for_self, referral_name, referral_mobile, referral_customer_id, total_amount, status, notes, created_at")
      .eq("customer_id", cid)
      .order("created_at", { ascending: false })
      .limit(100);
    if (error) throw error;
    return rows || [];
  });

// ===== Portal: get one quotation with items =====
export const portalGetQuotation = createServerFn({ method: "POST" })
  .inputValidator((d) => z.object({ token: z.string().min(10), id: z.string().uuid() }).parse(d))
  .handler(async ({ data }) => {
    const cid = await verifyToken(data.token);
    const { data: q, error } = await supabaseAdmin
      .from("quotations" as any)
      .select("*")
      .eq("id", data.id)
      .eq("customer_id", cid)
      .maybeSingle();
    if (error) throw error;
    if (!q) throw new Error("Quotation not found");
    const { data: items } = await supabaseAdmin
      .from("quotation_items" as any)
      .select("*")
      .eq("quotation_id", data.id)
      .order("created_at");
    return { quotation: q, items: items || [] };
  });

// ===== Portal: create quotation (draft or submitted) =====
export const portalCreateQuotation = createServerFn({ method: "POST" })
  .inputValidator((d) => z.object({
    token: z.string().min(10),
    for_self: z.boolean(),
    referral_name: z.string().trim().max(200).optional().default(""),
    referral_mobile: z.string().trim().max(20).optional().default(""),
    items: z.array(itemInput).min(1).max(100),
    notes: z.string().trim().max(1000).optional().default(""),
    submit: z.boolean().optional().default(false),
  }).parse(d))
  .handler(async ({ data }) => {
    const cid = await verifyToken(data.token);

    if (!data.for_self) {
      if (!data.referral_mobile || data.referral_mobile.length < 6) {
        throw new Error("রেফারেল মোবাইল নাম্বার দিন");
      }
    }

    // Insert quotation header
    const { data: qrowRaw, error: qerr } = await supabaseAdmin
      .from("quotations" as any)
      .insert({
        customer_id: cid,
        for_self: data.for_self,
        referral_name: data.for_self ? "" : data.referral_name,
        referral_mobile: data.for_self ? "" : data.referral_mobile,
        notes: data.notes,
        status: data.submit ? "submitted" : "draft",
      } as any)
      .select("id, quote_no")
      .single();
    if (qerr) throw qerr;
    const qrow = qrowRaw as unknown as { id: string; quote_no: string };


    // Fetch product prices server-side (do not trust client)
    const pids = data.items.map((i) => i.product_id);
    const { data: prods } = await supabaseAdmin
      .from("products")
      .select("id, name, name_bn, unit, image_url, retail_price")
      .in("id", pids);
    const pmap = new Map((prods || []).map((p: any) => [p.id, p]));

    const items = data.items.map((i) => {
      const p: any = pmap.get(i.product_id);
      if (!p) throw new Error("Product not found: " + i.product_id);
      const price = Number(p.retail_price || 0);
      return {
        quotation_id: qrow.id,
        product_id: i.product_id,
        product_name: p.name,
        product_name_bn: p.name_bn || "",
        unit: p.unit || "pcs",
        image_url: p.image_url || "",
        quantity: i.quantity,
        unit_price: price,
        line_total: price * i.quantity,
      };
    });
    const { error: ierr } = await supabaseAdmin.from("quotation_items" as any).insert(items as any);
    if (ierr) throw ierr;

    return { ok: true, id: qrow.id, quote_no: qrow.quote_no };
  });

// ===== Portal: submit a draft =====
export const portalSubmitQuotation = createServerFn({ method: "POST" })
  .inputValidator((d) => z.object({ token: z.string().min(10), id: z.string().uuid() }).parse(d))
  .handler(async ({ data }) => {
    const cid = await verifyToken(data.token);
    const { data: q } = await supabaseAdmin
      .from("quotations" as any)
      .select("id, status, customer_id")
      .eq("id", data.id)
      .maybeSingle();
    if (!q || (q as any).customer_id !== cid) throw new Error("Not found");
    if ((q as any).status !== "draft") throw new Error("Only draft can be submitted");
    const { error } = await supabaseAdmin
      .from("quotations" as any)
      .update({ status: "submitted" } as any)
      .eq("id", data.id);
    if (error) throw error;
    return { ok: true };
  });

// ===== Portal: delete a draft =====
export const portalDeleteQuotation = createServerFn({ method: "POST" })
  .inputValidator((d) => z.object({ token: z.string().min(10), id: z.string().uuid() }).parse(d))
  .handler(async ({ data }) => {
    const cid = await verifyToken(data.token);
    const { data: q } = await supabaseAdmin
      .from("quotations" as any)
      .select("id, status, customer_id")
      .eq("id", data.id)
      .maybeSingle();
    if (!q || (q as any).customer_id !== cid) throw new Error("Not found");
    if ((q as any).status !== "draft") throw new Error("Only drafts can be deleted");
    const { error } = await supabaseAdmin.from("quotations" as any).delete().eq("id", data.id);
    if (error) throw error;
    return { ok: true };
  });

// ===== Admin: list quotations =====
export const adminListQuotations = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((d) => z.object({
    search: z.string().trim().max(100).optional().default(""),
    status: z.enum(["all", "draft", "submitted", "approved", "rejected"]).optional().default("all"),
  }).parse(d))
  .handler(async ({ data, context }) => {
    await assertAdmin(context.supabase, context.userId);
    let q = supabaseAdmin
      .from("quotations" as any)
      .select("*")
      .order("created_at", { ascending: false })
      .limit(500);
    if (data.status !== "all") q = q.eq("status", data.status);
    if (data.search) q = q.or(`quote_no.ilike.%${data.search}%,referral_mobile.ilike.%${data.search}%,referral_name.ilike.%${data.search}%`);
    const { data: rows, error } = await q;
    if (error) throw error;
    const all = (rows || []) as any[];

    // Hydrate customer + referrer
    const custIds = Array.from(new Set(all.flatMap((r) => [r.customer_id, r.referral_customer_id].filter(Boolean))));
    let cmap = new Map<string, any>();
    if (custIds.length) {
      const { data: cs } = await supabaseAdmin
        .from("customers")
        .select("id, name, name_bn, mobile")
        .in("id", custIds);
      cmap = new Map((cs || []).map((c: any) => [c.id, c]));
    }
    return all.map((r) => ({
      ...r,
      customer: cmap.get(r.customer_id) || null,
      referrer: r.referral_customer_id ? cmap.get(r.referral_customer_id) || null : null,
    }));
  });

// ===== Admin: get single quotation with items =====
export const adminGetQuotation = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((d) => z.object({ id: z.string().uuid() }).parse(d))
  .handler(async ({ data, context }) => {
    await assertAdmin(context.supabase, context.userId);
    const { data: q, error } = await supabaseAdmin
      .from("quotations" as any)
      .select("*")
      .eq("id", data.id)
      .single();
    if (error) throw error;
    const { data: items } = await supabaseAdmin
      .from("quotation_items" as any)
      .select("*")
      .eq("quotation_id", data.id)
      .order("created_at");
    const ids = [(q as any).customer_id, (q as any).referral_customer_id].filter(Boolean) as string[];
    const { data: cs } = await supabaseAdmin.from("customers").select("id,name,name_bn,mobile").in("id", ids.length ? ids : ["00000000-0000-0000-0000-000000000000"]);
    const cmap = new Map((cs || []).map((c: any) => [c.id, c]));
    return {
      quotation: q,
      items: items || [],
      customer: cmap.get((q as any).customer_id) || null,
      referrer: (q as any).referral_customer_id ? cmap.get((q as any).referral_customer_id) || null : null,
    };
  });

// ===== Admin: change quotation status =====
export const adminSetQuotationStatus = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((d) => z.object({
    id: z.string().uuid(),
    status: z.enum(["draft", "submitted", "approved", "rejected"]),
  }).parse(d))
  .handler(async ({ data, context }) => {
    await assertAdmin(context.supabase, context.userId);
    const { error } = await supabaseAdmin
      .from("quotations" as any)
      .update({
        status: data.status,
        reviewed_by: context.userId,
        reviewed_at: new Date().toISOString(),
      } as any)
      .eq("id", data.id);
    if (error) throw error;
    return { ok: true };
  });

// ===== Admin: search customers (for create dialog) =====
export const adminSearchCustomers = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((d) => z.object({ search: z.string().trim().max(100).optional().default("") }).parse(d))
  .handler(async ({ data, context }) => {
    await assertAdmin(context.supabase, context.userId);
    let q = supabaseAdmin
      .from("customers")
      .select("id, name, name_bn, mobile")
      .is("deleted_at", null)
      .order("name")
      .limit(50);
    if (data.search) q = q.or(`name.ilike.%${data.search}%,name_bn.ilike.%${data.search}%,mobile.ilike.%${data.search}%`);
    const { data: rows, error } = await q;
    if (error) throw error;
    return rows || [];
  });

// ===== Admin: search products (for create dialog) =====
export const adminSearchProducts = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((d) => z.object({ search: z.string().trim().max(100).optional().default("") }).parse(d))
  .handler(async ({ data, context }) => {
    await assertAdmin(context.supabase, context.userId);
    let q = supabaseAdmin
      .from("products")
      .select("id, name, name_bn, image_url, unit, retail_price")
      .eq("is_deleted", false)
      .order("name")
      .limit(100);
    if (data.search) q = q.or(`name.ilike.%${data.search}%,name_bn.ilike.%${data.search}%`);
    const { data: rows, error } = await q;
    if (error) throw error;
    return (rows || []).map((p: any) => ({
      id: p.id, name: p.name, name_bn: p.name_bn || "",
      image_url: p.image_url || "", unit: p.unit || "pcs",
      price: Number(p.retail_price || 0),
    }));
  });

// ===== Admin: create quotation on behalf of a customer =====
export const adminCreateQuotation = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((d) => z.object({
    customer_id: z.string().uuid(),
    for_self: z.boolean(),
    referral_name: z.string().trim().max(200).optional().default(""),
    referral_mobile: z.string().trim().max(20).optional().default(""),
    items: z.array(itemInput).min(1).max(100),
    notes: z.string().trim().max(1000).optional().default(""),
    status: z.enum(["draft", "submitted", "approved"]).optional().default("approved"),
  }).parse(d))
  .handler(async ({ data, context }) => {
    await assertAdmin(context.supabase, context.userId);

    if (!data.for_self && (!data.referral_mobile || data.referral_mobile.length < 6)) {
      throw new Error("রেফারেল মোবাইল নাম্বার দিন");
    }

    const { data: qrowRaw, error: qerr } = await supabaseAdmin
      .from("quotations" as any)
      .insert({
        customer_id: data.customer_id,
        for_self: data.for_self,
        referral_name: data.for_self ? "" : data.referral_name,
        referral_mobile: data.for_self ? "" : data.referral_mobile,
        notes: data.notes,
        status: data.status,
        reviewed_by: data.status !== "draft" ? context.userId : null,
        reviewed_at: data.status !== "draft" ? new Date().toISOString() : null,
      } as any)
      .select("id, quote_no")
      .single();
    if (qerr) throw qerr;
    const qrow = qrowRaw as unknown as { id: string; quote_no: string };

    const pids = data.items.map((i) => i.product_id);
    const { data: prods } = await supabaseAdmin
      .from("products")
      .select("id, name, name_bn, unit, image_url, retail_price")
      .in("id", pids);
    const pmap = new Map((prods || []).map((p: any) => [p.id, p]));

    const items = data.items.map((i) => {
      const p: any = pmap.get(i.product_id);
      if (!p) throw new Error("Product not found: " + i.product_id);
      const price = Number(p.retail_price || 0);
      return {
        quotation_id: qrow.id,
        product_id: i.product_id,
        product_name: p.name,
        product_name_bn: p.name_bn || "",
        unit: p.unit || "pcs",
        image_url: p.image_url || "",
        quantity: i.quantity,
        unit_price: price,
        line_total: price * i.quantity,
      };
    });
    const { error: ierr } = await supabaseAdmin.from("quotation_items" as any).insert(items as any);
    if (ierr) throw ierr;

    return { ok: true, id: qrow.id, quote_no: qrow.quote_no };
  });

// ===== Admin: update quotation (replaces items) =====
export const adminUpdateQuotation = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((d) => z.object({
    id: z.string().uuid(),
    for_self: z.boolean(),
    referral_name: z.string().trim().max(200).optional().default(""),
    referral_mobile: z.string().trim().max(20).optional().default(""),
    items: z.array(itemInput).min(1).max(100),
    notes: z.string().trim().max(1000).optional().default(""),
    status: z.enum(["draft", "submitted", "approved", "rejected"]),
  }).parse(d))
  .handler(async ({ data, context }) => {
    await assertAdmin(context.supabase, context.userId);

    if (!data.for_self && (!data.referral_mobile || data.referral_mobile.length < 6)) {
      throw new Error("রেফারেল মোবাইল নাম্বার দিন");
    }

    const { error: uerr } = await supabaseAdmin
      .from("quotations" as any)
      .update({
        for_self: data.for_self,
        referral_name: data.for_self ? "" : data.referral_name,
        referral_mobile: data.for_self ? "" : data.referral_mobile,
        notes: data.notes,
        status: data.status,
        reviewed_by: context.userId,
        reviewed_at: new Date().toISOString(),
      } as any)
      .eq("id", data.id);
    if (uerr) throw uerr;

    const { error: derr } = await supabaseAdmin.from("quotation_items" as any).delete().eq("quotation_id", data.id);
    if (derr) throw derr;

    const pids = data.items.map((i) => i.product_id);
    const { data: prods } = await supabaseAdmin
      .from("products")
      .select("id, name, name_bn, unit, image_url, retail_price")
      .in("id", pids);
    const pmap = new Map((prods || []).map((p: any) => [p.id, p]));

    const items = data.items.map((i) => {
      const p: any = pmap.get(i.product_id);
      if (!p) throw new Error("Product not found: " + i.product_id);
      const price = Number(p.retail_price || 0);
      return {
        quotation_id: data.id,
        product_id: i.product_id,
        product_name: p.name,
        product_name_bn: p.name_bn || "",
        unit: p.unit || "pcs",
        image_url: p.image_url || "",
        quantity: i.quantity,
        unit_price: price,
        line_total: price * i.quantity,
      };
    });
    const { error: ierr } = await supabaseAdmin.from("quotation_items" as any).insert(items as any);
    if (ierr) throw ierr;

    return { ok: true };
  });

// ===== Admin: delete quotation =====
export const adminDeleteQuotation = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((d) => z.object({ id: z.string().uuid() }).parse(d))
  .handler(async ({ data, context }) => {
    await assertAdmin(context.supabase, context.userId);
    const { error: ie } = await supabaseAdmin.from("quotation_items" as any).delete().eq("quotation_id", data.id);
    if (ie) throw ie;
    const { error } = await supabaseAdmin.from("quotations" as any).delete().eq("id", data.id);
    if (error) throw error;
    return { ok: true };
  });





// ===== Portal: AI chat assistant for quotation (knows products + prices) =====
const chatMsg = z.object({
  role: z.enum(["user", "assistant"]),
  content: z.string().min(1).max(4000),
});
export const portalQuotationAIChat = createServerFn({ method: "POST" })
  .inputValidator((d) => z.object({
    token: z.string().min(10),
    messages: z.array(chatMsg).min(1).max(30),
  }).parse(d))
  .handler(async ({ data }) => {
    const cid = await verifyToken(data.token);
    const apiKey = process.env.LOVABLE_API_KEY;
    if (!apiKey) throw new Error("AI সার্ভিস কনফিগার করা নেই");

    // Look up customer type
    const { data: cust, error: custErr } = await supabaseAdmin
      .from("customers")
      .select("customer_type")
      .eq("id", cid)
      .maybeSingle();
    if (custErr) throw custErr;
    const isRetail = (cust?.customer_type || "retail") === "retail";

    // Load full catalog (safe fields only — no purchase_price/cost)
    const selectCols = isRetail
      ? "id, name, name_bn, sku, unit, image_url, retail_price, stock_quantity"
      : "id, name, name_bn, sku, unit, image_url, retail_price, wholesale_price, stock_quantity";
    const { data: prods, error } = await supabaseAdmin
      .from("products")
      .select(selectCols)
      .eq("is_deleted", false)
      .order("name")
      .limit(1000);
    if (error) throw error;

    const productBySku = new Map<string, any>();
    (prods || []).forEach((p: any) => { if (p.sku) productBySku.set(String(p.sku).toLowerCase(), p); });

    const lines = (prods || []).map((p: any) => {
      const retail = Number(p.retail_price || 0);
      const stock = Number(p.stock_quantity || 0) > 0 ? ` [স্টক: ${p.stock_quantity}]` : " [স্টক নেই]";
      if (isRetail) {
        return `• ${p.name_bn || p.name} (SKU: ${p.sku}) — ৳${retail}/${p.unit}${stock}`;
      }
      const wholesale = Number(p.wholesale_price || 0);
      const discount = retail > 0 && wholesale > 0 && wholesale < retail
        ? `, পাইকারি/ডিসকাউন্ট ৳${wholesale} (সাশ্রয় ৳${(retail - wholesale).toFixed(0)})`
        : "";
      return `• ${p.name_bn || p.name} (SKU: ${p.sku}) — খুচরা ৳${retail}/${p.unit}${discount}${stock}`;
    }).join("\n");

    const commonInstructions = `
গুরুত্বপূর্ণ — অ্যাকশন টুলস:
- গ্রাহক কোনো প্রোডাক্ট কোটেশনে যোগ করতে বললে (যেমন "এটা যোগ করো", "২টা নিব", "কার্টে দাও") \`add_product_to_cart\` টুল কল করো (সঠিক SKU + quantity দিয়ে)।
- গ্রাহক কোটেশন সাবমিট/ফাইনাল/পাঠাতে বললে (যেমন "সাবমিট করো", "পাঠিয়ে দাও", "অর্ডার দাও") \`submit_quotation\` টুল কল করো।
- "স্টক নেই" এমন প্রোডাক্ট কখনো যোগ করবে না — বরং বিকল্প সাজেস্ট করো।
- টুল কল করার পরে এক লাইনে বাংলায় নিশ্চিত করো কী যোগ/সাবমিট হয়েছে।
- গ্রাহক স্পষ্টভাবে না বললে নিজে থেকে কিছু যোগ বা সাবমিট করবে না।`;

    const system = isRetail
      ? `তুমি Niyamah-এর কাস্টমার পোর্টালের একজন বন্ধুসুলভ AI বিক্রয় সহকারী।
গ্রাহক কোটেশন তৈরি করছে এবং প্রোডাক্ট সম্পর্কে জিজ্ঞেস করছে। বাংলায় সংক্ষিপ্ত, পরিষ্কার উত্তর দাও।
নিচের ক্যাটালগ থেকে তথ্য দাও — শুধু খুচরা দাম এবং স্টক। ক্যাটালগে নেই এমন কিছু থাকলে স্পষ্টভাবে বলো।
গ্রাহককে সঠিক প্রোডাক্ট বেছে নিতে সাহায্য করো এবং প্রয়োজনে বিকল্প সাজেস্ট করো।
মনে রাখো — পাইকারি দাম কখনো বলা যাবে না।

স্টক না থাকলে কী করবে (গুরুত্বপূর্ণ):
- যদি গ্রাহকের চাওয়া প্রোডাক্টে "স্টক নেই" দেখা যায়, তখন স্পষ্টভাবে জানাও যে এটি এখন স্টকে নেই।
- এরপর ক্যাটালগ থেকে ১–৩টি বিকল্প প্রোডাক্ট সাজেস্ট করো যেগুলোতে স্টক আছে এবং নাম/ধরন/ব্যবহার কাছাকাছি।
- প্রতিটি বিকল্পের নাম, দাম ও ইউনিট সংক্ষেপে দাও।

ডিসকাউন্ট সংক্রান্ত নিয়ম (গ্রাহক জিজ্ঞেস করলেই কেবল বলবে):
- প্রোডাক্টের মূল্য (খুচরা দাম) অনুসারে ডিসকাউন্ট সর্বনিম্ন ৫% এবং সর্বোচ্চ ১৫% পর্যন্ত হতে পারে।
- কম মূল্যের প্রোডাক্টে কম শতাংশ (~৫%), বেশি মূল্যের প্রোডাক্টে বেশি শতাংশ (~১৫%)।
- চূড়ান্ত ডিসকাউন্ট অ্যাডমিন অনুমোদনের পর নিশ্চিত হবে।
- কখনোই নির্দিষ্ট পাইকারি দাম বা লাভের তথ্য প্রকাশ করবে না।
${commonInstructions}

==== প্রোডাক্ট ক্যাটালগ ====
${lines || "(কোনো প্রোডাক্ট পাওয়া যায়নি)"}
==== শেষ ====`
      : `তুমি Niyamah-এর কাস্টমার পোর্টালের একজন বন্ধুসুলভ AI বিক্রয় সহকারী।
গ্রাহক কোটেশন তৈরি করছে। বাংলায় সংক্ষিপ্ত, পরিষ্কার উত্তর দাও।
নিচের ক্যাটালগ থেকে তথ্য দাও — দাম, ডিসকাউন্ট, স্টক, ইউনিট। ক্যাটালগে নেই এমন কিছু থাকলে স্পষ্টভাবে বলো।

স্টক না থাকলে: স্পষ্টভাবে জানাও এবং স্টকে থাকা ১–৩টি কাছাকাছি বিকল্প সাজেস্ট করো (নাম, দাম, ইউনিট সহ)।
${commonInstructions}

==== প্রোডাক্ট ক্যাটালগ ====
${lines || "(কোনো প্রোডাক্ট পাওয়া যায়নি)"}
==== শেষ ====`;

    const tools = [
      {
        type: "function",
        function: {
          name: "add_product_to_cart",
          description: "কোটেশনের কার্টে একটি প্রোডাক্ট যোগ করো।",
          parameters: {
            type: "object",
            properties: {
              sku: { type: "string", description: "ক্যাটালগে দেওয়া প্রোডাক্টের SKU (হুবহু)" },
              quantity: { type: "number", description: "পরিমাণ, ন্যূনতম ১" },
            },
            required: ["sku", "quantity"],
            additionalProperties: false,
          },
        },
      },
      {
        type: "function",
        function: {
          name: "submit_quotation",
          description: "বর্তমান কার্টের সব প্রোডাক্ট নিয়ে কোটেশন সাবমিট করো।",
          parameters: { type: "object", properties: {}, additionalProperties: false },
        },
      },
    ];

    type Action =
      | { type: "add"; product: { id: string; name: string; name_bn: string; image_url: string; unit: string; price: number }; quantity: number }
      | { type: "submit" };
    const actions: Action[] = [];

    const convo: any[] = [
      { role: "system", content: system },
      ...data.messages,
    ];

    let finalReply = "";
    for (let i = 0; i < 4; i++) {
      const res = await fetch("https://ai.gateway.lovable.dev/v1/chat/completions", {
        method: "POST",
        headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` },
        body: JSON.stringify({
          model: "google/gemini-2.5-flash",
          messages: convo,
          tools,
          tool_choice: "auto",
        }),
      });
      if (res.status === 429) throw new Error("অনেক রিকোয়েস্ট — একটু পরে আবার চেষ্টা করুন");
      if (res.status === 402) throw new Error("AI ক্রেডিট শেষ — অ্যাডমিনকে জানান");
      if (!res.ok) throw new Error("AI সার্ভিস সাময়িকভাবে অনুপলব্ধ");
      const json: any = await res.json();
      const msg = json?.choices?.[0]?.message;
      if (!msg) { finalReply = "দুঃখিত, উত্তর তৈরি করা যায়নি"; break; }

      const toolCalls = msg.tool_calls || [];
      if (!toolCalls.length) {
        finalReply = msg.content || "";
        break;
      }

      convo.push({ role: "assistant", content: msg.content || "", tool_calls: toolCalls });

      for (const tc of toolCalls) {
        const name = tc.function?.name;
        let args: any = {};
        try { args = JSON.parse(tc.function?.arguments || "{}"); } catch {}
        let toolResult = "ok";

        if (name === "add_product_to_cart") {
          const sku = String(args.sku || "").toLowerCase();
          const qty = Math.max(1, Math.floor(Number(args.quantity) || 0));
          const p = productBySku.get(sku);
          if (!p) {
            toolResult = `error: SKU ${args.sku} ক্যাটালগে নেই`;
          } else if (Number(p.stock_quantity || 0) <= 0) {
            toolResult = `error: ${p.name_bn || p.name} এখন স্টকে নেই`;
          } else {
            actions.push({
              type: "add",
              product: {
                id: p.id,
                name: p.name,
                name_bn: p.name_bn || "",
                image_url: p.image_url || "",
                unit: p.unit || "pcs",
                price: Number(p.retail_price || 0),
              },
              quantity: qty,
            });
            toolResult = `added ${qty} × ${p.name_bn || p.name}`;
          }
        } else if (name === "submit_quotation") {
          actions.push({ type: "submit" });
          toolResult = "submitted";
        } else {
          toolResult = `error: unknown tool ${name}`;
        }

        convo.push({
          role: "tool",
          tool_call_id: tc.id,
          content: toolResult,
        });
      }
    }

    return { reply: finalReply || "ঠিক আছে।", actions };
  });
