import Link from "next/link";
import { useEffect, useRef, useState } from "react";
import Seo from "../../components/common/Seo";
import BreadCrumb from "../../components/dashboard/common/BreadCrumb";
import DashboardHeader from "../../components/header/DashboardHeader";
import DashboardSidebar from "../../components/header/DashboardSidebar";
import MobileMenu from "../../components/header/MobileMenu";
import Footer from "../../components/footer/Footer";
import { useAuth } from "../../contexts/auth";
import { useRouter } from "next/router";
import { useGetAppliedJobs as getAppliedJobsApi } from "../../utils/hooks";
import { useSkillApi } from "../../utils/hooks/useSkillApi";
import { useGetCandidateProfileDetails as getCandidateProfileDetailsApi } from "../../utils/hooks/useGetCandidateProfileDetails";
import Swal from "sweetalert2";

type AttachedExamCard = {
  key: string;
  jobId: number;
  jobTitle: string;
  companyName: string;
  examId: number;
  examTitle: string;
  duration?: number | null;
  description?: string;
  isTaken: boolean;
  percentage?: number | null;
  closingDate?: string | null;
};

const CACHE_KEY = "job_attached_skill_tests_cache_v1";
const CACHE_TTL_MS = 5 * 60 * 1000;

const JobAttachedSkillTestPage = () => {
  const [getIsSidebarOpen, setIsSidebarOpen] = useState(false);
  const [cards, setCards] = useState<AttachedExamCard[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const router = useRouter();
  const { userRole, isAuthenticated } = useAuth() as any;
  const skillApi = useSkillApi() as any;
  const hasLoadedRef = useRef(false);
  const skillApiRef = useRef(skillApi);

  useEffect(() => {
    skillApiRef.current = skillApi;
  }, [skillApi]);

  useEffect(() => {
    if (isAuthenticated && userRole && userRole.toLowerCase() !== "candidate") {
      router.push("/dashboard");
    }
  }, [isAuthenticated, userRole, router]);

  useEffect(() => {
    const parsePercentage = (result: any): number | null => {
      const rawPercentage = Number(result?.percentage);
      if (Number.isFinite(rawPercentage)) return rawPercentage;

      const scoreText = String(result?.score || "");
      const scoreMatch = scoreText.match(/(\d+)\s*\/\s*(\d+)/);
      if (!scoreMatch) return null;

      const obtained = Number(scoreMatch[1]);
      const total = Number(scoreMatch[2]);
      if (!Number.isFinite(obtained) || !Number.isFinite(total) || total <= 0) {
        return null;
      }
      return (obtained / total) * 100;
    };

    const getCachedCards = () => {
      try {
        const raw = sessionStorage.getItem(CACHE_KEY);
        if (!raw) return null;
        const parsed = JSON.parse(raw) as {
          ts: number;
          cards: AttachedExamCard[];
        };
        if (!parsed?.ts || Date.now() - parsed.ts > CACHE_TTL_MS) return null;
        if (!Array.isArray(parsed.cards)) return null;
        return parsed.cards;
      } catch {
        return null;
      }
    };

    const setCachedCards = (nextCards: AttachedExamCard[]) => {
      try {
        sessionStorage.setItem(
          CACHE_KEY,
          JSON.stringify({ ts: Date.now(), cards: nextCards }),
        );
      } catch {
        // ignore cache write failures
      }
    };

    const buildCards = (
      appliedJobs: any[],
      attachedExamsByJobId: Map<number, any[]>,
      completedByExamId?: Map<number, number | null>,
    ) => {
      const collectAttachedExamsFromJob = (job: any) => {
        const app = job?.applications?.[0] || {};
        const examCollections = [
          ...(Array.isArray(job?.skillExams) ? job.skillExams : []),
          ...(Array.isArray(job?.jobPost?.skillExams)
            ? job.jobPost.skillExams
            : []),
          ...(Array.isArray(app?.jobPost?.skillExams)
            ? app.jobPost.skillExams
            : []),
          ...(attachedExamsByJobId.get(Number(job?.id)) || []),
        ];

        const attachedIds = [
          Number(job?.skillExamId),
          Number(job?.jobPost?.skillExamId),
          Number(app?.jobPost?.skillExamId),
        ].filter((id) => Number.isFinite(id) && id > 0);

        attachedIds.forEach((id) => {
          examCollections.push({
            id,
            title: "Skill Test",
          });
        });

        return examCollections;
      };

      const extractTakenInfoFromPerformances = (job: any, examId: number) => {
        const app = job?.applications?.[0] || {};
        const performances = [
          ...((app?.candidate?.examPerformances as any[]) || []),
          ...((job?.candidate?.examPerformances as any[]) || []),
          ...((job?.examPerformances as any[]) || []),
        ];

        const matched = performances.find((perf: any) => {
          const perfExamId = Number(perf?.examId ?? perf?.exam_id);
          const answerSetExamIds = Array.isArray(perf?.answerSet)
            ? perf.answerSet
                .map((ans: any) =>
                  Number(
                    ans?.id ?? ans?.examId ?? ans?.exam_id ?? ans?.skillExamId,
                  ),
                )
                .filter((id: number) => Number.isFinite(id) && id > 0)
            : [];
          const examType = String(perf?.examType || perf?.exam_type || "")
            .trim()
            .toLowerCase();
          const isSkillExam = examType ? examType.includes("skill") : true;
          const isCompleted =
            !!perf?.endTime ||
            !!perf?.end_time ||
            String(perf?.score || "").trim().length > 0 ||
            String(perf?.status || "").toUpperCase() === "COMPLETED";

          return (
            isSkillExam &&
            isCompleted &&
            (perfExamId === examId || answerSetExamIds.includes(examId))
          );
        });

        if (!matched) {
          return { isTaken: false, percentage: null as number | null };
        }

        return { isTaken: true, percentage: parsePercentage(matched) };
      };

      const nextCards: AttachedExamCard[] = [];
      const dedupe = new Set<string>();

      appliedJobs.forEach((job: any) => {
        const jobId = Number(job?.id);
        if (!Number.isFinite(jobId) || jobId <= 0) return;

        const jobTitle = String(job?.title || "Untitled Job");
        const companyName = String(job?.company?.name || "Company");
        const closingDate = job?.closingDate || job?.jobPost?.closingDate || null;
        const rawSkillExams = collectAttachedExamsFromJob(job);

        rawSkillExams.forEach((exam: any) => {
          const examId = Number(
            exam?.id ?? exam?.examId ?? exam?.exam_id ?? exam?.skillExamId,
          );
          if (!Number.isFinite(examId) || examId <= 0) return;

          const uniqueKey = `${jobId}-${examId}`;
          if (dedupe.has(uniqueKey)) return;
          dedupe.add(uniqueKey);

          const examTitle = String(exam?.title || exam?.name || "Skill Test");
          const fallbackTakenInfo = extractTakenInfoFromPerformances(
            job,
            examId,
          );
          const takenByResults = completedByExamId?.has(examId) || false;
          const isTaken = takenByResults || fallbackTakenInfo.isTaken;
          const percentage = takenByResults
            ? (completedByExamId?.get(examId) ?? null)
            : fallbackTakenInfo.percentage;

          nextCards.push({
            key: uniqueKey,
            jobId,
            jobTitle,
            companyName,
            examId,
            examTitle,
            duration: Number(exam?.duration) || null,
            description: String(exam?.description || ""),
            isTaken,
            percentage,
            closingDate,
          });
        });
      });

      return nextCards;
    };

    const fetchData = async () => {
      if (
        !isAuthenticated ||
        String(userRole || "").toLowerCase() !== "candidate"
      ) {
        return;
      }
      if (hasLoadedRef.current) return;
      hasLoadedRef.current = true;

      try {
        setLoading(true);
        setError(null);

        const cachedCards = getCachedCards();
        if (cachedCards && cachedCards.length > 0) {
          setCards(cachedCards);
          setLoading(false);
        }

        // Load all applied jobs pages
        let nextPage: string | null = "/?page=1";
        const appliedJobs: any[] = [];
        const visitedPages = new Set<string>();
        let pageGuard = 0;
        while (nextPage && pageGuard < 30) {
          if (visitedPages.has(nextPage)) break;
          visitedPages.add(nextPage);
          pageGuard += 1;

          const pageResp = (await getAppliedJobsApi("desc", nextPage)) as any;
          if (Array.isArray(pageResp?.data)) {
            appliedJobs.push(...pageResp.data);
          }
          nextPage = pageResp?.meta?.nextPageUrl || null;
        }

        // Fallback lookup: some applied-job payloads omit skillExams, but exams exist by jobPostId.
        const attachedExamsByJobId = new Map<number, any[]>();
        try {
          const allExamsResp = await skillApiRef.current.getExams();
          const allExams = Array.isArray(allExamsResp)
            ? allExamsResp
            : Array.isArray(allExamsResp?.data)
              ? allExamsResp.data
              : Array.isArray(allExamsResp?.exams)
                ? allExamsResp.exams
                : Array.isArray(allExamsResp?.skillExams)
                  ? allExamsResp.skillExams
                  : [];

          allExams.forEach((exam: any) => {
            const jobPostId = Number(exam?.jobPostId ?? exam?.job_post_id);
            if (!Number.isFinite(jobPostId) || jobPostId <= 0) return;
            const list = attachedExamsByJobId.get(jobPostId) || [];
            list.push(exam);
            attachedExamsByJobId.set(jobPostId, list);
          });
        } catch (examsErr) {
          console.warn("Unable to load fallback exams list.", examsErr);
        }

        // Build and render quickly using applied-job payload + fallback exam map.
        const initialCards = buildCards(appliedJobs, attachedExamsByJobId);
        setCards(initialCards);
        setCachedCards(initialCards);
        setLoading(false);

        // Enrich with official candidate results in background.
        const { resp } = (await getCandidateProfileDetailsApi()) as any;
        const candidateId = Number(resp?.id);
        const completedByExamId = new Map<number, number | null>();
        if (Number.isFinite(candidateId) && candidateId > 0) {
          try {
            const results = await skillApiRef.current.getResults(candidateId);
            if (Array.isArray(results)) {
              results.forEach((result: any) => {
                const examId = Number(result?.examId || result?.exam_id);
                const status = String(result?.status || "").toUpperCase();
                if (
                  !Number.isFinite(examId) ||
                  examId <= 0 ||
                  status !== "COMPLETED"
                ) {
                  return;
                }
                const pct = parsePercentage(result);
                if (!completedByExamId.has(examId)) {
                  completedByExamId.set(examId, pct);
                }
              });
            }
          } catch (resultsErr) {
            console.warn(
              "Unable to load completed results, using fallback performance data.",
              resultsErr,
            );
          }
        }

        const enrichedCards = buildCards(
          appliedJobs,
          attachedExamsByJobId,
          completedByExamId,
        );
        setCards(enrichedCards);
        setCachedCards(enrichedCards);
      } catch (err: any) {
        hasLoadedRef.current = false;
        setError(
          err?.response?.data?.message ||
            err?.message ||
            "Unable to load attached skill tests.",
        );
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [isAuthenticated, userRole]);

  return (
    <>
      <Seo pageTitle="Job Atteaced Skill Test" />
      <div className="page-wrapper dashboard">
        <span className="header-span"></span>
        <DashboardHeader
          logo={"/images/human_capital_logo.png"}
          ac_holder={"My Account"}
        />
        <MobileMenu />
        <DashboardSidebar
          getIsSidebarOpen={getIsSidebarOpen}
          setIsSidebarOpen={setIsSidebarOpen}
        />

        <section className="user-dashboard">
          <div className="dashboard-outer">
            <BreadCrumb
              title="Job Attached Skill Test"
              getIsSidebarOpen={getIsSidebarOpen}
              setIsSidebarOpen={setIsSidebarOpen}
            />

            <div className="row">
              <div className="col-lg-12">
                <div className="ls-widget">
                  <div className="widget-title">
                    <h4>Applied Job Attached Skill Tests</h4>
                  </div>
                  <div className="widget-content" style={{ paddingTop: "6px" }}>
                    {loading && <p>Loading attached skill tests...</p>}
                    {error && <p className="text-danger">{error}</p>}

                    {!loading && !error && cards.length === 0 && (
                      <p>
                        No job attached skill tests available for your applied
                        jobs.
                      </p>
                    )}

                    {!loading && !error && cards.length > 0 && (
                      <div className="row gx-4 gy-3">
                        {cards.map((card) => (
                          <div key={card.key} className="col-lg-6 col-md-12">
                            <div
                              className="h-100 d-flex flex-column"
                              style={{
                                minHeight: "275px",
                                padding: "20px 24px 18px",
                                background: "#f4fbfd",
                                border: "1px solid #d8ecf1",
                                borderRadius: "10px",
                                boxShadow: "0 2px 8px rgba(5, 88, 117, 0.08)",
                              }}
                            >
                              <div>
                                <h4
                                  className="mb-2"
                                  style={{ lineHeight: 1.2, fontWeight: 700 }}
                                >
                                  {card.examTitle}
                                </h4>
                                <p className="mb-1">
                                  <strong>Job:</strong> {card.jobTitle}
                                </p>
                                <p className="mb-2">
                                  <strong>Company:</strong> {card.companyName}
                                </p>
                                {card.duration ? (
                                  <p className="mb-2">
                                    <strong>Duration:</strong> {card.duration}{" "}
                                    min
                                  </p>
                                ) : null}
                                {card.description ? (
                                  <p
                                    className="mb-0"
                                    style={{ color: "#56606b" }}
                                  >
                                    <strong>Description:</strong>{" "}
                                    {card.description}
                                  </p>
                                ) : null}
                              </div>

                              {(() => {
                                const isJobExpired = card.closingDate ? card.closingDate < new Date().toISOString().split("T")[0] : false;

                                if (card.isTaken) {
                                  return (
                                    <div className="mt-auto pt-3 text-center">
                                      <p className="mb-2 text-success fw-bold">
                                        {typeof card.percentage === "number"
                                          ? `You Scored ${card.percentage.toFixed(2)}%`
                                          : "You already completed this attached skill test."}
                                      </p>
                                      <button
                                        className="theme-btn btn-style-three"
                                        disabled
                                        style={{
                                          cursor: "not-allowed",
                                          minWidth: "175px",
                                          padding: "10px 16px",
                                        }}
                                      >
                                        Exam Already Taken
                                      </button>
                                    </div>
                                  );
                                }

                                if (isJobExpired) {
                                  return (
                                    <div className="mt-auto pt-3 text-center">
                                      <button
                                        className="theme-btn btn-style-three"
                                        onClick={() => {
                                          Swal.fire({
                                            title: "Expired",
                                            text: "You cannot take the test because the job posting has expired.",
                                            icon: "error"
                                          });
                                        }}
                                        style={{
                                          minWidth: "175px",
                                          padding: "10px 16px",
                                        }}
                                      >
                                        Job Expired
                                      </button>
                                    </div>
                                  );
                                }

                                return (
                                  <div className="mt-auto pt-3 text-center">
                                    <Link
                                      href={`/dashboard/skill-test/startexam?examId=${card.examId}&jobId=${card.jobId}`}
                                      className="theme-btn btn-style-one"
                                      style={{
                                        minWidth: "175px",
                                        padding: "10px 16px",
                                      }}
                                    >
                                      Click to Take Test
                                    </Link>
                                  </div>
                                );
                              })()}
                            </div>
                          </div>
                        ))}
                      </div>
                    )}
                  </div>
                </div>
              </div>
            </div>
          </div>
        </section>

        <Footer />
      </div>
    </>
  );
};

export default JobAttachedSkillTestPage;
