"use client";

import { useQueryClient } from "@tanstack/react-query";
import Image from "next/image";
import { useRouter } from "next/navigation";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { IoClose } from "react-icons/io5";
import Button from "@/components/Componentes/button";
import DataErrorState from "@/components/Componentes/data-error-state";
import ErrorToast from "@/components/Componentes/error-toast";
import { FixToTheEnd } from "@/components/Componentes/fix-to-the-end";
import InformationSheet from "@/components/Componentes/information-sheet";
import NavigationButton from "@/components/Componentes/navigation-button";
import { PageBackground } from "@/components/Componentes/page-background";
import { getQuestionAnswersStorageKey } from "@/components/Componentes/question-answer-storage";
import QuestionCard from "@/components/Componentes/question-card";
import RequiredStepsCard from "@/components/Componentes/required-steps-card";
import type { MarriageField } from "@/hooks/marriage/types";
import { marriageQueryKeys } from "@/hooks/marriage/query-keys";
import {
  getFormSection,
  useFormOverviewQuery,
} from "@/hooks/marriage/use-form-schema";
import { useStartMarriageMatchMutation } from "@/hooks/marriage/use-match-start";
import { useMarriageProfileQuery } from "@/hooks/marriage/use-profile-main";
import {
  applyProfilePatchResultToCache,
  updateMarriageSectionData,
} from "@/hooks/marriage/use-section-data";
import { useCloseServiceOnBack } from "@/hooks/use-close-service-on-back";
import { getAssessmentLocalProgress } from "@/lib/assessment-progress";
import {
  getSubmitPath,
  hasCompletedMarriageProfileBasics,
} from "@/lib/get-submit-path";
import { REQUIRED_PROFILE_SECTION_COUNT } from "@/lib/marriage-profile-contract";
import {
  clearMatchStartGrace,
  markMatchStarted,
} from "@/lib/match-start-grace";
import type { QuestionListItem } from "@/lib/schema-adapter";
import { convertOverviewToFrontendItems } from "@/lib/schema-adapter";
import { localizePath } from "@/translations/config";
import { useI18n } from "@/translations/provider";
import { prefetchSectionsWithBoundedConcurrency } from "./section-prefetch";
import SectionsRequest from "./sections-request";

export default function QuestionsListPage() {
  useCloseServiceOnBack();
  const { dictionary: t, locale } = useI18n();
  const router = useRouter();
  const queryClient = useQueryClient();
  const { data: profile, isLoading: isProfileLoading, isError: isProfileError, refetch: refetchProfile } =
    useMarriageProfileQuery();
  const { data: overview, isLoading: isSchemaLoading, isError: isSchemaError, refetch: refetchOverview } = useFormOverviewQuery(
    "profile",
    locale,
  );

  const isSectionsLoading = false;

  const profileTargetPath = useMemo(
    () => (profile ? getSubmitPath(profile) : null),
    [profile],
  );
  const isProfileRedirecting =
    profileTargetPath !== null &&
    profileTargetPath !== "/questions-list" &&
    (!hasCompletedMarriageProfileBasics(profile) ||
      profile?.can_edit_profile === false);

  useEffect(() => {
    if (isProfileRedirecting && profileTargetPath) {
      router.replace(localizePath(profileTargetPath, locale));
    }
  }, [isProfileRedirecting, locale, profileTargetPath, router]);

  const startMatchMutation = useStartMarriageMatchMutation({
    onSuccess: () => {
      markMatchStarted();
      router.push(localizePath("/finding-match", locale));
    },
    onError: () => {
      // Never pretend the request went through – the user stays here and can
      // retry instead of being parked on the waiting screen forever.
      clearMatchStartGrace();
    },
  });
  const [isOptionalInfoSheetOpen, setIsOptionalInfoSheetOpen] = useState(false);
  const [selectedSection, setSelectedSection] =
    useState<QuestionListItem | null>(null);
  const questionListItems = useMemo(
    () => convertOverviewToFrontendItems(overview),
    [overview],
  );
  const [localAssessmentProgress, setLocalAssessmentProgress] = useState<
    Map<string, number>
  >(new Map());

  useEffect(() => {
    const next = new Map<string, number>();
    for (const slug of ["personality_test", "glasser_5_needs_test"]) {
      try {
        const raw = window.localStorage.getItem(`marriage:tests:${slug}:draft`);
        const draft = raw ? JSON.parse(raw) : null;
        const progress = getAssessmentLocalProgress(draft, false);
        if (progress > 0) next.set(slug, progress);
      } catch {
        // Ignore malformed local drafts.
      }
    }
    setLocalAssessmentProgress(next);
  }, [overview]);

  const sectionProgressBySlug = useMemo(() => {
    const progressBySlug = new Map<string, number>();

    if (overview?.progress?.sections_progress) {
      Object.entries(overview.progress.sections_progress).forEach(
        ([slug, prog]) => {
          progressBySlug.set(
            slug,
            Math.max(0, Math.min(100, Math.round(prog.completion_percent))),
          );
        },
      );
    }
    localAssessmentProgress.forEach((progress, slug) => {
      if ((progressBySlug.get(slug) ?? 0) < 100)
        progressBySlug.set(slug, progress);
    });

    // Add fallback for combined section from the schema adapter which attaches it to questionListItems directly
    questionListItems.forEach((item) => {
      if (!progressBySlug.has(item.slug)) {
        progressBySlug.set(item.slug, item.progress);
      }
    });

    return progressBySlug;
  }, [overview, questionListItems, localAssessmentProgress]);

  const requiredQuestionListItems = useMemo(
    () => questionListItems.filter((item) => Boolean(item.required)),
    [questionListItems],
  );

  const completedRequiredSections = useMemo(
    () =>
      requiredQuestionListItems.filter(
        (item) => (sectionProgressBySlug.get(item.slug) ?? 0) >= 100,
      ).length,
    [requiredQuestionListItems, sectionProgressBySlug],
  );
  const [displayedRequiredSections, setDisplayedRequiredSections] = useState(
    () => completedRequiredSections,
  );

  useEffect(() => {
    if (displayedRequiredSections === completedRequiredSections) return;
    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
      setDisplayedRequiredSections(completedRequiredSections);
      return;
    }
    const direction =
      completedRequiredSections > displayedRequiredSections ? 1 : -1;
    const distance = Math.abs(
      completedRequiredSections - displayedRequiredSections,
    );
    const interval = window.setInterval(
      () => {
        setDisplayedRequiredSections((current) => {
          const next = current + direction;
          if (next === completedRequiredSections)
            window.clearInterval(interval);
          return next;
        });
      },
      Math.max(90, Math.floor(500 / distance)),
    );
    return () => window.clearInterval(interval);
  }, [completedRequiredSections, displayedRequiredSections]);

  const hasValidRequiredContract =
    requiredQuestionListItems.length === REQUIRED_PROFILE_SECTION_COUNT;

  useEffect(() => {
    if (overview && !hasValidRequiredContract) {
      console.error("Required section contract mismatch", {
        expected: REQUIRED_PROFILE_SECTION_COUNT,
        actual: requiredQuestionListItems.length,
      });
    }
  }, [hasValidRequiredContract, overview, requiredQuestionListItems.length]);

  const allRequiredSectionsCompleted = useMemo(() => {
    if (!hasValidRequiredContract) {
      return false;
    }

    return requiredQuestionListItems.every((item) => {
      const progress = sectionProgressBySlug.get(item.slug) ?? 0;
      return progress >= 100;
    });
  }, [
    hasValidRequiredContract,
    requiredQuestionListItems,
    sectionProgressBySlug,
  ]);

  const profileStatus = profile?.status;
  const isProfileSuspended = profileStatus === "suspended";
  const isProfileBlocked =
    profileStatus === "in_case" || profileStatus === "matched";
  const canStartMatch =
    !isProfileSuspended && !isProfileBlocked && allRequiredSectionsCompleted;
  const [isSyncError, setIsSyncError] = useState(false);
  const [isSyncing, setIsSyncing] = useState(false);
  const [toastMessage, setToastMessage] = useState<string | null>(null);

  const syncPromiseRef = useRef<Promise<void> | null>(null);

  const syncPendingAnswers = useCallback(async () => {
    if (!overview) return;
    if (syncPromiseRef.current) {
      return syncPromiseRef.current;
    }

    const task = (async () => {
      const pendingSections: Array<{
        storageKey: string;
        storedValue: {
          current_step: number;
          fields: MarriageField[];
          pending_keys: string[];
          pending_sync: boolean;
        };
        fields: MarriageField[];
        slug: string;
      }> = [];
      for (const item of questionListItems) {
        if (
          item.slug === "personality_test" ||
          item.slug === "glasser_5_needs_test"
        ) {
          continue;
        }
        const storageKey = getQuestionAnswersStorageKey(item.slug);
        const rawValue = window.localStorage.getItem(storageKey);
        if (!rawValue) continue;

        let storedValue: any;
        try {
          storedValue = JSON.parse(rawValue);
        } catch {
          continue;
        }

        if (
          !storedValue ||
          !storedValue.pending_sync ||
          !Array.isArray(storedValue.fields)
        ) {
          continue;
        }
        const pendingKeys = new Set<string>(
          Array.isArray(storedValue.pending_keys)
            ? storedValue.pending_keys
            : storedValue.fields.map((field: { key: string }) => field.key),
        );
        const pendingFields = storedValue.fields.filter(
          (field: { key: string }) => pendingKeys.has(field.key),
        );
        if (pendingFields.length === 0) continue;
        pendingSections.push({
          storageKey,
          storedValue,
          fields: pendingFields,
          slug: item.slug,
        });
      }

      if (pendingSections.length === 0) return;
      const result = await updateMarriageSectionData(pendingSections[0].slug, {
        current_step: pendingSections[0].storedValue.current_step,
        fields: pendingSections.flatMap((section) => section.fields),
        version: overview.version,
      });
      applyProfilePatchResultToCache(queryClient, locale, result);
      const cleared = new Set(result.cleared_answer_ids ?? []);

      for (const { storageKey, storedValue } of pendingSections) {
        storedValue.fields = storedValue.fields.filter(
          (field: { key: string }) => !cleared.has(field.key),
        );
        storedValue.pending_sync = false;
        storedValue.pending_keys = [];
        if (storedValue.fields.length === 0) {
          window.localStorage.removeItem(storageKey);
        } else {
          window.localStorage.setItem(storageKey, JSON.stringify(storedValue));
        }
      }
    })();

    syncPromiseRef.current = task;
    try {
      await task;
      setIsSyncError(false);
    } finally {
      syncPromiseRef.current = null;
    }
  }, [locale, overview, queryClient, questionListItems]);

  const prefetchSection = useCallback(
    (item: QuestionListItem) => {
      const href = localizePath(`/questions-list/${item.slug}`, locale);
      router.prefetch(href);
      if (
        item.slug === "personality_test" ||
        item.slug === "glasser_5_needs_test"
      )
        return;
      void queryClient.prefetchQuery({
        queryKey: marriageQueryKeys.formSection("profile", item.slug, locale),
        queryFn: () => getFormSection("profile", item.slug, locale),
        staleTime: 30 * 1000,
      });
    },
    [locale, queryClient, router],
  );

  const viewportPrefetchChain = useRef(Promise.resolve());
  const viewportPrefetchSlugs = useRef(new Set<string>());
  const enqueueViewportPrefetch = useCallback(
    (item: QuestionListItem) => {
      if (
        item.slug === "personality_test" ||
        item.slug === "glasser_5_needs_test" ||
        viewportPrefetchSlugs.current.has(item.slug)
      ) {
        return;
      }
      viewportPrefetchSlugs.current.add(item.slug);
      viewportPrefetchChain.current = viewportPrefetchChain.current
        .catch(() => undefined)
        .then(() =>
          queryClient.fetchQuery({
            queryKey: marriageQueryKeys.formSection(
              "profile",
              item.slug,
              locale,
            ),
            queryFn: () => getFormSection("profile", item.slug, locale),
            staleTime: 30 * 1000,
          }),
        )
        .then(() => undefined);
    },
    [locale, queryClient],
  );

  const prefetchQueueStarted = useRef(false);
  useEffect(() => {
    if (prefetchQueueStarted.current || !overview) return;
    const profileSections = questionListItems
      .filter(
        (item) =>
          item.slug !== "personality_test" &&
          item.slug !== "glasser_5_needs_test",
      )
      .sort((first, second) => {
        const firstPriority =
          first.required &&
          (sectionProgressBySlug.get(first.slug) ?? first.progress) < 100
            ? 0
            : 1;
        const secondPriority =
          second.required &&
          (sectionProgressBySlug.get(second.slug) ?? second.progress) < 100
            ? 0
            : 1;
        return firstPriority - secondPriority;
      });
    if (profileSections.length === 0) return;
    prefetchQueueStarted.current = true;
    let cancelled = false;
    void prefetchSectionsWithBoundedConcurrency(
      profileSections,
      (item) =>
        queryClient.fetchQuery({
          queryKey: marriageQueryKeys.formSection("profile", item.slug, locale),
          queryFn: () => getFormSection("profile", item.slug, locale),
          staleTime: 30 * 1000,
        }),
      () => cancelled,
    );
    return () => {
      cancelled = true;
    };
  }, [locale, overview, queryClient, questionListItems, sectionProgressBySlug]);

  useEffect(() => {
    void syncPendingAnswers().catch((err) => {
      console.warn("Background draft sync:", err);
    });
    const handleOnline = () => {
      void syncPendingAnswers().catch((err) => {
        console.warn("Background draft sync on online:", err);
      });
    };
    window.addEventListener("online", handleOnline);
    return () => window.removeEventListener("online", handleOnline);
  }, [syncPendingAnswers]);

  useEffect(() => {
    if (startMatchMutation.isError) {
      setToastMessage(
        t[
          "Sending the match request failed. Please check your connection and try again."
        ],
      );
    }
  }, [startMatchMutation.isError, t]);

  const handleCloseToast = () => {
    setToastMessage(null);
    setIsSyncError(false);
    startMatchMutation.reset();
  };

  const isStartMatchDisabled =
    startMatchMutation.isPending || isSyncing || !canStartMatch;

  const hasIncompleteOptionalSections = useMemo(() => {
    return questionListItems.some(
      (item) =>
        !item.required && (sectionProgressBySlug.get(item.slug) ?? 0) < 100,
    );
  }, [questionListItems, sectionProgressBySlug]);

  const handleStartMatch = async () => {
    if (isStartMatchDisabled || isSyncing) {
      return;
    }

    setIsSyncing(true);
    setIsSyncError(false);

    try {
      await syncPendingAnswers();
      startMatchMutation.mutate();
    } catch (err) {
      console.error("Failed to sync pending sections:", err);
      setIsSyncError(true);
      setToastMessage(
        t[
          "Sending the match request failed. Please check your connection and try again."
        ] ?? "Sending the match request failed. Please check your connection and try again."
      );
    } finally {
      setIsSyncing(false);
    }
  };

  if (
    isProfileLoading ||
    isSectionsLoading ||
    isSchemaLoading ||
    isProfileRedirecting
  ) {
    return (
      <>
        <PageBackground disabled />
        <main
          style={{ paddingBottom: "calc(100px + var(--safe-bottom))" }}
          className="-mx-[17px] relative min-h-screen overflow-x-clip bg-[#F5F5F5] px-[17px] pt-0"
        >
          <div className="pointer-events-none absolute inset-x-0 top-0 h-[240px] bg-[radial-gradient(circle_at_top,rgba(255,255,255,0.98)_0%,rgba(255,255,255,0.7)_42%,rgba(255,255,255,0)_100%)]" />
          <div className="pointer-events-none absolute -top-16 left-1/2 h-[220px] w-[220px] -translate-x-1/2 rounded-full bg-white/70 blur-3xl" />

          <header
            style={{
              paddingTop: "max(12px, calc(var(--safe-top) + 4px))",
            }}
            className="sticky top-0 z-20 -mx-[17px] flex items-center justify-between bg-[#F5F5F5]/90 px-[17px] pb-3 backdrop-blur-md"
          >
            <NavigationButton
              icon="back"
              iconLabel={t["Close questions list"]}
              onClick={(e) => {
                e.preventDefault();
                if (typeof window !== "undefined" && (window as any).HabibApp) {
                  (window as any).HabibApp.postMessage(
                    JSON.stringify({ action: "close_service" }),
                  );
                } else {
                  router.push("/");
                }
              }}
            />
            <h1 className="group-16 font-semibold text-[#151515]">
              {t["Profile registration"]}
            </h1>
            <NavigationButton
              icon="document"
              iconLabel={t["Support"]}
              className="shadow-[0_10px_26px_rgba(15,23,42,0.05)]"
            />
          </header>

          <div className="relative mt-4 space-y-5">
            <RequiredStepsCard
              completed={displayedRequiredSections}
              total={REQUIRED_PROFILE_SECTION_COUNT}
            />

            {/* Section Card Skeletons (solid blocks like the Meet/checkup
                AppShimmer loading — one sweep band runs across each card) */}
            <div className="space-y-3">
              {Array.from({ length: 6 }).map((_, idx) => (
                <div key={idx} className="shimmer-bg h-[84px] rounded-[20px]" />
              ))}
            </div>
          </div>

          <FixToTheEnd>
            <Button aria-label={t["Find Matches"]} disabled>
              <span className="flex items-center justify-center gap-2.5">
                <Image
                  src="/assets/images/noun-wedding-rings-6540466 1.svg"
                  alt=""
                  aria-hidden="true"
                  width={28}
                  height={28}
                  className="shrink-0"
                  loading="eager"
                  fetchPriority="high"
                />
                <span className="leading-none font-semibold">
                  {t["Submit"]}
                </span>
              </span>
            </Button>
          </FixToTheEnd>
        </main>
      </>
    );
  }

  if (isProfileError || isSchemaError) {
    return (
      <>
        <PageBackground disabled />
        <main
          style={{ paddingBottom: "calc(100px + var(--safe-bottom))" }}
          className="-mx-[17px] relative min-h-screen overflow-x-clip bg-[#F5F5F5] px-[17px] pt-0"
        >
          <div className="pointer-events-none absolute inset-x-0 top-0 h-[240px] bg-[radial-gradient(circle_at_top,rgba(255,255,255,0.98)_0%,rgba(255,255,255,0.7)_42%,rgba(255,255,255,0)_100%)]" />
          <div className="pointer-events-none absolute -top-16 left-1/2 h-[220px] w-[220px] -translate-x-1/2 rounded-full bg-white/70 blur-3xl" />

          <header
            style={{
              paddingTop: "max(12px, calc(var(--safe-top) + 4px))",
            }}
            className="sticky top-0 z-20 -mx-[17px] flex items-center justify-between bg-[#F5F5F5]/90 px-[17px] pb-3 backdrop-blur-md"
          >
            <NavigationButton
              icon="back"
              iconLabel={t["Close questions list"]}
              onClick={(e) => {
                e.preventDefault();
                if (typeof window !== "undefined" && (window as any).HabibApp) {
                  (window as any).HabibApp.postMessage(
                    JSON.stringify({ action: "close_service" }),
                  );
                } else {
                  router.push("/");
                }
              }}
            />
            <h1 className="group-16 font-semibold text-[#151515]">
              {t["Profile registration"]}
            </h1>
            <NavigationButton
              icon="document"
              iconLabel={t["Support"]}
              className="shadow-[0_10px_26px_rgba(15,23,42,0.05)]"
            />
          </header>

          <DataErrorState
            onRetry={() => {
              if (isProfileError) refetchProfile();
              if (isSchemaError) refetchOverview();
            }}
          />
        </main>
      </>
    );
  }

  return (
    <>
      {toastMessage && (
        <ErrorToast message={toastMessage} onClose={handleCloseToast} />
      )}
      {isOptionalInfoSheetOpen ? (
        <InformationSheet
          icon="warning"
          title={t["Important Note"]}
          description={
            <p className="px-0.5 text-sm leading-[1.45] text-[#2D2D2D]">
              {
                t[
                  "You've completed all required fields. However, filling in all sections will help us find better matches for you"
                ]
              }
            </p>
          }
          onClose={() => setIsOptionalInfoSheetOpen(false)}
          buttons={({ close }) => (
            <div className="grid w-full grid-cols-[33fr_67fr] gap-3">
              <Button
                className="rounded-[11px] border border-[#9B9B9B] bg-transparent text-[#8B8B8B] min-w-0"
                onClick={close}
                variant="outlined"
              >
                <span className="truncate">{t["Cancel"]}</span>
              </Button>
              <Button
                className="rounded-[11px] min-w-0"
                disabled={isStartMatchDisabled}
                onClick={() => {
                  close();
                  handleStartMatch();
                }}
              >
                <span className="truncate">{t["Submit"]}</span>
              </Button>
            </div>
          )}
        />
      ) : null}
      {selectedSection ? (
        <InformationSheet
          icon={null}
          title={({ close }) => (
            <span className="flex w-full items-start justify-between gap-3 text-left">
              <span className="group-14 leading-5 font-bold tracking-normal text-[#8B8B8B]">
                {selectedSection.title}
              </span>
              <button
                type="button"
                aria-label={`Close ${selectedSection.title} explanation`}
                className="-mt-0.5 flex size-6 shrink-0 items-center justify-center text-[#8F8F8F]"
                onClick={close}
              >
                <IoClose aria-hidden="true" className="text-[22px]" />
              </button>
            </span>
          )}
          description={
            <p className="px-0.5 group-14 leading-[1.45] text-[#2D2D2D]">
              {selectedSection.summary}
            </p>
          }
          onClose={() => setSelectedSection(null)}
          className="text-left"
        />
      ) : null}
      <SectionsRequest sections={overview?.sections} />
      <PageBackground disabled />

      <main
        style={{ paddingBottom: "calc(100px + var(--safe-bottom))" }}
        className="-mx-[17px] relative min-h-screen overflow-x-clip bg-[#F5F5F5] px-[17px] pt-0"
      >
        <div className="pointer-events-none absolute inset-x-0 top-0 h-[240px] bg-[radial-gradient(circle_at_top,rgba(255,255,255,0.98)_0%,rgba(255,255,255,0.7)_42%,rgba(255,255,255,0)_100%)]" />
        <div className="pointer-events-none absolute -top-16 left-1/2 h-[220px] w-[220px] -translate-x-1/2 rounded-full bg-white/70 blur-3xl" />

        <header
          style={{
            paddingTop: "max(12px, calc(var(--safe-top) + 4px))",
          }}
          className="sticky top-0 z-20 -mx-[17px] flex items-center justify-between bg-[#F5F5F5]/90 px-[17px] pb-3 backdrop-blur-md"
        >
          <NavigationButton
            icon="back"
            iconLabel={t["Close questions list"]}
            onClick={(e) => {
              e.preventDefault();
              if (typeof window !== "undefined" && (window as any).HabibApp) {
                (window as any).HabibApp.postMessage(
                  JSON.stringify({ action: "close_service" }),
                );
              } else {
                router.push("/");
              }
            }}
          />
          <h1 className="group-16 font-semibold text-[#151515]">
            {t["Profile registration"]}
          </h1>
          <NavigationButton
            icon="document"
            iconLabel={t["Support"]}
            className="shadow-[0_10px_26px_rgba(15,23,42,0.05)]"
          />
        </header>

        <div className="relative">
          <div className="mt-4">
            <RequiredStepsCard
              completed={displayedRequiredSections}
              total={REQUIRED_PROFILE_SECTION_COUNT}
            />
          </div>

          <section className="mt-5 space-y-3">
            {questionListItems.map((item) => (
              <QuestionCard
                key={item.slug}
                item={item}
                progress={sectionProgressBySlug.get(item.slug) ?? null}
                onInfoClick={(section) => setSelectedSection(section)}
                onNearViewport={enqueueViewportPrefetch}
                onPrefetch={prefetchSection}
              />
            ))}
          </section>
        </div>

        <FixToTheEnd>
          <Button
            aria-label={t["Find Matches"]}
            disabled={isStartMatchDisabled}
            isLoading={startMatchMutation.isPending || isSyncing}
            onClick={() => {
              if (hasIncompleteOptionalSections) {
                setIsOptionalInfoSheetOpen(true);
                return;
              }

              handleStartMatch();
            }}
          >
            <span className="flex items-center justify-center gap-2.5">
              <Image
                src="/assets/images/noun-wedding-rings-6540466 1.svg"
                alt=""
                aria-hidden="true"
                width={28}
                height={28}
                className="shrink-0"
                // Above-the-fold CTA asset: fetch it with the initial
                // document instead of letting next/image lazy-load it.
                loading="eager"
                fetchPriority="high"
              />
              <span className="leading-none font-semibold">{t["Submit"]}</span>
            </span>
          </Button>
        </FixToTheEnd>
      </main>
    </>
  );
}
