import dayjs from "dayjs";
import toast from "react-hot-toast";
import { useNavigate } from "react-router-dom";
import { useDebounce } from "@/hooks/useDebounce";
import React, { useEffect, useState } from "react";
import { API_Instance } from "@/api/axios.instance";
import API_Constants from "@/constants/api.constants";
import { Difficulty, ISubjectQuestions } from "@/types";
import ROUTE_CONSTANTS from "@/constants/route.constants";
import { AccordionRow } from "@/components/shared/Accordion";
import { getAxiosErrorMessage, difficultyColor } from "@/utils/index.utils";
import { Card, Input, Pagination, Spin, Empty, Tooltip, Popconfirm } from "antd";
import { Search, Pencil, Trash2, ChevronDown, ChevronRight, ClipboardList, Clock, Info, CheckCircle, Share2 } from "lucide-react";

interface SubjectTestsTabProps {
  subject: ISubjectQuestions;
}

const paginationInitial = {
  page: 1,
  limit: 10,
  total: 0,
  totalPages: 0,
};

export const SubjectTestsTab: React.FC<SubjectTestsTabProps> = ({ subject }) => {
  const [loading, setLoading] = useState<boolean>(false);
  const [search, setSearch] = useState<string>("");
  const [tests, setTests] = useState<any[]>([]);
  const [pagination, setPagination] = useState(paginationInitial);
  const debouncedSearch = useDebounce(search, 600);
  const navigate = useNavigate();

  const [openTestId, setOpenTestId] = useState<string | null>(null);
  const [openQuestionId, setOpenQuestionId] = useState<string | null>(null);
  const [questions, setQuestions] = useState<any[]>([]);
  const [questionPagination, setQuestionPagination] = useState(paginationInitial);
  const [questionsLoading, setQuestionsLoading] = useState<boolean>(false);
  const [questionSearch, setQuestionSearch] = useState<string>("");
  const debouncedQuestionSearch = useDebounce(questionSearch, 600);

  const fetchTests = async (page = 1, limit = 10) => {
    if (!subject?.id) return;
    setLoading(true);
    try {
      const res = await API_Instance.get(API_Constants.tests, {
        params: {
          page,
          limit,
          search: debouncedSearch,
          subjectId: subject.id
        },
      });
      setTests(res.data.data || []);

      if (res.data.meta) {
        setPagination({
          page: Number(res.data.meta.page),
          limit: Number(res.data.meta.limit),
          total: Number(res.data.meta.total),
          totalPages: Number(res.data.meta.totalPages),
        });
      } else {
        setPagination({
          page: Number(page),
          limit: Number(limit),
          total: Number(res.data.data?.length || 0),
          totalPages: 1,
        });
      }
    } catch (err) {
      toast.error(getAxiosErrorMessage(err));
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    fetchTests(1, pagination.limit);
  }, [debouncedSearch, subject?.id]);

  const handleDelete = async (id: string) => {
    try {
      await API_Instance.delete(`${API_Constants.tests}/${id}`);
      toast.success("Test deleted successfully");
      fetchTests(pagination.page, pagination.limit);
    } catch (error: any) {
      toast.error(getAxiosErrorMessage(error));
    }
  };

  const getQuestions = async (page = 1, limit = 10, testId: string, qSearch = "", totalQuestionsFallback = 0) => {
    if (!testId) return;
    setQuestionsLoading(true);
    try {
      const response = await API_Instance.get(
        `${API_Constants.tests}/questions/${testId}`,
        { params: { page, limit, search: qSearch } }
      );
      setQuestions(response.data.questions || []);

      const metaData = response.data.meta || response.data.pagination;
      setQuestionPagination(
        metaData
          ? {
            page: Number(metaData.page),
            limit: Number(metaData.limit),
            total: Number(metaData.total),
            totalPages: Number(metaData.totalPages),
          }
          : {
            page: Number(page),
            limit: Number(limit),
            total: Number(totalQuestionsFallback),
            totalPages: Math.ceil(totalQuestionsFallback / limit)
          }
      );
    } catch (error) {
      toast.error(getAxiosErrorMessage(error));
    } finally {
      setQuestionsLoading(false);
    }
  };

  const toggleTest = (testId: string, totalQuestions: number) => {
    if (openTestId === testId) {
      setOpenTestId(null);
      setOpenQuestionId(null);
      setQuestions([]);
      return;
    }
    setOpenTestId(testId);
    setOpenQuestionId(null);
    setQuestions([]);
    setQuestionSearch("");
    setQuestionPagination({ ...paginationInitial, total: totalQuestions });
    getQuestions(1, paginationInitial.limit, testId, "", totalQuestions);
  };

  const toggleQuestion = (id: string) => {
    setOpenQuestionId(openQuestionId === id ? null : id);
  };

  useEffect(() => {
    if (openTestId) {
      const activeTest = tests.find((t) => t.id === openTestId);
      const fallbackCount = activeTest?.questions?.length || activeTest?._count?.testQuestions || 0;
      getQuestions(1, questionPagination.limit, openTestId, debouncedQuestionSearch, fallbackCount);
    }
  }, [debouncedQuestionSearch]);

  return (
    <div className="w-full mt-2">
      <div className="flex justify-between items-center">
        <div className="w-full md:w-72">
          <Input
            placeholder="Search Tests..."
            prefix={<Search size={16} className="text-slate-400" />}
            allowClear
            value={search}
            onChange={(e) => setSearch(e.target.value)}
          />
        </div>
        <div className="text-slate-500 text-sm">
          Total Tests: <span className="font-semibold text-slate-800">{pagination.total}</span>
        </div>
      </div>

      <Spin spinning={loading}>
        {tests.length === 0 && !loading ? (
          <div className="min-h-[200px] flex items-center justify-center">
            <Empty description={debouncedSearch ? "No tests found matching your criteria" : "No tests available"} />
          </div>
        ) : (
          <div className="pt-4 pl-2 border-l-2 border-slate-200 ml-6 space-y-1">
            {tests.map((test) => {
              const qCount = test.questions?.length || test._count?.testQuestions || 0;
              return (
                <AccordionRow
                  key={test.id}
                  title={
                    <div className="w-full flex items-center justify-between gap-3">
                      <div className="flex items-center gap-2">
                        <h2 className="text-md font-semibold text-slate-900">{test.title}</h2>
                        <p className="text-xs text-slate-500 mt-0.5 flex items-center gap-2">
                          <span>{qCount} Questions</span>
                        </p>
                        {test.referenceSourceId && (
                          <div className="flex items-center gap-1.5 px-2 py-0.5 bg-blue-50 border border-blue-100 rounded-md ml-2">
                            <Share2 size={12} className="text-blue-500" />
                            <span className="text-[11px] font-medium text-blue-600">Shared by Exam Infra</span>
                          </div>
                        )}
                      </div>
                      <div className="flex items-center gap-1 pl-2 border-l border-slate-200 ml-2" onClick={(e) => e.stopPropagation()}>
                        <Tooltip title={test.referenceSourceId ? "Cannot edit a shared test" : "Edit Test"}>
                          <div style={{ display: 'inline-block' }}>
                            <button
                              className={`p-1.5 rounded-xl transition-colors ${test.referenceSourceId ? 'text-slate-300 cursor-not-allowed' : 'text-slate-400 hover:text-blue-600 hover:bg-blue-50'}`}
                              disabled={!!test.referenceSourceId}
                              onClick={() => { if (!test.referenceSourceId) navigate(ROUTE_CONSTANTS.TestsEdit, { state: test }) }}
                            >
                              <Pencil size={15} />
                            </button>
                          </div>
                        </Tooltip>

                        <Popconfirm
                          title="This action will remove the test from all mapped Practice Tests. Continue?"
                          onConfirm={() => handleDelete(test.id)}
                          okText="Yes"
                          cancelText="No"
                          disabled={test.hasResults || !!test.referenceSourceId}
                        >
                          <Tooltip title={test.hasResults ? "Cannot delete this test because students have already taken it." : test.referenceSourceId ? "Cannot delete a shared test" : "Delete Test"}>
                            <div style={{ display: 'inline-block' }}>
                              <button
                                className={`p-1.5 rounded-xl transition-colors ${test.hasResults || test.referenceSourceId ? 'text-slate-300 cursor-not-allowed' : 'text-slate-400 hover:text-red-600 hover:bg-red-50'}`}
                                disabled={test.hasResults || !!test.referenceSourceId}
                              >
                                <Trash2 size={15} />
                              </button>
                            </div>
                          </Tooltip>
                        </Popconfirm>
                      </div>
                    </div>
                  }
                  isOpen={openTestId === test.id}
                  onToggle={() => toggleTest(test.id, qCount)}
                  disabled={qCount === 0}
                  content={
                    <>
                      <div className="mt-2 flex gap-3 items-end w-[18rem]">
                        <Input
                          placeholder={"Search Questions"}
                          prefix={<Search size={16} />}
                          autoComplete="off"
                          allowClear
                          value={questionSearch}
                          onChange={(e) => setQuestionSearch(e.target.value)}
                        />
                      </div>
                      <Spin spinning={questionsLoading}>
                        {questions.length === 0 && !questionsLoading ? (
                          <div className="min-h-[100px] flex items-center justify-center">
                            <Empty description={debouncedQuestionSearch ? "No question found for your search" : "No question available"} />
                          </div>
                        ) : (
                          <>
                            {questions.map((q) => {
                              const isQuestionOpen = openQuestionId === q.id;
                              return (
                                <AccordionRow
                                  key={q.id}
                                  hideIcon
                                  className="bg-white shadow-sm border border-slate-100 overflow-hidden my-2"
                                  title={
                                    <div className="flex items-center gap-4 p-0 cursor-pointer transition-colors duration-200">
                                      <div className="text-slate-400 transition-transform duration-200">
                                        {isQuestionOpen ? <ChevronDown size={14} /> : <ChevronRight size={14} />}
                                      </div>
                                      <div className="flex-1 grid grid-cols-1 xl:grid-cols-12 gap-4 items-center">
                                        <div className="xl:col-span-4 flex items-center gap-3">
                                          <div className="hidden sm:flex items-center justify-center p-1 rounded bg-slate-100 text-brand-blue shrink-0">
                                            <ClipboardList size={20} />
                                          </div>
                                          <h3 className={`text-sm font-medium text-left leading-relaxed line-clamp-1 ${isQuestionOpen ? "text-brand-blue" : "text-slate-700"}`}>
                                            {q.questionText}
                                          </h3>
                                        </div>
                                        <div className="xl:col-span-8 flex flex-wrap xl:justify-end items-center gap-x-3 gap-y-2 mt-2 xl:mt-0">
                                          {q.subject && (
                                            <span className="text-[11px] px-2 py-0.5 rounded bg-purple-50 text-purple-600 border border-purple-100">
                                              {typeof q.subject === "object" ? (q.subject as any).subjectName : q.subject}
                                            </span>
                                          )}
                                          {q.topic && <span className="text-[11px] px-2 py-0.5 rounded bg-blue-50 text-blue-600 border border-blue-100">{q.topic}</span>}
                                          {q.language && <span className="text-[11px] px-2 py-0.5 rounded bg-amber-50 text-amber-600 border border-amber-100">{q.language}</span>}
                                          {q.updatedAt && (
                                            <div className="hidden 2xl:flex items-center gap-1.5 text-[11px] text-slate-400 min-w-[80px] justify-end">
                                              <Clock size={12} />
                                              <span>{dayjs(q.updatedAt).format("DD-MM-YYYY")}</span>
                                            </div>
                                          )}
                                          <span className={`text-[10px] px-2.5 py-0.5 rounded-full font-semibold border min-w-[60px] text-center ${difficultyColor(q.difficulty === "Easy" ? Difficulty.Easy : q.difficulty === "Medium" ? Difficulty.Medium : Difficulty.Hard)}`}>
                                            {q.difficulty}
                                          </span>
                                        </div>
                                      </div>
                                    </div>
                                  }
                                  isOpen={isQuestionOpen}
                                  onToggle={() => toggleQuestion(q.id)}
                                  content={
                                    <div className="pt-2 pb-6 px-4 sm:px-8 bg-slate-50 border-t border-slate-100">
                                      <div className="mb-4 flex flex-col items-start gap-2">
                                        <div className="text-sm font-medium text-left leading-relaxed text-slate-700 text-wrap">{q.questionText}</div>
                                        {q.questionImage && <img src={q.questionImage} alt="Question" className="h-[5rem] object-contain rounded-md mt-2" />}
                                      </div>
                                      <div className="space-y-3">
                                        {q.options?.map((option: any, idx: number) => {
                                          const isCorrect = idx === q.correctAnswer;
                                          let optionClass = "w-full text-left p-3 rounded-xl border text-sm font-medium flex justify-between items-center transition-all duration-200 cursor-default ";
                                          if (isCorrect) optionClass += "bg-green-50 border-green-500 text-green-800 shadow-sm ring-1 ring-green-500/20";
                                          else optionClass += "bg-white border-slate-200 text-slate-500 opacity-80";
                                          return (
                                            <div key={idx} className={optionClass}>
                                              <div className="flex items-center gap-3">
                                                <span className={`flex items-center justify-center w-6 h-6 rounded-full text-xs font-bold border ${isCorrect ? "border-green-600 bg-green-100 text-green-700" : "border-slate-300 bg-slate-50 text-slate-500"}`}>
                                                  {String.fromCharCode(65 + idx)}
                                                </span>
                                                {option.option !== "" && <span>{option.option}</span>}
                                                {option.optionImage && <img src={option.optionImage} alt="Option" className="h-[5rem] w-auto object-contain rounded-xl ml-5" />}
                                              </div>
                                              {isCorrect && <CheckCircle className="text-green-600" size={18} />}
                                            </div>
                                          );
                                        })}
                                      </div>
                                      {(q.explanation || q.explanationImage) && (
                                        <div className="mt-6 space-y-4">
                                          <div className="p-4 rounded-xl border bg-blue-50 border-blue-100">
                                            <h4 className="text-xs font-bold uppercase tracking-wider mb-2 flex items-center gap-2 text-blue-700">
                                              <Info size={14} /> Explanation
                                            </h4>
                                            {q.explanation && <p className="text-sm text-slate-700 leading-relaxed font-medium whitespace-pre-line">{q.explanation}</p>}
                                            {q.explanationImage && <img src={q.explanationImage} alt="Explanation" className="h-[5rem] w-auto object-contain rounded-xl mt-3" />}
                                          </div>
                                        </div>
                                      )}
                                    </div>
                                  }
                                />
                              );
                            })}
                            <div className="flex justify-end pb-2 mt-4">
                              <Pagination
                                current={questionPagination.page}
                                total={questionPagination.total}
                                pageSize={questionPagination.limit}
                                onChange={(p, pageSize) => {
                                  setQuestionPagination({
                                    ...questionPagination,
                                    page: p,
                                    limit: pageSize,
                                  });
                                  getQuestions(p, pageSize, openTestId, questionSearch, questionPagination.total);
                                }}
                                showSizeChanger
                              />
                            </div>
                          </>
                        )}
                      </Spin>
                    </>
                  }
                />
              );
            })}

            <div className="flex justify-end pb-2 mt-4">
              <Pagination
                current={pagination.page}
                total={pagination.total}
                pageSize={pagination.limit}
                onChange={(p, pageSize) => {
                  setPagination({
                    ...pagination,
                    page: p,
                    limit: pageSize,
                  });
                  fetchTests(p, pageSize);
                }}
                showSizeChanger
              />
            </div>
          </div>
        )}
      </Spin>
    </div>
  );
};
