import toast from "react-hot-toast";
import type { TableProps } from "antd";
import { useNavigate } from "react-router-dom";
import { useDebounce } from "@/hooks/useDebounce";
import { API_Instance } from "@/api/axios.instance";
import API_Constants from "@/constants/api.constants";
import ROUTE_CONSTANTS from "@/constants/route.constants";
import { getAxiosErrorMessage } from "@/utils/index.utils";
import React, { useState, useEffect, useCallback, useMemo } from "react";
import { Card, Skeleton, Empty, Select, Tabs, Table, Tag, Pagination, Input } from "antd";
import { TrendingUp, Calendar, FileText, Users, ArrowUpDown, Filter, BookOpen, Search, ChartNoAxesColumnDecreasing, ChartNoAxesColumnIncreasing } from "lucide-react";
import { ResponsiveContainer, LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend } from "recharts";

interface IGraphPoint {
    week: string;
    percentage: number | null;
}

interface IStudentRow {
    studentId: string;
    studentName: string;
    email?: string;
    assignedExam: string;
    weeks: Record<string, number | null>;
    overallAverage: number;
    hasAttended: boolean;
}

const formatWeekLabel = (label: string): string => {
    if (!label) return "";
    const formattedLabel = label.replace(/From\s+/i, "");
    const parts = formattedLabel.split(/\s+to\s+/i);
    if (parts.length !== 2) return label;

    const formatDate = (dateStr: string, includeMonth: boolean) => {
        const date = new Date(dateStr);
        if (isNaN(date.getTime())) return dateStr;
        return date.toLocaleDateString("en-US", {
            month: includeMonth ? "short" : undefined,
            day: "numeric",
        });
    };

    const firstDate = new Date(parts[0]);
    const secondDate = new Date(parts[1]);
    if (isNaN(firstDate.getTime()) || isNaN(secondDate.getTime())) return label;

    const sameMonthAndYear =
        firstDate.getFullYear() === secondDate.getFullYear() &&
        firstDate.getMonth() === secondDate.getMonth();

    const firstFormatted = formatDate(parts[0], true);
    const secondFormatted = sameMonthAndYear ? formatDate(parts[1], false) : formatDate(parts[1], true);

    return `${firstFormatted} - ${secondFormatted}`;
};

const ChartTooltip = ({ active, payload, label }: any) => {
    if (!active || !payload?.[0]) return null;
    const data = payload[0].payload;
    const formattedLabel = formatWeekLabel(label);

    return (
        <div className="bg-white rounded-xl p-3 shadow-xl border border-slate-100 min-w-[160px]">
            <p className="font-bold text-slate-700 text-xs mb-1.5 flex items-center gap-1">
                <Calendar size={12} className="text-slate-400" />
                {formattedLabel}
            </p>
            {!data.hasSubmissions ? (
                <p className="text-slate-400 text-xs italic">No Submissions</p>
            ) : (
                <p className="text-brand-blue text-xs font-medium flex items-center gap-1.5">
                    <span className="w-2 h-2 rounded-full bg-brand-blue inline-block" />
                    Percentage: <span className="font-bold text-slate-800">{data.percentage}%</span>
                </p>
            )}
        </div>
    );
};

const PercentageCell = ({ value }: { value: number | null }) => {
    if (value === null || value === undefined) {
        return <span className="text-slate-300 text-xs font-medium">—</span>;
    }
    const color =
        value >= 75 ? "success" :
            value >= 50 ? "processing" :
                value >= 25 ? "warning" : "error";

    return (
        <Tag
            color={color}
            className="rounded-full text-xs font-semibold min-w-[48px] text-center"
        >
            {value}%
        </Tag>
    );
};

const PyqTestReport: React.FC = () => {
    const navigate = useNavigate();
    const [graphData, setGraphData] = useState<IGraphPoint[]>([]);
    const [chartLoading, setChartLoading] = useState(false);
    const [activeTab, setActiveTab] = useState("overall");

    const [tableData, setTableData] = useState<IStudentRow[]>([]);
    const [tableColumns, setTableColumns] = useState<string[]>([]);
    const [tableLoading, setTableLoading] = useState(false);
    const [tableExamName, setTableExamName] = useState<string>("All Exams");
    const [sortBy, setSortBy] = useState<"studentName" | "overallAverage">("studentName");
    const [sortOrder, setSortOrder] = useState<"asc" | "desc">("asc");
    const [tablePage, setTablePage] = useState(1);
    const [tableLimit, setTableLimit] = useState(10);
    const [tableTotal, setTableTotal] = useState(0);

    const [studentSearch, setStudentSearch] = useState("");
    const debouncedStudentSearch = useDebounce(studentSearch, 500);

    const [statusFilter, setStatusFilter] = useState<"all" | "attended" | "notattended">("all");

    const [counts, setCounts] = useState({ all: 0, attended: 0, notattended: 0 });

    const [exams, setExams] = useState<{ id: string; examName: string }[]>([]);
    const [selectedExamId, setSelectedExamId] = useState<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 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);
            if (page === 1 && newExams.length > 0 && !selectedExamId) {
                setSelectedExamId(newExams[0].id);
            }
        } catch (e) {
            console.error("Failed to load exams list", e);
        } finally {
            setLoadingExams(false);
        }
    };

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

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

    const fetchGraphData = useCallback(async () => {
        setChartLoading(true);
        try {
            const res = await API_Instance.get(`${API_Constants.reports}/overall/pyq-test-weekly`, {
                params: { examId: selectedExamId || undefined }
            });
            setGraphData(res.data?.data?.graphData || []);
        } catch (e) {
            toast.error(getAxiosErrorMessage(e));
        } finally {
            setChartLoading(false);
        }
    }, [selectedExamId]);

    const fetchCategoryCounts = useCallback(async () => {
        if (!selectedExamId) { setCounts({ all: 0, attended: 0, notattended: 0 }); return; }
        try {
            const res = await API_Instance.get(`${API_Constants.reports}/overall/pyq-test-student-weekly`, {
                params: {
                    examId: selectedExamId || undefined,
                    statusFilter: "all",
                    limit: 2000
                }
            });
            const students: IStudentRow[] = res.data?.data || [];
            const attendedCount = students.filter(s => s.hasAttended).length;
            setCounts({
                all: students.length,
                attended: attendedCount,
                notattended: students.length - attendedCount
            });
        } catch (e) {
            console.error("Failed to fetch student counts", e);
        }
    }, [selectedExamId]);

    const fetchTableData = useCallback(async (page = tablePage, limit = tableLimit, filter = statusFilter, search = debouncedStudentSearch) => {
        if (!selectedExamId) { setTableData([]); setTableColumns([]); setTableTotal(0); return; }
        setTableLoading(true);
        try {
            const res = await API_Instance.get(`${API_Constants.reports}/overall/pyq-test-student-weekly`, {
                params: {
                    examId: selectedExamId || undefined,
                    sortBy,
                    sortOrder,
                    statusFilter: filter,
                    search: search || undefined,
                    page,
                    limit
                }
            });
            setTableData(res.data?.data || []);
            setTableExamName(res.data?.examName || "All Exams");
            setTableTotal(res.data?.pagination?.total || 0);
            const rawCols: string[] = res.data?.columns || [];
            setTableColumns(rawCols.filter((c: string) => c !== "Student Name" && c !== "Overall Average"));
        } catch (e) {
            toast.error(getAxiosErrorMessage(e));
        } finally {
            setLoadingExams(false);
            setTableLoading(false);
        }
    }, [selectedExamId, sortBy, sortOrder, statusFilter, tablePage, tableLimit, debouncedStudentSearch]);

    useEffect(() => {
        if (activeTab === "overall") {
            fetchGraphData();
        }
    }, [fetchGraphData, activeTab]);

    useEffect(() => {
        if (activeTab === "students") {
            setTablePage(1);
            if (!selectedExamId) {
                setTableData([]);
                setTableColumns([]);
                setTableTotal(0);
                setCounts({ all: 0, attended: 0, notattended: 0 });
                return;
            }
            fetchCategoryCounts();
            fetchTableData(1, tableLimit, statusFilter, debouncedStudentSearch);
        }
    }, [selectedExamId, sortBy, sortOrder, statusFilter, activeTab, debouncedStudentSearch]);

    const processedGraphData = useMemo(() => {
        return graphData.map((item) => ({
            ...item,
            displayPercentage: item.percentage ?? 0,
            hasSubmissions: item.percentage !== null && item.percentage !== undefined,
        }));
    }, [graphData]);

    const selectedExamName = useMemo(() => {
        const found = exams.find((e) => e.id === selectedExamId);
        return found ? found.examName : "";
    }, [exams, selectedExamId]);

    const examOptions = useMemo(() => {
        return exams.map((e) => ({ label: e.examName, value: e.id }));
    }, [exams]);

    const studentExamOptions = useMemo(() => {
        return exams.map((e) => ({ label: e.examName, value: e.id }));
    }, [exams]);

    const antdColumns = useMemo((): TableProps<IStudentRow>["columns"] => {
        const staticFirst = {
            title: (
                <button
                    className="flex items-center gap-1 font-semibold text-slate-700 text-sm cursor-pointer group select-none"
                    onClick={() => {
                        setSortBy("studentName");
                        setSortOrder((prev) => (sortBy === "studentName" && prev === "asc" ? "desc" : "asc"));
                    }}
                >
                    Student Details
                    <ArrowUpDown
                        size={13}
                        className={`transition-colors ${sortBy === "studentName" ? "text-blue-500" : "text-slate-400 group-hover:text-blue-400"}`}
                    />
                </button>
            ),
            dataIndex: "studentName",
            key: "studentName",
            fixed: "left" as const,
            width: 210,
            render: (name: string, record: IStudentRow) => (
                <div className="flex flex-col gap-0.5">
                    <span
                        className="font-semibold text-blue-600 hover:text-blue-800 hover:underline text-sm cursor-pointer"
                        onClick={() => navigate(ROUTE_CONSTANTS.StudentPerformance.replace(":studentId", record.studentId))}
                    >
                        {name}
                    </span>
                    {record.email && (
                        <span className="text-xs text-slate-400 font-normal">{record.email}</span>
                    )}
                </div>
            )
        };

        const weekCols = tableColumns.map((weekLabel) => ({
            title: (
                <span className="text-xs text-slate-500 font-medium whitespace-nowrap">
                    {formatWeekLabel(weekLabel)}
                </span>
            ),
            key: weekLabel,
            width: 110,
            align: "center" as const,
            render: (_: any, record: IStudentRow) => (
                <PercentageCell value={record.weeks[weekLabel] ?? null} />
            )
        }));

        const staticLast = {
            title: (
                <button
                    className="flex items-center gap-1 font-semibold text-slate-700 text-sm cursor-pointer group select-none"
                    onClick={() => {
                        setSortBy("overallAverage");
                        setSortOrder((prev) => (sortBy === "overallAverage" && prev === "desc" ? "asc" : "desc"));
                    }}
                >
                    Overall Avg
                    <ArrowUpDown
                        size={13}
                        className={`transition-colors ${sortBy === "overallAverage" ? "text-blue-500" : "text-slate-400 group-hover:text-blue-400"}`}
                    />
                </button>
            ),
            dataIndex: "overallAverage",
            key: "overallAverage",
            fixed: "left" as const,
            width: 130,
            align: "center" as const,
            render: (val: number, record: IStudentRow) => (
                <Tag
                    color={!record.hasAttended ? "default" : (val >= 75 ? "success" : val >= 50 ? "processing" : val >= 25 ? "warning" : "error")}
                    className="rounded-full text-xs font-bold min-w-[52px] text-center"
                >
                    {record.hasAttended ? `${val}%` : "—"}
                </Tag>
            )
        };

        return [staticFirst, staticLast, ...weekCols];
    }, [tableColumns, sortBy, sortOrder, tableExamName]);

    const examSelectProps = {
        className: "w-full",
        showSearch: true,
        filterOption: false as const,
        placeholder: "Select Exam",
        onSearch: (val: string) => setExamSearch(val),
        onDropdownVisibleChange: (open: boolean) => { if (!open) setExamSearch(""); },
        onPopupScroll: (e: React.UIEvent<HTMLElement>) => {
            const target = e.target as HTMLElement;
            const atBottom = Math.ceil(target.scrollTop + target.clientHeight) >= target.scrollHeight - 15;
            if (atBottom && hasMoreExams && !loadingExams) {
                setExamPage((prev) => prev + 1);
            }
        },
        value: selectedExamId,
        onChange: (val: string) => setSelectedExamId(val || ""),
        options: examOptions,
        loading: loadingExams
    };

    const studentExamSelectProps = {
        className: "w-full",
        showSearch: true,
        filterOption: false as const,
        placeholder: "Select Exam",
        onSearch: (val: string) => setExamSearch(val),
        onDropdownVisibleChange: (open: boolean) => { if (!open) setExamSearch(""); },
        onPopupScroll: (e: React.UIEvent<HTMLElement>) => {
            const target = e.target as HTMLElement;
            const atBottom = Math.ceil(target.scrollTop + target.clientHeight) >= target.scrollHeight - 15;
            if (atBottom && hasMoreExams && !loadingExams) {
                setExamPage((prev) => prev + 1);
            }
        },
        value: selectedExamId || undefined,
        onChange: (val: string) => setSelectedExamId(val || ""),
        options: studentExamOptions,
        loading: loadingExams
    };

    return (
        <div className="flex flex-col gap-6 p-4">

            <div>
                <h2 className="text-2xl font-bold text-slate-800">PYQ Test Report</h2>
                <p className="text-slate-500 text-sm mt-1">
                    Analyze previous year question papers metrics and student performance trend charts.
                </p>
            </div>

            <Tabs
                activeKey={activeTab}
                onChange={(key) => setActiveTab(key)}
                className="custom-report-tabs"
                items={[
                    {
                        key: "overall",
                        label: (
                            <span className="flex items-center gap-2 text-sm font-medium px-1 py-0.5">
                                <FileText size={16} />
                                Overall Performance Trend
                            </span>
                        ),
                        children: (
                            <div className="flex flex-col gap-6 mt-2">
                                <div className="flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 bg-white p-4 rounded-xl border border-slate-200/80 shadow-sm w-full">
                                    <div className="flex flex-col">
                                        <span className="text-[10px] font-bold uppercase tracking-wider text-slate-400">Selected Exam</span>
                                        <span className="text-base font-bold text-[#1677ff] mt-0.5">
                                            {selectedExamName || "No Exam Selected"}
                                        </span>
                                    </div>
                                    <div className="flex items-center gap-3 w-full sm:w-auto justify-end">
                                        <span className="font-semibold text-sm text-slate-600 whitespace-nowrap">Select Exam:</span>
                                        <div className="w-full sm:w-80">
                                            <Select {...examSelectProps} />
                                        </div>
                                    </div>
                                </div>

                                <Card className="shadow-sm border border-slate-200/80 rounded-2xl w-full">
                                    <div className="flex flex-col sm:flex-row justify-between items-start sm:items-center mb-6 gap-4">
                                        <div>
                                            <h3 className="text-lg font-bold text-slate-800 flex items-center gap-2">
                                                <TrendingUp size={18} className="text-[#1677ff]" />
                                                Exam-Wise Weekly Performance Trend ( All Students )
                                            </h3>
                                            <p className="text-xs font-medium text-slate-400 mt-0.5">
                                                Overall PYQ Examination Statistics • Last 90 Days
                                            </p>
                                            {selectedExamName && (
                                                <p className="text-xs font-semibold text-indigo-600 mt-2 uppercase tracking-wide bg-indigo-50 px-2.5 py-1 rounded-md w-fit">
                                                    Exam: {selectedExamName}
                                                </p>
                                            )}
                                        </div>
                                    </div>

                                    {chartLoading ? (
                                        <div className="p-4">
                                            <Skeleton active paragraph={{ rows: 6 }} />
                                        </div>
                                    ) : processedGraphData.length === 0 ? (
                                        <div className="h-64 flex items-center justify-center">
                                            <Empty description="No PYQ test performance data available" />
                                        </div>
                                    ) : (
                                        <ResponsiveContainer width="100%" height={330}>
                                            <LineChart data={processedGraphData} margin={{ top: 25, right: 15, left: 15, bottom: 40 }}>
                                                <CartesianGrid strokeDasharray="3 3" vertical={false} stroke="#f1f5f9" />
                                                <XAxis
                                                    dataKey="week"
                                                    tickFormatter={formatWeekLabel}
                                                    tick={{ fill: "#94a3b8", fontSize: 11, fontWeight: 500 }}
                                                    axisLine={false}
                                                    tickLine={false}
                                                    dy={10}
                                                    label={{ value: "Weeks", position: "bottom", offset: 25, fill: "#64748b", fontSize: 12, fontWeight: 600 }}
                                                />
                                                <YAxis
                                                    tick={{ fill: "#94a3b8", fontSize: 11 }}
                                                    axisLine={false}
                                                    tickLine={false}
                                                    domain={[0, 100]}
                                                    ticks={[0, 25, 50, 75, 100]}
                                                    tickFormatter={(v) => `${v}%`}
                                                    label={{ value: "Percentage", angle: -90, position: "left", offset: 10, fill: "#64748b", style: { textAnchor: "middle", fontSize: 12, fontWeight: 600 } }}
                                                />
                                                <Tooltip content={<ChartTooltip />} cursor={{ stroke: "#f1f5f9", strokeWidth: 2 }} />
                                                <Line
                                                    type="monotone"
                                                    dataKey="displayPercentage"
                                                    name="Average Score %"
                                                    stroke="#1677ff"
                                                    strokeWidth={3}
                                                    connectNulls
                                                    dot={(props: any) => {
                                                        const { cx, cy, payload } = props;
                                                        const hasSubmissions = payload?.hasSubmissions;
                                                        const value = payload?.displayPercentage;

                                                        if (!hasSubmissions || value === null || value === undefined) {
                                                            return (
                                                                <circle
                                                                    key={props.key}
                                                                    cx={cx}
                                                                    cy={cy}
                                                                    r={3}
                                                                    fill="#cbd5e1"
                                                                    stroke="none"
                                                                />
                                                            );
                                                        }

                                                        return (
                                                            <g key={props.key}>
                                                                <circle
                                                                    cx={cx}
                                                                    cy={cy}
                                                                    r={4}
                                                                    fill="#1677ff"
                                                                    stroke="#fff"
                                                                    strokeWidth={2}
                                                                />
                                                                <text
                                                                    x={cx}
                                                                    y={cy - 10}
                                                                    textAnchor="middle"
                                                                    fill="#1677ff"
                                                                    fontSize={10}
                                                                    fontWeight={700}
                                                                >
                                                                    {`${value}%`}
                                                                </text>
                                                            </g>
                                                        );
                                                    }}
                                                    activeDot={{ r: 6, strokeWidth: 0 }}
                                                />
                                            </LineChart>
                                        </ResponsiveContainer>
                                    )}
                                </Card>
                            </div>
                        )
                    },
                    {
                        key: "students",
                        label: (
                            <span className="flex items-center gap-2 text-sm font-medium px-1 py-0.5">
                                <Users size={16} />
                                Students Wise Reports
                            </span>
                        ),
                        children: (
                            <Card className="shadow-sm border border-slate-200/80 rounded-2xl w-full mt-2">
                                <div className="flex flex-col gap-4 mb-5">
                                    <div>
                                        <h3 className="text-lg font-bold text-slate-800 flex items-center gap-2">
                                            <Users size={18} className="text-[#1677ff]" />
                                            Student-Wise Weekly Performance
                                        </h3>
                                        <p className="text-xs text-slate-400 mt-0.5 flex items-center gap-2">
                                            Per-student PYQ performance over the last 90 days
                                        </p>
                                        {selectedExamName && (
                                            <p className="text-xs font-semibold text-indigo-600 mt-2 uppercase tracking-wide bg-indigo-50 px-2.5 py-1 rounded-md w-fit">
                                                Exam: {selectedExamName}
                                            </p>
                                        )}
                                    </div>

                                    <div className="flex flex-col sm:flex-row items-stretch sm:items-center gap-3 w-full justify-start border-t border-slate-100 pt-4">
                                        <div className="w-full sm:w-60">
                                            <Input
                                                placeholder="Search student..."
                                                prefix={<Search size={14} className="text-slate-400" />}
                                                value={studentSearch}
                                                onChange={(e) => setStudentSearch(e.target.value)}
                                                allowClear
                                                className="h-8 rounded-lg"
                                            />
                                        </div>

                                        <div
                                            onClick={() => setSortOrder((prev) => (prev === "asc" ? "desc" : "asc"))}
                                            className={`inline-flex items-center justify-center gap-1.5 px-3 py-1.5 rounded-xl border text-xs font-semibold transition-all duration-200 cursor-pointer select-none whitespace-nowrap shadow-sm h-8
                                                ${sortOrder === "desc"
                                                    ? "bg-indigo-50/70 text-indigo-600 border-indigo-200/80 hover:bg-indigo-100/80"
                                                    : "bg-rose-50/70 text-rose-600 border-rose-200/80 hover:bg-rose-100/80"
                                                }`}
                                        >
                                            {sortOrder === "desc" ? (
                                                <>
                                                    <ChartNoAxesColumnDecreasing size={18} /> Highest to Lowest
                                                </>
                                            ) : (
                                                <>
                                                    <ChartNoAxesColumnIncreasing size={18} /> Lowest to Highest
                                                </>
                                            )}
                                        </div>

                                        <div className="w-full sm:w-48">
                                            <Select
                                                className="w-full h-8"
                                                placeholder="Filter Status"
                                                suffixIcon={<Filter size={14} className="text-slate-400" />}
                                                value={statusFilter}
                                                onChange={(value: "all" | "attended" | "notattended") => setStatusFilter(value)}
                                                options={[
                                                    { label: `All Students (${counts.all})`, value: "all" },
                                                    { label: `Attended (${counts.attended})`, value: "attended" },
                                                    { label: `Not Attended (${counts.notattended})`, value: "notattended" }
                                                ]}
                                            />
                                        </div>

                                        <div className="w-full sm:w-80">
                                            <Select {...studentExamSelectProps} />
                                        </div>
                                    </div>
                                </div>

                                {!selectedExamId ? (
                                    <div className="h-64 flex flex-col items-center justify-center text-slate-400 gap-2">
                                        <BookOpen size={48} className="text-slate-200" />
                                        <p>Please select an exam to view students.</p>
                                    </div>
                                ) : tableLoading ? (
                                    <Skeleton active paragraph={{ rows: 8 }} />
                                ) : tableData.length === 0 ? (
                                    <div className="h-64 flex items-center justify-center">
                                        <Empty description="No student PYQ test data available for this period" />
                                    </div>
                                ) : (
                                    <>
                                        <Table
                                            dataSource={tableData}
                                            columns={antdColumns}
                                            rowKey="studentId"
                                            scroll={{ x: "max-content" }}
                                            pagination={false}
                                            size="middle"
                                            rowClassName="hover:bg-slate-50/60 transition-colors"
                                        />
                                        <div className="flex justify-end mt-4">
                                            <Pagination
                                                current={tablePage}
                                                total={tableTotal}
                                                pageSize={tableLimit}
                                                showSizeChanger
                                                showTotal={(total) => `Total ${total} items`}
                                                onChange={(page, pageSize) => {
                                                    setTablePage(page);
                                                    setTableLimit(pageSize);
                                                    fetchTableData(page, pageSize, statusFilter, debouncedStudentSearch);
                                                }}
                                            />
                                        </div>
                                    </>
                                )}
                            </Card>
                        )
                    }
                ]}
            />
        </div>
    );
};

export default PyqTestReport;