"use server";

import { revalidatePath } from "next/cache";
import { createClient } from "../lib/supabase/server";
import z from "zod";
import { cache } from "react";

export const getContent = cache(async (client_id: string | undefined) => {
  const supabase = await createClient();

  let { data, error } = await supabase
    .from("content_schedule")
    .select(
      `*, URL:url_id(*, Content:Content(posted, created_at, content_approved))`,
    )
    .order(`posted_at`, { ascending: false })
    .eq("client_id", client_id ? +client_id : 1);

  if (error) {
    return { status: 500, message: error.message };
  }
  return { status: 200, data: data };
});
export const getTabData = cache(
  async (
    range_start: number,
    range_end: number,
    month: number,
    client_id: string | undefined,
    strategy_id?: number | null,
  ) => {
    const supabase = await createClient();

    let dataQuery = supabase
      .from("URL")
      .select(
        "*, strategy:strategy_id(id, client_id, strategy_version, strategy_status,created_at, comment_strategy)",
      )
      .eq("client_id", client_id ? +client_id : 1)
      .eq("include", true)
      .order("priority")
      .range(range_start, range_end - 1);

    if (strategy_id) {
      const { data, error } = await dataQuery.eq("strategy_id", strategy_id);

      if (error) {
        return [];
      }
      if (!data || data.length === 0) {
        return [];
      }
      return data.map((row) => ({ ...row, month: month }));
    } else {
      const { data, error } = await dataQuery;

      if (error) {
        return [];
      }
      if (!data || data.length === 0) {
        return [];
      }

      return data.map((row) => ({ ...row, month: month }));
    }
  },
);
export const getCountCategories = cache(
  async (
    client_id: string | undefined,
    category: string,
    strategy_id?: number | null,
  ) => {
    const supabase = await createClient();

    let dataCountQuery = supabase
      .from("URL")
      .select("page_type_frontend", { count: "exact", head: true })
      .eq("client_id", client_id ? +client_id : 1)
      .eq("include", true)
      .eq("page_type_frontend", category);

    if (strategy_id) {
      const { count } = await dataCountQuery.eq("strategy_id", strategy_id);
      return { status: 200, count: count };
    } else {
      const { count } = await dataCountQuery;
      return { status: 200, count: count };
    }
  },
);
export const moveRowToMonth = async (
  rowId: number,
  targetMonth: number,
  clientId: number,
  oldRank: number,
  ITEMS_PER_MONTH: number,
) => {
  const supabase = await createClient();

  if (oldRank === null) {
    throw new Error("Could not find the row's current rank.");
  }

  const visualOffset = ITEMS_PER_MONTH * (targetMonth - 1);

  const { data: anchorRow } = await supabase
    .from("URL")
    .select("priority")
    .eq("client_id", clientId)
    .eq("include", true)
    .order("priority", { ascending: true })
    .range(visualOffset, visualOffset)
    .single();

  let newRank = anchorRow ? anchorRow.priority : visualOffset;

  if (newRank === oldRank) return;

  let neighborQuery = supabase
    .from("URL")
    .select("url_id, priority")
    .eq("client_id", clientId);

  let shiftValue: 1 | -1;

  if (newRank < oldRank) {
    neighborQuery = neighborQuery
      .gte("priority", newRank)
      .lt("priority", oldRank);
    shiftValue = 1;
  } else {
    neighborQuery = neighborQuery
      .gt("priority", oldRank)
      .lte("priority", newRank);
    shiftValue = -1;
  }

  const { data: neighbors, error: neighborError } = await neighborQuery;

  if (neighborError) throw new Error("Failed to fetch shifting neighbors.");
  if (!neighbors) return;

  const updates = [];

  neighbors.forEach((row) => {
    updates.push({
      url_id: row.url_id,
      priority: row.priority + shiftValue,
    });
  });

  updates.push({
    url_id: rowId,
    priority: newRank,
  });

  const { error: updateError } = await supabase
    .from("URL")
    .upsert(updates, { onConflict: "url_id" });

  if (updateError) {
    return { status: 500, message: "Failed to move row" };
  }

  revalidatePath("/url-creation");
};

export const moveRowToMonthContent = async (
  rowId: number,
  targetMonth: number,
  clientId: number,
) => {
  const supabase = await createClient();

  // 1. Fetch current schedule ordered by plan_month and id
  const { data: schedule, error: fetchError } = await supabase
    .from("content_schedule")
    .select("id, url_id, plan_month, client_id")
    .eq("client_id", clientId)
    .order("plan_month", { ascending: true })
    .order("id", { ascending: true });

  if (fetchError || !schedule) {
    return {
      status: 500,
      message: fetchError?.message || "Failed to fetch schedule",
    };
  }

  const targetItem = schedule.find((item) => item.url_id === rowId);
  if (!targetItem) {
    return { status: 404, message: "Item not found in schedule" };
  }

  const sourceMonth = targetItem.plan_month;
  if (sourceMonth === targetMonth) {
    return { status: 200, message: "Item is already in target month" };
  }

  const updates: { id: number; plan_month: number }[] = [];

  updates.push({ id: targetItem.id, plan_month: targetMonth });

  if (targetMonth < sourceMonth) {
    for (let m = targetMonth; m < sourceMonth; m++) {
      const itemsInMonth = schedule.filter(
        (item) => item.plan_month === m && item.url_id !== rowId,
      );

      if (itemsInMonth.length === 0) {
        break;
      }

      const itemToShift = itemsInMonth[itemsInMonth.length - 1];
      updates.push({ id: itemToShift.id, plan_month: m + 1 });
    }
  } else {
    for (let m = sourceMonth; m < targetMonth; m++) {
      const itemsInNextMonth = schedule.filter(
        (item) => item.plan_month === m + 1 && item.url_id !== rowId,
      );

      if (itemsInNextMonth.length === 0) {
        break;
      }

      const itemToShift = itemsInNextMonth[0];
      updates.push({ id: itemToShift.id, plan_month: m });
    }
  }

  if (updates.length > 0) {
    const updatePromises = updates.map((update) =>
      supabase
        .from("content_schedule")
        .update({ plan_month: update.plan_month })
        .eq("id", update.id),
    );

    const results = await Promise.all(updatePromises);
    const hasError = results.some((result) => result.error);

    if (hasError) {
      console.error("Shift Error during Promise.all updates");
      return { status: 500, message: "Error shifting schedule" };
    }
  }

  revalidatePath("/", "layout");
  return { status: 200, message: "Schedule shifted successfully!" };
};

export const getStrategy = cache(async (client_id: string | undefined) => {
  const supabase = await createClient();

  const { data, error } = await supabase
    .from("strategy")
    .select(`*`)
    .eq("client_id", client_id ? +client_id : 1)
    .order("id", { ascending: true });

  if (error) {
    return { status: 500, message: error.message };
  }
  return { status: 200, strategies: data };
});

const FormSchema = z.object({
  comment_strategy: z.string(),
});
export const createStrategy = async (
  data: z.infer<typeof FormSchema>,
  client_id: number,
  strategy_id: number | null,
) => {
  const supabase = await createClient();
  const result = FormSchema.safeParse(data);

  if (!result.success) {
    return { status: 500, error: "Invalid form data" };
  }

  const { error } = await supabase
    .from("strategy")
    .update({
      strategy_status: "pending",
      comment_strategy: result.data.comment_strategy,
    })
    .eq("client_id", client_id)
    .eq("id", strategy_id);

  if (error) {
    return { status: 500, message: error.message };
  }

  revalidatePath("/url-creation", "layout");
  return {
    status: 200,
    message: "The strategy is in the process of creating.",
  };
};
