import dayjs from "dayjs";
import toast from "react-hot-toast";
import type { ColumnsType, TableProps } from "antd/es/table";
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 { getAxiosErrorMessage } from "@/utils/index.utils";
import { Search, ClipboardList, Loader2, Download, Share2 } from "lucide-react";
import { Button, Card, DatePicker, Input, Pagination, Select, Table, Tag, Typography, message } from "antd";

const { Text } = Typography;

interface IReport {
  id: string;
  testTitle: string;
  studentName: string;
  email: string;
  createdAt: string;
  totalQuestions: number;
  obtainedMarks: number;
  totalMarks: number;
  examName: string;
  examType: string;
  subjectName: string | null;
  percentage: string;
}

const filterInitial = {
  search: "",
  examId: undefined as string | undefined,
  examType: undefined as string | undefined,
  subjectId: undefined as string | undefined,
  startDate: undefined as string | undefined,
  endDate: undefined as string | undefined,
};

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

interface ISortState {
  field: "title" | "date" | "score" | "percentage" | undefined;
  order: "asc" | "desc" | undefined;
}

const ReportsScoreTab: React.FC = () => {
  const [reports, setReports] = useState<IReport[]>([]);
  const [loading, setLoading] = useState(false);
  const [downloading, setDownloading] = useState(false);
  const [pagination, setPagination] = useState(paginationInitial);
  const [filters, setFilters] = useState(filterInitial);
  
  // No default sort highlighted — backend already returns date desc by default
  const [sort, setSort] = useState<ISortState>({ field: undefined, order: undefined });

  const debouncedSearch = useDebounce(filters.search, 600);
  const [exams, setExams] = useState<{ id: string; examName: string }[]>([]);
  const [examSearch, setExamSearch] = useState("");
  const debouncedExamSearch = useDebounce(examSearch, 500);
  const [examPage, setExamPage] = useState(1);
  const [hasMoreExams, setHasMoreExams] = useState(true);
  const [loadingExams, setLoadingExams] = useState(false);
  const [subjects, setSubjects] = useState<{ id: string; subjectName: string }[]>([]);
  const [subjectSearch, setSubjectSearch] = useState("");
  const debouncedSubjectSearch = useDebounce(subjectSearch, 500);
  const [subjectPage, setSubjectPage] = useState(1);
  const [hasMoreSubjects, setHasMoreSubjects] = useState(true);
  const [loadingSubjects, setLoadingSubjects] = useState(false);

  const fetchReports = async (page = 1, limit = 10, filterData = filters, sortData = sort) => {
    setLoading(true);
    try {
      const res = await API_Instance.get(API_Constants.reports, {
        params: {
          page,
          limit,
          search: filterData.search,
          examId: filterData.examId,
          examType: filterData.examType,
          subjectId: filterData.examType === "PRACTICE" ? filterData.subjectId : undefined,
          startDate: filterData.startDate,
          endDate: filterData.endDate,
          sortBy: sortData.field,
          sortOrder: sortData.order,
        },
      });
      setReports(res.data.data);
      setPagination(res.data.meta);
    } catch (error) {
      toast.error(getAxiosErrorMessage(error));
    } finally {
      setLoading(false);
    }
  };

  const fetchExamsList = async (search = "", page = 1) => {
    setLoadingExams(true);
    try {
      const res = await API_Instance.get(API_Constants.exams, {
        params: { search, page, limit: 10, isPublished: true }
      });
      const newExams = res.data.data || [];
      setExams((prev) => (page === 1 ? newExams : [...prev, ...newExams]));
      setHasMoreExams(newExams.length === 10);
    } catch (e) {
      console.error("Failed to parse master exams options list", e);
    } finally {
      setLoadingExams(false);
    }
  };

  const fetchSubjectsList = async (search = "", page = 1) => {
    setLoadingSubjects(true);
    try {
      const res = await API_Instance.get("/subjects", {
        params: { search, page, limit: 10, isPublished: true, includeShared: true }
      });
      const newSubjects = res.data.data || [];
      setSubjects((prev) => (page === 1 ? newSubjects : [...prev, ...newSubjects]));
      setHasMoreSubjects(newSubjects.length === 10);
    } catch (e) {
      console.error("Failed to parse master subjects options list", e);
    } finally {
      setLoadingSubjects(false);
    }
  };

  const handleDownloadPDF = async () => {
    if (reports.length === 0) {
      toast.error("No data available to export.");
      return;
    }
    setDownloading(true);
    try {
      const response = await API_Instance.get(`${API_Constants.reports}/score-report-pdf`, {
        params: {
          search: filters.search,
          examId: filters.examId,
          examType: filters.examType,
          subjectId: filters.examType === "PRACTICE" ? filters.subjectId : undefined,
          startDate: filters.startDate,
          endDate: filters.endDate,
          sortBy: sort.field,
          sortOrder: sort.order,
        },
        responseType: "blob",
      });

      const blobUrl = window.URL.createObjectURL(new Blob([response.data], { type: "application/pdf" }));
      const link = document.createElement("a");
      link.href = blobUrl;
      link.setAttribute("download", `Reports_Scores_Summary_${dayjs().format("DD-MM-YYYY")}.pdf`);

      document.body.appendChild(link);
      link.click();

      link.remove();
      window.URL.revokeObjectURL(blobUrl);
      message.success("PDF report layout downloaded successfully!");
    } catch (error) {
      console.error("PDF generation layout runtime failure:", error);
      toast.error("Failed to compile structural PDF.");
    } finally {
      setDownloading(false);
    }
  };

  useEffect(() => {
    setExamPage(1);
    fetchExamsList(debouncedExamSearch, 1);
  }, [debouncedExamSearch]);

  useEffect(() => {
    if (examPage > 1) {
      fetchExamsList(debouncedExamSearch, examPage);
    }
  }, [examPage]);

  useEffect(() => {
    if (filters.examType === "PRACTICE") {
      setSubjectPage(1);
      fetchSubjectsList(debouncedSubjectSearch, 1);
    }
  }, [debouncedSubjectSearch, filters.examType]);

  useEffect(() => {
    if (subjectPage > 1 && filters.examType === "PRACTICE") {
      fetchSubjectsList(debouncedSubjectSearch, subjectPage);
    }
  }, [subjectPage]);

  useEffect(() => {
    const updatedFilters = {
      ...filters,
      search: debouncedSearch
    };
    fetchReports(1, pagination.limit, updatedFilters, sort);
  }, [
    debouncedSearch,
    filters.examId,
    filters.examType,
    filters.subjectId,
    filters.startDate,
    filters.endDate,
    sort.field,
    sort.order
  ]);

  const handleTableChange: TableProps<IReport>["onChange"] = (_pagination, _filters, sorter: any) => {
    if (sorter && sorter.field && sorter.order) {
      let backendField = sorter.field;
      if (sorter.field === "testTitle") backendField = "title";
      if (sorter.field === "createdAt") backendField = "date";
      if (sorter.field === "obtainedMarks") backendField = "score";

      setSort({
        field: backendField,
        order: sorter.order === "ascend" ? "asc" : "desc",
      });
    } else {
      setSort({ field: undefined, order: undefined });
    }
    setPagination((prev) => ({ ...prev, page: 1 }));
  };

  const columns: ColumnsType<IReport> = [
    {
      title: "Student Name",
      dataIndex: "studentName",
      key: "studentName",
      render: (text, record) => (
        <div className="font-semibold text-slate-700">
          <span>{text}</span>
          <span className="text-slate-400 font-light text-sm block">{record.email}</span>
        </div>
      ),
    },
    {
      title: "Exam Name",
      dataIndex: "examName",
      key: "examName",
      render: (text) => <span className="text-slate-600">{text}</span>,
    },
    {
      title: "Test Type",
      dataIndex: "examType",
      key: "examType",
      render: (text, record) => {
        let tagColor = "blue";
        if (text === "OQP" || text === "PYQ") tagColor = "green";
        if (text === "MOCK") tagColor = "purple";

        return (
          <div className="flex flex-col gap-1.5 items-start">
            <Tag color={tagColor} className="rounded-full px-3 font-medium m-0">
              {text === "MOCK" ? "MOCK TEST" : (text === "OQP" ? "PYQ" : text)}
            </Tag>
            {text === "PRACTICE" && record.subjectName && (
              <Tag
                color="orange"
                className="!uppercase rounded-full font-medium px-3 m-0 border border-orange-100 bg-orange-50"
              >
                {record.subjectName}
              </Tag>
            )}
          </div>
        );
      },
    },
    {
      title: "Test Title",
      dataIndex: "testTitle",
      key: "testTitle",
      sorter: true,
      sortOrder: sort.field === "title" ? (sort.order === "asc" ? "ascend" : "descend") : undefined,
      render: (text) => <span className="text-slate-600">{text}</span>,
    },
    {
      title: "Date",
      dataIndex: "createdAt",
      key: "createdAt",
      sorter: true,
      sortOrder: sort.field === "date" ? (sort.order === "asc" ? "ascend" : "descend") : undefined,
      render: (date) => (
        <span className="text-xs text-slate-500">
          {dayjs(date).format("DD/MM/YYYY, hh:mm A")}
        </span>
      ),
    },
    {
      title: "Score",
      dataIndex: "obtainedMarks",
      key: "obtainedMarks",
      sorter: true,
      sortOrder: sort.field === "score" ? (sort.order === "asc" ? "ascend" : "descend") : undefined,
      render: (_, record) => (
        <div className="flex items-center gap-1 font-medium">
          <span className="text-blue-600">{record.obtainedMarks}</span>
          <span className="text-slate-400">/</span>
          <span className="text-slate-600">{record.totalMarks}</span>
        </div>
      ),
    },
    {
      title: "Percentage",
      dataIndex: "percentage",
      key: "percentage",
      sorter: true,
      sortOrder: sort.field === "percentage" ? (sort.order === "asc" ? "ascend" : "descend") : undefined,
      render: (percentage) => {
        const numericValue = parseFloat(percentage);
        const isPass = !isNaN(numericValue) && numericValue >= 40;
        return (
          <Tag color={isPass ? "success" : "error"} className="font-semibold rounded-full px-3">
            {percentage}
          </Tag>
        );
      },
    },
  ];

  return (
    <div className="flex flex-col gap-4 px-4 py-6">
      <div className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4">
        <div>
          <h2 className="text-2xl font-bold text-slate-800 flex items-center gap-2">
            <ClipboardList className="text-blue-600" /> Reports & Scores
          </h2>
          <p className="text-slate-500 text-sm mt-1">
            View all students performance and exam results.
          </p>
        </div>
        <Button
          type="primary"
          disabled={downloading}
          onClick={handleDownloadPDF}
          className="bg-blue-600 hover:bg-blue-700 hover:text-white flex items-center gap-2 rounded-lg font-medium"
          icon={downloading ? <Loader2 size={16} className="animate-spin" /> : <Download size={16} />}
        >
          {downloading ? "Generating PDF..." : "Export PDF"}
        </Button>
      </div>

      <Card className="shadow-sm border border-slate-200 rounded-xl bg-white">
        <div className={`grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 ${filters.examType === "PRACTICE" ? "xl:grid-cols-5" : "xl:grid-cols-4"} gap-4 mb-6 p-4 bg-slate-50 rounded-xl border border-slate-100`}>
          <div className="w-full">
            <Input
              placeholder="Search student, email..."
              prefix={<Search size={16} className="text-slate-400" />}
              allowClear
              value={filters.search}
              onChange={(e) => setFilters({ ...filters, search: e.target.value })}
              className="w-full"
            />
          </div>

          <Select
            placeholder="Select Exam"
            className="w-full"
            allowClear
            showSearch
            filterOption={false}
            onSearch={(val) => setExamSearch(val)}
            onPopupScroll={(e) => {
              const target = e.target as HTMLElement;
              if (
                Math.ceil(target.scrollTop + target.offsetHeight) >= target.scrollHeight &&
                hasMoreExams &&
                !loadingExams
              ) {
                setExamPage((prev) => prev + 1);
              }
            }}
            value={filters.examId}
            onChange={(val) => setFilters({ ...filters, examId: val })}
            options={exams.map((e) => ({ label: e.examName, value: e.id }))}
            loading={loadingExams}
          />

          <Select
            placeholder="Test Type"
            className="w-full"
            allowClear
            value={filters.examType}
            onChange={(val) => setFilters({ ...filters, examType: val, subjectId: undefined })}
            options={[
              { label: "Practice Test", value: "PRACTICE" },
              { label: "PYQ Test", value: "OQP" },
              { label: "Mock Test", value: "MOCK" },
            ]}
          />

          {filters.examType === "PRACTICE" && (
            <Select
              placeholder="Select Subject"
              className="w-full animate-fade-in"
              allowClear
              showSearch
              filterOption={false}
              onSearch={(val) => setSubjectSearch(val)}
              onPopupScroll={(e) => {
                const target = e.target as HTMLElement;
                if (
                  Math.ceil(target.scrollTop + target.offsetHeight) >= target.scrollHeight &&
                  hasMoreSubjects &&
                  !loadingSubjects
                ) {
                  setSubjectPage((prev) => prev + 1);
                }
              }}
              value={filters.subjectId}
              onChange={(val) => setFilters({ ...filters, subjectId: val })}
              optionLabelProp="name"
              options={subjects.map((s: any) => ({
                name: s.subjectName,
                label: (
                  <div className="flex items-center gap-2">
                    {s.isShared && (
                      // <span title={`Shared by ${s.sharedInstitutionName || "Institution"}`}>
                      //   <Share2 size={14} className="text-purple-500 flex-shrink-0" />
                      // </span>
                       <span title={`Shared by Exam Infra`}>
                        <Share2 size={14} className="text-purple-500 flex-shrink-0" />
                      </span>
                    )}
                    <span className="font-medium text-slate-700 truncate">{s.subjectName}</span>
                  </div>
                ),
                value: s.id,
              }))}
              loading={loadingSubjects}
            />
          )}

          <div className="sm:col-span-1 md:col-span-2 xl:col-span-1 flex items-center justify-between gap-2 border border-slate-300 rounded-lg px-2 bg-white h-[32px] w-full">
            <DatePicker
              placeholder="From Date"
              format="DD/MM/YYYY"
              className="border-none p-0 shadow-none flex-1 text-xs"
              value={filters.startDate ? dayjs(filters.startDate) : null}
              disabledDate={(current) => {
                const isFuture = current && current > dayjs().endOf('day');
                const isAfterEnd = filters.endDate
                  ? current && current > dayjs(filters.endDate).endOf('day')
                  : false;
                return isFuture || isAfterEnd;
              }}
              onChange={(date) => setFilters({ ...filters, startDate: date ? date.format("YYYY-MM-DD") : undefined })}
            />
            <span className="text-slate-300 text-xs px-1">to</span>
            <DatePicker
              placeholder="To Date"
              format="DD/MM/YYYY"
              className="border-none p-0 shadow-none flex-1 text-xs"
              value={filters.endDate ? dayjs(filters.endDate) : null}
              disabledDate={(current) => {
                const isFuture = current && current > dayjs().endOf('day');
                const isBeforeStart = filters.startDate
                  ? current && current < dayjs(filters.startDate).startOf('day')
                  : false;
                return isFuture || isBeforeStart;
              }}
              onChange={(date) => setFilters({ ...filters, endDate: date ? date.format("YYYY-MM-DD") : undefined })}
            />
          </div>
        </div>

        <div className="flex flex-row justify-between items-center mb-4 px-1">
          <Button
            type="link"
            size="small"
            className="text-slate-500 hover:text-blue-600 flex items-center gap-1 font-medium p-0"
            onClick={() => {
              setFilters(filterInitial);
              setSort({ field: undefined, order: undefined });
            }}
          >
            Clear All Filters
          </Button>

          <div className="text-slate-500 text-sm bg-slate-100 px-3 py-1 rounded-md border border-slate-200">
            Total Records: <span className="font-bold text-slate-800">{pagination.total}</span>
          </div>
        </div>

        <Table
          columns={columns}
          dataSource={reports}
          loading={loading}
          rowKey="id"
          pagination={false}
          scroll={{ x: 800 }}
          onChange={handleTableChange}
          className="border border-slate-100 rounded-lg overflow-hidden"
        />

        <div className="flex justify-end mt-4">
          <Pagination
            current={pagination.page}
            total={pagination.total}
            pageSize={pagination.limit}
            onChange={(page, pageSize) => {
              setPagination((prev) => ({ ...prev, page, limit: pageSize }));
              fetchReports(page, pageSize, filters, sort);
            }}
            showSizeChanger
            showTotal={(total) => `Total ${total} items`}
          />
        </div>
      </Card>
    </div>
  );
};

export default ReportsScoreTab;