import BreadCrumbLink from "@/layouts/shared/page.breadcrumbLink";
import { createRoleProtectedLoader } from "@/lib/features/protectedFetcher";
import { listPromoCodes } from "@/lib/features/promo-codes/query";
import type {
  PromoCode,
  PromoCodeListQueryParams,
  PromoCodeListResult,
  PromoCodeReferralFilter,
  PromoCodeStatusFilter,
  PromoCodeExpiredFilter,
} from "@/lib/features/promo-codes/types";
import type { AccessScope, CoreResponse } from "@/lib/features/types";
import { FEATURE_SLUGS, getCheckedAccess } from "@/lib/role-helpers";
import type { Route } from "./+types/page";
import PromoCodesClientPage from "./_client";

const DEFAULT_PROMO_CODES_LIMIT = 25;

const parsePositiveInteger = (value: string | null, fallback: number) => {
  const parsed = Number.parseInt(value ?? "", 10);
  return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
};

const getFiniteNumber = (value: unknown) => {
  if (typeof value === "number" && Number.isFinite(value)) {
    return value;
  }
  if (typeof value === "string" && value.trim().length > 0) {
    const parsed = Number.parseInt(value, 10);
    if (Number.isFinite(parsed)) {
      return parsed;
    }
  }
  return undefined;
};

const extractPromoCodeListResult = (
  response: CoreResponse<{ data: PromoCode[]; pagination: any }>,
  pageSize: number,
  fallbackOffset: number,
): PromoCodeListResult => {
  const innerData = response?.success ? response.data : null;
  const items = innerData?.data || [];

  const pagination = innerData?.pagination;
  const totalCount = getFiniteNumber(pagination?.total);
  const hasNextPage = pagination?.hasNext ?? false;
  const offset = getFiniteNumber(pagination?.offset) ?? fallbackOffset;

  return {
    items,
    total:
      totalCount ??
      (hasNextPage ? offset + items.length + 1 : offset + items.length),
    totalKnown: totalCount !== undefined,
    hasNextPage,
    limit: getFiniteNumber(pagination?.limit) ?? pageSize,
    offset,
    raw: innerData,
  };
};

export const handle = {
  breadcrumb: () => (
    <BreadCrumbLink
      links={[
        {
          label: "Promo Codes",
        },
        {
          label: "Overview",
        },
      ]}
    />
  ),
};

export const loader = createRoleProtectedLoader(
  FEATURE_SLUGS.promoCodes,
  "read",
  async ({ request }) => {
    const url = new URL(request.url);
    // Active defaults ON: absent param → checked (isActive=true). Explicit
    // "all" means the user unchecked it (show every status).
    const rawIsActiveParam = url.searchParams.get("isActive");
    const isActiveParam: PromoCodeStatusFilter =
      rawIsActiveParam === "all" || rawIsActiveParam === "false"
        ? rawIsActiveParam
        : "true";
    // Only Promo Code defaults ON: absent → checked (show managed promo codes).
    // Explicit "false" = the user unchecked it.
    const rawOnlyPromoCodes = url.searchParams.get("onlyPromoCodes");
    const onlyPromoCodes: PromoCodeReferralFilter =
      rawOnlyPromoCodes === "false" ? "false" : "true";
    // Include Member Referral defaults OFF.
    const rawMemberReferral = url.searchParams.get("onlyMemberReferralCodes");
    const memberReferral: PromoCodeReferralFilter =
      rawMemberReferral === "true" ? "true" : "false";
    const rawIncludeExpired = url.searchParams.get("includeExpired");
    const includeExpired: PromoCodeExpiredFilter =
      rawIncludeExpired === "true" ? "true" : "false";
    const searchTerm = url.searchParams.get("searchTerm") || "";

    const limit = parsePositiveInteger(
      url.searchParams.get("limit"),
      DEFAULT_PROMO_CODES_LIMIT,
    );
    const offset = parsePositiveInteger(url.searchParams.get("offset"), 0);
    const query: PromoCodeListQueryParams = {
      isActive: isActiveParam === "all" ? undefined : isActiveParam,
      onlyPromoCodes: onlyPromoCodes === "true" ? "true" : undefined,
      onlyMemberReferralCodes: memberReferral === "true" ? "true" : undefined,
      includeExpired,
      searchTerm: searchTerm || undefined,
      limit,
      offset,
    };

    const response = await listPromoCodes(query, {
      Cookie: request.headers.get("Cookie") ?? "",
    });

    const accessScope = getCheckedAccess(request, FEATURE_SLUGS.promoCodes);
    const listResult = extractPromoCodeListResult(response, limit, offset);

    return {
      response,
      isActiveParam,
      onlyPromoCodes,
      memberReferral,
      includeExpired,
      searchTerm,
      limit: listResult.limit ?? limit,
      offset: listResult.offset ?? offset,
      totalCount: listResult.total,
      totalCountKnown: listResult.totalKnown,
      hasNextPage: listResult.hasNextPage,
      items: listResult.items,
      accessScope,
    };
  },
);

const PromoCodesPage: React.FC<Route.ComponentProps> = ({ loaderData }) => {
  const {
    response,
    items,
    isActiveParam,
    onlyPromoCodes,
    memberReferral,
    includeExpired,
    searchTerm,
    limit,
    offset,
    totalCount,
    totalCountKnown,
    hasNextPage,
    accessScope,
  } = loaderData as unknown as {
    response: CoreResponse<{ data: PromoCode[]; pagination: any }>;
    items: PromoCode[];
    isActiveParam: PromoCodeStatusFilter;
    onlyPromoCodes: PromoCodeReferralFilter;
    memberReferral: PromoCodeReferralFilter;
    includeExpired: PromoCodeExpiredFilter;
    searchTerm: string;
    limit: number;
    offset: number;
    totalCount: number;
    totalCountKnown: boolean;
    hasNextPage: boolean;
    accessScope: AccessScope;
  };

  return (
    <PromoCodesClientPage
      initialPromoCodes={items}
      initialIsActive={isActiveParam}
      initialOnlyPromoCodes={onlyPromoCodes}
      initialMemberReferral={memberReferral}
      initialIncludeExpired={includeExpired}
      initialSearchTerm={searchTerm}
      initialLimit={limit}
      initialOffset={offset}
      initialTotalCount={totalCount}
      initialTotalCountKnown={totalCountKnown}
      initialHasNextPage={hasNextPage}
      initialError={response?.success ? undefined : response?.message}
      accessScope={accessScope}
    />
  );
};

export default PromoCodesPage;
