import { cookies } from "next/headers";
import type { NextResponse } from "next/server";
import type {
  StorefrontCart,
  StorefrontCartItem,
  StorefrontCartItemVariation,
  StorefrontImage,
} from "@/types/storefront";
import { starterRouteFetch } from "@/lib/wordpress-client";
import {
  type StorefrontSession,
  type WooMoney,
  fetchWooStoreJson,
  formatWooMoney,
} from "@/lib/woo-store-client";

export const CART_TOKEN_COOKIE = "shop_starter_cart_token";
export const CART_NONCE_COOKIE = "shop_starter_cart_nonce";

export type StorefrontCartSession = StorefrontSession;

interface WooCartItem {
  key: string;
  id: number;
  quantity: number;
  type: string;
  name: string;
  permalink: string;
  images?: Array<{
    src?: string;
    alt?: string;
  }>;
  variation?: Array<{
    attribute?: string;
    value?: string;
  }>;
  item_data?: Array<{
    key?: string;
    name?: string;
    display?: string;
    value?: string;
    hidden?: boolean;
  }>;
  prices: WooMoney & {
    price: string;
    regular_price?: string;
    sale_price?: string;
  };
  totals: WooMoney & {
    line_total: string;
  };
}

interface WooCart {
  items: WooCartItem[];
  items_count: number;
  totals: WooMoney & {
    total_items: string;
    total_price: string;
  };
}

interface CartMetaResponse {
  items?: Array<{
    requested_id?: number;
    product_id?: number;
    variation_id?: number | null;
    href?: string;
    brand?: string;
    category?: string;
    image?: {
      src?: string;
      alt?: string;
    } | null;
  }>;
}

type CartMetaItem = NonNullable<CartMetaResponse["items"]>[number];

function normalizeVariation(item: WooCartItem): StorefrontCartItemVariation[] {
  const itemData = (item.item_data ?? [])
    .filter((entry) => !entry.hidden)
    .map((entry) => ({
      label: entry.name?.trim() || entry.key?.trim() || "",
      value: entry.display?.trim() || entry.value?.trim() || "",
    }))
    .filter((entry) => entry.label && entry.value);

  if (itemData.length > 0) {
    return itemData;
  }

  return (item.variation ?? [])
    .map((entry) => ({
      label: (entry.attribute ?? "")
        .replace(/^attribute_/, "")
        .replace(/^pa_/, "")
        .replace(/[_-]+/g, " ")
        .replace(/\b\w/g, (character) => character.toUpperCase()),
      value: entry.value?.trim() || "",
    }))
    .filter((entry) => entry.label && entry.value);
}

function normalizeImage(
  image?: { src?: string; alt?: string } | null,
): StorefrontImage | null {
  if (!image?.src) {
    return null;
  }

  return {
    src: image.src,
    alt: image.alt ?? "",
  };
}

function toProductHref(permalink?: string, fallback = "/shop") {
  if (!permalink) {
    return fallback;
  }

  try {
    return new URL(permalink).pathname;
  } catch {
    return permalink.startsWith("/") ? permalink : fallback;
  }
}

async function getCartMeta(ids: number[]) {
  if (ids.length === 0) {
    return new Map<number, CartMetaItem>();
  }

  try {
    const payload = await starterRouteFetch<CartMetaResponse>(
      `/cart-meta?ids=${ids.join(",")}`,
      { cache: "no-store" },
    );

    return new Map<number, CartMetaItem>(
      (payload.items ?? [])
        .map((item) => [item.requested_id ?? 0, item] as const)
        .filter((entry) => entry[0] > 0),
    );
  } catch {
    return new Map<number, CartMetaItem>();
  }
}

async function requestWooCart(
  pathname: string,
  {
    method = "GET",
    session,
    body,
    retryOnAuthFailure = true,
  }: {
    method?: "GET" | "POST";
    session: StorefrontCartSession;
    body?: Record<string, unknown>;
    retryOnAuthFailure?: boolean;
  },
) {
  return fetchWooStoreJson<WooCart>(pathname, {
    method,
    session,
    body,
    retryOnAuthFailure,
    refreshPath: "/cart",
  });
}

export async function getCartSessionFromRequestCookies(): Promise<StorefrontCartSession> {
  const cookieStore = await cookies();

  return {
    cartToken: cookieStore.get(CART_TOKEN_COOKIE)?.value,
    nonce: cookieStore.get(CART_NONCE_COOKIE)?.value,
  };
}

export async function getRawStorefrontCart(session: StorefrontCartSession) {
  return requestWooCart("/cart", {
    method: "GET",
    session,
  });
}

export async function addStorefrontCartItem(
  session: StorefrontCartSession,
  input: {
    id: number;
    quantity: number;
    variation?: Array<{
      attribute: string;
      value: string;
    }>;
  },
) {
  return requestWooCart("/cart/add-item", {
    method: "POST",
    session,
    body: input,
  });
}

export async function updateStorefrontCartItem(
  session: StorefrontCartSession,
  key: string,
  quantity: number,
) {
  return requestWooCart("/cart/update-item", {
    method: "POST",
    session,
    body: {
      key,
      quantity,
    },
  });
}

export async function removeStorefrontCartItem(
  session: StorefrontCartSession,
  key: string,
) {
  return requestWooCart("/cart/remove-item", {
    method: "POST",
    session,
    body: {
      key,
    },
  });
}

export async function normalizeStorefrontCart(cart: WooCart): Promise<StorefrontCart> {
  const metaMap = await getCartMeta(
    Array.from(new Set(cart.items.map((item) => item.id))),
  );

  const items: StorefrontCartItem[] = cart.items.map((item) => {
    const meta = metaMap.get(item.id);
    const regularPrice =
      item.prices.regular_price && Number(item.prices.regular_price) > 0
        ? formatWooMoney(item.prices.regular_price, item.prices)
        : undefined;
    const baseImage = normalizeImage(item.images?.[0]);
    const metaImage = normalizeImage(meta?.image ?? null);
    const isOnSale =
      Boolean(item.prices.sale_price) &&
      Number(item.prices.regular_price ?? item.prices.price) >
        Number(item.prices.sale_price ?? item.prices.price);

    return {
      key: item.key,
      productId: meta?.product_id ?? item.id,
      variationId: meta?.variation_id ?? undefined,
      name: item.name,
      href: toProductHref(item.permalink, meta?.href ?? "/shop"),
      label: meta?.brand?.trim() || meta?.category?.trim() || "Proizvod",
      image: baseImage ?? metaImage,
      quantity: item.quantity,
      variation: normalizeVariation(item),
      unitPrice: formatWooMoney(item.prices.price, item.prices),
      total: formatWooMoney(item.totals.line_total, item.totals),
      regularPrice,
      isOnSale,
    };
  });

  return {
    items,
    itemCount: cart.items_count,
    subtotal: formatWooMoney(cart.totals.total_items, cart.totals),
    total: formatWooMoney(cart.totals.total_price, cart.totals),
    isEmpty: items.length === 0,
  };
}

export function applyCartSessionCookies(
  response: NextResponse,
  session: StorefrontCartSession,
) {
  if (session.cartToken) {
    response.cookies.set(CART_TOKEN_COOKIE, session.cartToken, {
      httpOnly: true,
      sameSite: "lax",
      secure: process.env.NODE_ENV === "production",
      path: "/",
      maxAge: 60 * 60 * 24 * 30,
    });
  }

  if (session.nonce) {
    response.cookies.set(CART_NONCE_COOKIE, session.nonce, {
      httpOnly: true,
      sameSite: "lax",
      secure: process.env.NODE_ENV === "production",
      path: "/",
      maxAge: 60 * 60 * 24,
    });
  }
}
