import { corsHeaders, handleCors } from "../_shared/cors.ts";
import { verifyAdmin, AuthError } from "../_shared/auth.ts";
import { createServiceClient } from "../_shared/supabase-client.ts";

Deno.serve(async (req: Request) => {
  // Handle CORS preflight
  const corsResponse = handleCors(req);
  if (corsResponse) return corsResponse;

  try {
    // Verify admin auth
    await verifyAdmin(req);

    const supabase = createServiceClient();

    // ── DELETE: remove a job OR a single item ───────────────
    if (req.method === "DELETE") {
      const body = await req.json();
      const { jobId, itemId } = body as { jobId?: string; itemId?: string };

      // ── Delete a single track ──────────────────────────────
      if (itemId && typeof itemId === "string") {
        // Fetch the item to get its storage_path, status, and parent job_id
        const { data: item, error: fetchErr } = await supabase
          .from("download_items")
          .select("*")
          .eq("id", itemId)
          .single();

        if (fetchErr || !item) {
          return new Response(JSON.stringify({ error: "Item not found" }), {
            status: 404,
            headers: { ...corsHeaders, "Content-Type": "application/json" },
          });
        }

        // Remove audio file from storage if it exists
        if (item.storage_path) {
          const { error: storageError } = await supabase.storage
            .from("workout-audio")
            .remove([item.storage_path]);

          if (storageError) {
            console.error("Storage cleanup error:", storageError.message);
            // Continue with DB deletion even if storage cleanup fails
          }
        }

        // Delete the item row
        const { error: deleteError } = await supabase
          .from("download_items")
          .delete()
          .eq("id", itemId);

        if (deleteError) {
          throw new Error(`Failed to delete item: ${deleteError.message}`);
        }

        // Update the parent job counters
        const decrement: Record<string, number> = { total_items: -1 };
        if (item.status === "completed") {
          decrement.completed_items = -1;
        } else if (item.status === "failed") {
          decrement.failed_items = -1;
        }

        // Fetch current job to compute new values (Supabase doesn't support atomic decrement)
        const { data: parentJob } = await supabase
          .from("download_jobs")
          .select("total_items, completed_items, failed_items")
          .eq("id", item.job_id)
          .single();

        if (parentJob) {
          const updates: Record<string, number> = {
            total_items: Math.max(0, parentJob.total_items + (decrement.total_items ?? 0)),
          };
          if (decrement.completed_items) {
            updates.completed_items = Math.max(0, parentJob.completed_items + decrement.completed_items);
          }
          if (decrement.failed_items) {
            updates.failed_items = Math.max(0, parentJob.failed_items + decrement.failed_items);
          }

          await supabase
            .from("download_jobs")
            .update(updates)
            .eq("id", item.job_id);
        }

        return new Response(
          JSON.stringify({ deleted: true, itemId, jobId: item.job_id }),
          {
            status: 200,
            headers: { ...corsHeaders, "Content-Type": "application/json" },
          }
        );
      }

      // ── Delete an entire job ───────────────────────────────
      if (!jobId || typeof jobId !== "string") {
        return new Response(JSON.stringify({ error: "jobId or itemId is required" }), {
          status: 400,
          headers: { ...corsHeaders, "Content-Type": "application/json" },
        });
      }

      // Fetch items to find storage paths for cleanup
      const { data: items } = await supabase
        .from("download_items")
        .select("storage_path")
        .eq("job_id", jobId);

      // Delete files from storage bucket
      const storagePaths = (items ?? [])
        .map((i) => i.storage_path)
        .filter(Boolean) as string[];

      if (storagePaths.length > 0) {
        const { error: storageError } = await supabase.storage
          .from("workout-audio")
          .remove(storagePaths);

        if (storageError) {
          console.error("Storage cleanup error:", storageError.message);
          // Continue with DB deletion even if storage cleanup fails
        }
      }

      // Delete the job row (items cascade via FK)
      const { error: deleteError } = await supabase
        .from("download_jobs")
        .delete()
        .eq("id", jobId);

      if (deleteError) {
        throw new Error(`Failed to delete job: ${deleteError.message}`);
      }

      return new Response(
        JSON.stringify({ deleted: true, jobId, filesRemoved: storagePaths.length }),
        {
          status: 200,
          headers: { ...corsHeaders, "Content-Type": "application/json" },
        }
      );
    }

    // ── GET: fetch job(s) ─────────────────────────────────────
    if (req.method !== "GET" && req.method !== "PATCH") {
      return new Response(JSON.stringify({ error: "Method not allowed" }), {
        status: 405,
        headers: { ...corsHeaders, "Content-Type": "application/json" },
      });
    }

    // ── PATCH: update genre on download items ─────────────────
    if (req.method === "PATCH") {
      const { itemId, genre } = await req.json();
      if (!itemId || typeof itemId !== "string") {
        return new Response(
          JSON.stringify({ error: "itemId is required" }),
          {
            status: 400,
            headers: { ...corsHeaders, "Content-Type": "application/json" },
          }
        );
      }

      // genre can be null (to clear) or a valid genre string
      const { error: updateError } = await supabase
        .from("download_items")
        .update({ genre: genre || null })
        .eq("id", itemId);

      if (updateError) {
        throw new Error(`Failed to update genre: ${updateError.message}`);
      }

      return new Response(
        JSON.stringify({ updated: true, itemId, genre: genre || null }),
        {
          status: 200,
          headers: { ...corsHeaders, "Content-Type": "application/json" },
        }
      );
    }

    // ── GET: fetch job(s) ─────────────────────────────────────

    // Parse query params
    const url = new URL(req.url);
    const jobId = url.searchParams.get("jobId");

    // If jobId is provided, return that specific job + items
    if (jobId) {
      const { data: job, error: jobError } = await supabase
        .from("download_jobs")
        .select("*")
        .eq("id", jobId)
        .single();

      if (jobError || !job) {
        return new Response(JSON.stringify({ error: "Job not found" }), {
          status: 404,
          headers: { ...corsHeaders, "Content-Type": "application/json" },
        });
      }

      const { data: items } = await supabase
        .from("download_items")
        .select("*")
        .eq("job_id", jobId)
        .order("created_at", { ascending: true });

      return new Response(
        JSON.stringify({ job, items: items ?? [] }),
        {
          status: 200,
          headers: { ...corsHeaders, "Content-Type": "application/json" },
        }
      );
    }

    // No jobId -- return all jobs (most recent first)
    const { data: jobs, error: jobsError } = await supabase
      .from("download_jobs")
      .select("*")
      .order("created_at", { ascending: false })
      .limit(50);

    if (jobsError) {
      throw new Error(`Failed to fetch jobs: ${jobsError.message}`);
    }

    return new Response(
      JSON.stringify({ jobs: jobs ?? [] }),
      {
        status: 200,
        headers: { ...corsHeaders, "Content-Type": "application/json" },
      }
    );
  } catch (error) {
    const status = error instanceof AuthError ? error.status : 500;
    const message =
      error instanceof Error ? error.message : "Unknown error occurred";

    return new Response(JSON.stringify({ error: message }), {
      status,
      headers: { ...corsHeaders, "Content-Type": "application/json" },
    });
  }
});
