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

export interface KnowledgeRow {
  id: string;
  kind: "faq" | "snippet";
  title: string;
  content: string;
  category: string;
  published: boolean;
  created_at: string;
  updated_at: string;
}

function publicClient() {
  const key = process.env.SUPABASE_PUBLISHABLE_KEY!;
  return createClient<Database>(process.env.SUPABASE_URL!, key, {
    auth: { persistSession: false, autoRefreshToken: false },
    global: {
      fetch: (input, init) => {
        const h = new Headers(init?.headers);
        if (key.startsWith("sb_") && h.get("Authorization") === `Bearer ${key}`) {
          h.delete("Authorization");
        }
        h.set("apikey", key);
        return fetch(input, { ...init, headers: h });
      },
    },
  });
}

async function assertAdmin(context: { supabase: any; userId: string }) {
  const { data, error } = await context.supabase.rpc("has_role", {
    _user_id: context.userId,
    _role: "admin",
  });
  if (error) throw new Error("Could not verify your permissions.");
  if (!data) throw new Error("Forbidden: admin access required.");
}

export const listKnowledge = createServerFn({ method: "GET" })
  .middleware([requireSupabaseAuth])
  .handler(async ({ context }) => {
    await assertAdmin(context);
    const { data, error } = await context.supabase
      .from("chatbot_knowledge")
      .select("*")
      .order("kind")
      .order("created_at", { ascending: false });
    if (error) throw new Error(error.message);
    return (data ?? []) as KnowledgeRow[];
  });

const knowledgeSchema = z.object({
  id: z.string().uuid().optional(),
  kind: z.enum(["faq", "snippet"]).default("faq"),
  title: z.string().trim().min(3).max(200),
  content: z.string().trim().min(5).max(6000),
  category: z.string().trim().min(1).max(60).default("general"),
  published: z.boolean().default(true),
});

export const saveKnowledge = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((input: unknown) => knowledgeSchema.parse(input))
  .handler(async ({ data, context }) => {
    await assertAdmin(context);
    const { id, ...values } = data;
    const query = id
      ? context.supabase.from("chatbot_knowledge").update(values).eq("id", id)
      : context.supabase.from("chatbot_knowledge").insert(values);
    const { error } = await query;
    if (error) throw new Error(error.message);
    return { ok: true as const };
  });

export const deleteKnowledge = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((input: { id: string }) => z.object({ id: z.string().uuid() }).parse(input))
  .handler(async ({ data, context }) => {
    await assertAdmin(context);
    const { error } = await context.supabase
      .from("chatbot_knowledge")
      .delete()
      .eq("id", data.id);
    if (error) throw new Error(error.message);
    return { ok: true as const };
  });

export const submitChatFeedback = createServerFn({ method: "POST" })
  .inputValidator((input: unknown) =>
    z
      .object({
        rating: z.enum(["up", "down"]),
        question: z.string().trim().max(2000).optional(),
        answer: z.string().trim().max(6000).optional(),
        messageRef: z.string().trim().max(120).optional(),
      })
      .parse(input),
  )
  .handler(async ({ data }) => {
    const { error } = await publicClient().from("chatbot_feedback").insert({
      rating: data.rating,
      question: data.question ?? null,
      answer: data.answer ?? null,
      message_ref: data.messageRef ?? null,
    });
    if (error) {
      console.error("chat feedback insert failed:", error.message);
      return { ok: false as const };
    }
    return { ok: true as const };
  });

export const chatFeedbackStats = createServerFn({ method: "GET" })
  .middleware([requireSupabaseAuth])
  .handler(async ({ context }) => {
    await assertAdmin(context);
    const { data, error } = await context.supabase
      .from("chatbot_feedback")
      .select("rating, question, answer, created_at")
      .order("created_at", { ascending: false })
      .limit(200);
    if (error) throw new Error(error.message);
    const rows = (data ?? []) as {
      rating: "up" | "down";
      question: string | null;
      answer: string | null;
      created_at: string;
    }[];
    const up = rows.filter((r) => r.rating === "up").length;
    const down = rows.length - up;
    return {
      up,
      down,
      satisfaction: rows.length ? Math.round((up / rows.length) * 100) : 0,
      recent: rows.slice(0, 30),
    };
  });
