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 CourseRow {
  id: string;
  slug: string;
  title: string;
  summary: string;
  category: string;
  level: string;
  duration_hours: number;
}

export interface LessonRow {
  id: string;
  course_id: string;
  title: string;
  content: string;
  position: number;
  duration_minutes: number;
}

export interface StudioRequestRow {
  id: string;
  kind: string;
  title: string;
  details: string;
  status: string;
  output_url: string | null;
  created_at: string;
}

export interface GenerationRow {
  id: string;
  kind: string;
  prompt: string;
  output: string;
  created_at: string;
}

const GATEWAY = "https://ai.gateway.lovable.dev/v1/chat/completions";

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 });
      },
    },
  });
}

/* ---------------- e-learning ---------------- */

export const listCourses = createServerFn({ method: "GET" }).handler(async () => {
  const client = publicClient();
  const [{ data: courses }, { data: lessons }] = await Promise.all([
    client.from("courses").select("*").eq("published", true).order("title"),
    client.from("lessons").select("*").order("position"),
  ]);
  return {
    courses: (courses ?? []) as CourseRow[],
    lessons: (lessons ?? []) as LessonRow[],
  };
});

export const myEnrollments = createServerFn({ method: "GET" })
  .middleware([requireSupabaseAuth])
  .handler(async ({ context }) => {
    const { data } = await context.supabase
      .from("course_enrollments")
      .select("course_id, completed_lessons")
      .eq("user_id", context.userId);
    return (data ?? []) as { course_id: string; completed_lessons: string[] }[];
  });

export const enrollCourse = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((input: unknown) => z.object({ courseId: z.string().uuid() }).parse(input))
  .handler(async ({ data, context }) => {
    const { error } = await context.supabase
      .from("course_enrollments")
      .upsert(
        { user_id: context.userId, course_id: data.courseId },
        { onConflict: "user_id,course_id", ignoreDuplicates: true },
      );
    if (error) throw new Error(error.message);
    return { ok: true as const };
  });

export const toggleLesson = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((input: unknown) =>
    z.object({ courseId: z.string().uuid(), lessonId: z.string().uuid() }).parse(input),
  )
  .handler(async ({ data, context }) => {
    const { data: row } = await context.supabase
      .from("course_enrollments")
      .select("id, completed_lessons")
      .eq("user_id", context.userId)
      .eq("course_id", data.courseId)
      .maybeSingle();

    const current: string[] = (row?.completed_lessons as string[]) ?? [];
    const next = current.includes(data.lessonId)
      ? current.filter((id) => id !== data.lessonId)
      : [...current, data.lessonId];

    if (row) {
      await context.supabase
        .from("course_enrollments")
        .update({ completed_lessons: next })
        .eq("id", row.id);
    } else {
      await context.supabase
        .from("course_enrollments")
        .insert({ user_id: context.userId, course_id: data.courseId, completed_lessons: next });
    }
    return { completed: next };
  });

/* ---------------- creative suite ---------------- */

const docSchema = z.object({
  kind: z.enum(["document", "copy", "script"]).default("document"),
  prompt: z.string().trim().min(8).max(3000),
});

export const generateDocument = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((input: unknown) => docSchema.parse(input))
  .handler(async ({ data, context }) => {
    const key = process.env.LOVABLE_API_KEY;
    if (!key) throw new Error("AI is not configured yet.");

    const system =
      data.kind === "script"
        ? "You are a senior scriptwriter. Produce a clear, well-paced script with scene or segment headers."
        : data.kind === "copy"
          ? "You are a senior marketing copywriter. Produce persuasive, concrete copy with headings and bullets."
          : "You are a professional business writer. Produce a well-structured document in Markdown with headings, bullets and a short summary.";

    const res = await fetch(GATEWAY, {
      method: "POST",
      headers: { "content-type": "application/json", "Lovable-API-Key": key },
      body: JSON.stringify({
        model: "google/gemini-2.5-flash",
        messages: [
          { role: "system", content: system },
          { role: "user", content: data.prompt },
        ],
      }),
    });
    if (res.status === 429) throw new Error("Rate limit reached. Please try again shortly.");
    if (res.status === 402) throw new Error("AI credits exhausted. Please top up to continue.");
    if (!res.ok) throw new Error("Generation failed. Please try again.");

    const json = (await res.json()) as { choices?: { message?: { content?: string } }[] };
    const output = json.choices?.[0]?.message?.content ?? "";
    await context.supabase
      .from("studio_generations")
      .insert({ user_id: context.userId, kind: data.kind, prompt: data.prompt, output });
    return { output };
  });

export const generateImage = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((input: unknown) =>
    z.object({ prompt: z.string().trim().min(5).max(1500) }).parse(input),
  )
  .handler(async ({ data, context }) => {
    const key = process.env.LOVABLE_API_KEY;
    if (!key) throw new Error("AI is not configured yet.");

    const res = await fetch(GATEWAY, {
      method: "POST",
      headers: { "content-type": "application/json", "Lovable-API-Key": key },
      body: JSON.stringify({
        model: "google/gemini-2.5-flash-image-preview",
        messages: [{ role: "user", content: data.prompt }],
        modalities: ["image", "text"],
      }),
    });
    if (res.status === 429) throw new Error("Rate limit reached. Please try again shortly.");
    if (res.status === 402) throw new Error("AI credits exhausted. Please top up to continue.");
    if (!res.ok) throw new Error("Image generation failed. Please try again.");

    const json = (await res.json()) as {
      choices?: { message?: { images?: { image_url?: { url?: string } }[] } }[];
    };
    const url = json.choices?.[0]?.message?.images?.[0]?.image_url?.url;
    if (!url) throw new Error("No image was returned. Try a more descriptive prompt.");

    await context.supabase
      .from("studio_generations")
      .insert({ user_id: context.userId, kind: "image", prompt: data.prompt, output: "" });
    return { imageUrl: url };
  });

const requestSchema = z.object({
  kind: z.enum(["voice_clone", "video"]),
  title: z.string().trim().min(3).max(160),
  details: z.string().trim().min(10).max(3000),
});

export const createStudioRequest = createServerFn({ method: "POST" })
  .middleware([requireSupabaseAuth])
  .inputValidator((input: unknown) => requestSchema.parse(input))
  .handler(async ({ data, context }) => {
    const { error } = await context.supabase
      .from("studio_requests")
      .insert({ user_id: context.userId, ...data });
    if (error) throw new Error(error.message);
    return { ok: true as const };
  });

export const myStudioWork = createServerFn({ method: "GET" })
  .middleware([requireSupabaseAuth])
  .handler(async ({ context }) => {
    const [requests, generations] = await Promise.all([
      context.supabase
        .from("studio_requests")
        .select("*")
        .eq("user_id", context.userId)
        .order("created_at", { ascending: false }),
      context.supabase
        .from("studio_generations")
        .select("*")
        .eq("user_id", context.userId)
        .order("created_at", { ascending: false })
        .limit(30),
    ]);
    return {
      requests: (requests.data ?? []) as StudioRequestRow[],
      generations: (generations.data ?? []) as GenerationRow[],
    };
  });
