import {
    UpkQuestionChoice
} from "@/api_fsb";
import {
    ChevronRightIcon
} from "lucide-react";
import { KeyboardEvent, MouseEvent, useEffect, useRef, useState } from "react";

import { useAppDispatch, useAppSelector } from "@/hooks";
import { bpid } from "@/lib/utils";
import {
    createColumnHelper,
    flexRender,
    getCoreRowModel,
    getFilteredRowModel,
    getSortedRowModel,
    RowModel,
    RowSelectionState,
    useReactTable,
} from '@tanstack/react-table';
import { clsx } from "clsx";

import {
    Pagination,
    PaginationContent,
    PaginationItem,
    PaginationLink
} from "@/components/ui/pagination";

import {
    addAnswers,
    fetchNewQuestions,
    goToNextQuestion,
    ProfileQuestion,
    questionsSelectors,
    saveAnswer,
    selectActiveQuestion,
    selectActiveQuestionValidation,
    selectAllQuestions,
    setActiveQuestion
} from "@/models/profilingQuestionsSlice";
import { useSelector } from "react-redux";
// import {motion} from "framer-motion"

const TextEntry = () => {
    const dispatch = useAppDispatch()

    const activeQuestion = useSelector(selectActiveQuestion);
    // const selectAnswer = useMemo(() => selectAnswerForQuestion(question), [question]);
    // const selectAnswer = useSelector(selectAnswerForQuestion(question));
    const metadata = activeQuestion?._metadata
    const validation = activeQuestion?._validation
    const bpuid = useAppSelector(state => state.app.bpuid)

    if (!metadata) return null
    if (!validation) return null

    const error = validation?.errors.length > 0

    const handleInputChange = (event: React.KeyboardEvent<HTMLInputElement>) => {
        if (!activeQuestion.question_id) return;

        const target = event.target as HTMLInputElement;
        dispatch(addAnswers({ questionId: activeQuestion.question_id!, answers: [target.value] as string[] }))
    };

    const handleKeyPress = (event: KeyboardEvent<HTMLInputElement>) => {
        if (!activeQuestion.question_id) return;
        if (!bpuid) return;

        if (event.key === 'Enter') {
            dispatch(saveAnswer({ questionId: activeQuestion.question_id!, bpuid: bpuid }))
        }
    };

    return (
        <div className="px-6 my-6">
            <input type="text"
                id="text-entry-input"
                aria-describedby=""
                // defaultValue={answer?.values.length ? answer?.values[0] : ""}
                onKeyUp={handleInputChange}
                onKeyDown={handleKeyPress} // Use onKeyDown to listen for the key press
                // title={error ? answer?.error_msg : ""}
                className={clsx(
                    'w-full border-1 rounded px-2 py-1',
                    error ?
                        'border-red-500 focus-visible:ring-red-500' :
                        'border-blue-50'
                )}
            />

            {
                validation.errors.map(e => {
                    return (
                        <p className="text-sm text-red-100 my-2">{e.message}</p>
                    )
                })
            }
        </div>
    )
}


export default function useKeyboardMode(
    rowModel: RowModel<UpkQuestionChoice>,
) {
    //   const [keyboardEnabled, setKeyboardEnabled] = useState(
    //     localStorage.getItem(keyboardMode) === "enabled",
    //   );
    const rowRefs = useRef<(HTMLTableRowElement | null)[]>([]);

    const dispatch = useAppDispatch()
    const activeQuestion = useSelector(selectActiveQuestion);
    const bpuid = useAppSelector(state => state.app.bpuid)

    const keyboardSelectionIdxRef = useRef(0);

    useEffect(() => {
        const handleKeyDown = (event: KeyboardEvent) => {

            if (!activeQuestion) return;
            if (!bpuid) return;

            //   if (!keyboardEnabled) {
            //     return;
            //   }

            const { key } = event;
            const totalRows = rowRefs.current.length;
            const prevIdx = keyboardSelectionIdxRef.current;
            let nextIdx = prevIdx;

            if (key === "ArrowDown") nextIdx = Math.min(prevIdx + 1, totalRows - 1);
            if (key === "ArrowUp") nextIdx = Math.max(prevIdx - 1, 0);
            if (key === " ") {
                const active = document.activeElement as HTMLElement | null;

                if (active?.tabIndex === 0) {
                    return;
                } else {
                    rowModel.rows[keyboardSelectionIdxRef.current].toggleSelected();
                }
            }

            if (event.key === 'Enter') {
                dispatch(saveAnswer({ questionId: activeQuestion.question_id!, bpuid: bpuid }))
            }


            if (nextIdx !== prevIdx) {

                rowRefs.current[prevIdx]?.classList.remove("bg-blue-400");
                rowRefs.current[nextIdx]?.classList.add("bg-blue-400");

                rowRefs.current[nextIdx]?.scrollIntoView({
                    behavior: "smooth",
                    block: "center",
                });
                keyboardSelectionIdxRef.current = nextIdx;
            }
        };

        // I really don't know, and I don't really care enough to make this
        //  technically type'd correctly.  - Max

        // @ts-ignore
        window.addEventListener("keydown", handleKeyDown);
        // @ts-ignore
        return () => window.removeEventListener("keydown", handleKeyDown);

    }, [rowModel.rows]);

    return {
        // keyboardEnabled,
        // setKeyboardEnabled,
        rowRefs,
        keyboardSelectionIdxRef,
    };
}

const MultipleChoice = () => {
    const dispatch = useAppDispatch()
    const activeQuestion = useSelector(selectActiveQuestion);

    // const error: Boolean = answer?.error_msg.length > 0
    // console.log("Rendering MultipleChoice with answer:", answer, error)

    // TODO! Retrieve store values to use as the initial state for the table
    //  This is useful for if they tab around before submitting the answer
    const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
    const [globalFilter, setGlobalFilter] = useState('');

    const handleRowSelectionChange = (updaterOrValue: RowSelectionState | ((old: RowSelectionState) => RowSelectionState)) => {
        setRowSelection((oldSelection) => {
            // Get the new selection state
            const newSelection = typeof updaterOrValue === 'function'
                ? updaterOrValue(oldSelection)
                : updaterOrValue;

            // Find which row was just selected/deselected
            const changedRowId = Object.keys(newSelection).find(
                key => newSelection[key] !== oldSelection[key]
            );

            if (!changedRowId) return newSelection;

            // Get the actual row data
            const row = table.getRow(changedRowId);
            const rowData = row.original; // Your row data object

            // Check if "None of the Above" was selected
            const normalized = rowData.choice_text.trim().toLowerCase();
            const isNoneOfTheAbove = (normalized === "none of the above") || (rowData.exclusive ?? false);
            if (isNoneOfTheAbove && newSelection[changedRowId]) {
                // Clear all other selections, keep only this one
                return { [changedRowId]: true };
            }

            // Check if a regular option was selected while "None of the Above" exists
            const noneOfTheAboveId = Object.keys(newSelection).find(id => {
                const r = table.getRow(id);
                const rowData = r.original as UpkQuestionChoice;

                const normalized = rowData.choice_text.trim().toLowerCase();
                const isNoneOfTheAbove = (normalized === "none of the above") || (rowData.exclusive ?? false);

                return isNoneOfTheAbove && newSelection[id];
            });

            if (noneOfTheAboveId && changedRowId !== noneOfTheAboveId) {
                // Remove "None of the Above" selection
                const { [noneOfTheAboveId]: _, ...rest } = newSelection;
                return rest;
            }

            return newSelection;
        });
    };

    useEffect(() => {
        if (!activeQuestion?.question_id) return;
        // Run this anytime a rowSelection changes, to update 
        //  the answer in the store
        const selectedChoices = Object.keys(rowSelection)
        dispatch(addAnswers({ questionId: activeQuestion.question_id, answers: selectedChoices }))
    }, [rowSelection])

    // Define columns
    const columnHelper = createColumnHelper<UpkQuestionChoice>()
    const columns = [
        columnHelper.display({
            id: 'select',
            cell: ({ row }) => {
                const canSelected = row.getCanSelect()

                return (
                    <input
                        type="checkbox"
                        checked={row.getIsSelected()}
                        disabled={!row.getCanSelect()}
                        onChange={row.getToggleSelectedHandler()}
                        className={`w-4 h-4 rounded-0 border-slate-300 cursor-pointer
                    focus:outline-none focus:border-blue-500 focus:ring-blue-500
                    ${canSelected ? ' ' : 'hidden'}
                    `}
                    />
                )
            },
            size: 20,
            meta: {
                align: 'center'
            }
        }),

        columnHelper.accessor("choice_text", {
            header: () => 'Choice Text',
            cell: (info) => {
                const text = info.getValue();
                const selected = info.row.getIsSelected()
                const canSelected = info.row.getCanSelect()

                return (
                    <p className={`
                        w-max truncate
                        text-sm text-left pl-1
                        ${selected ? 'font-bold' : 'font-medium'}
                        ${canSelected ? 'text-blue-950' : 'text-blue-600'}
                        `}>
                        {text}
                    </p>
                )
            },
            size: 380,
            meta: {
                align: 'left'
            }
        }),
    ]

    const table = useReactTable({
        'data': activeQuestion!.choices ?? [],
        columns,
        getRowId: (row) => row.choice_id,
        state: {
            rowSelection,
            globalFilter,
        },
        // enableRowSelection: true,
        enableRowSelection: (row) => {
            // Allow deselection always, but limit new selections
            const currentSelectionCount = Object.keys(rowSelection).length;
            const isRowSelected = rowSelection[row.id];

            const max_selection = activeQuestion?.selector === "SA" ? 1 : activeQuestion?.choices?.length ?? 10

            // Allow if: row is already selected OR we haven't hit the limit
            return isRowSelected || currentSelectionCount < max_selection;
        },
        onRowSelectionChange: handleRowSelectionChange,
        onGlobalFilterChange: setGlobalFilter,
        getCoreRowModel: getCoreRowModel(),
        getSortedRowModel: getSortedRowModel(),
        getFilteredRowModel: getFilteredRowModel(),
    });

    const selectedCount = table.getSelectedRowModel().rows.length;

    //const { rowRefs, setKeyboardEnabled, keyboardSelectionIdxRef } = useKeyboardMode(table.getRowModel());
    const { rowRefs } = useKeyboardMode(table.getRowModel());

    return (
        <>

            {/* Controls */}
            <div className="py-1">
                <div className="flex flex-wrap gap-2">

                    {/* Search */}
                    <div className="flex-1">
                        <input
                            type="text"
                            placeholder="Search choices..."
                            value={globalFilter ?? ''}
                            onChange={e => setGlobalFilter(e.target.value)}
                            className="w-full px-4 py-1
                                    border border-blue-900 bg-blue-400 rounded 
                                    text-white text-sm
                                    focus:outline-none focus:ring-2 focus:ring-indigo-500"
                        />
                    </div>

                    {/* Selected Count */}
                    {selectedCount > 0 && (
                        <div className="flex items-center gap-2 px-2 py-1
                                border border-blue-900 text-blue-700 rounded font-medium
                                text-[10px]
                                hover:cursor-pointer hover:bg-blue-800 hover:text-white
                                "
                            onClick={() => setRowSelection({})}>
                            <span>{selectedCount} selected</span>
                            <button className="m-0 p-0 font-bold">✕</button>
                        </div>
                    )}

                </div>
            </div>

            {/* Table */}
            <div className="border border-blue-200 rounded max-h-[400px] overflow-y-auto
                [&::-webkit-scrollbar]:h-[4px]
                [&::-webkit-scrollbar]:w-1

                [&::-webkit-scrollbar-track]:bg-blue-100
                [&::-webkit-scrollbar-thumb]:bg-blue-300
            ">
                <table className="text-xs table-fixed border-collapse w-full">
                    <tbody className="w-full">
                        {table.getRowModel().rows.map((row, idx) => (
                            <tr key={row.id}
                                ref={(el) => {
                                    rowRefs.current[idx] = el;
                                }}
                                onClick={() => row.toggleSelected()}
                                className={`cursor-pointer transition-colors w-full
                                    ${row.getIsSelected() ? 'bg-blue-600 ' : ' '
                                    }`}
                            >

                                {row.getVisibleCells().map((cell) => {
                                    const align = cell.column.columnDef.meta?.align || 'left';
                                    const alignClass = align === 'center' ? 'text-center' :
                                        align === 'right' ? 'text-right' : 'text-left';

                                    return (
                                        <td key={cell.id}
                                            className={`py-2 ${alignClass}`}
                                            style={{
                                                width: `${cell.column.getSize()}px`,
                                            }}
                                        >
                                            {flexRender(cell.column.columnDef.cell, cell.getContext())}
                                        </td>
                                    )
                                })}

                            </tr>
                        ))}
                    </tbody>
                </table>
            </div>

            {/* Empty State */}
            {table.getRowModel().rows.length === 0 && (
                <div className="p-12 text-center text-blue-50 font-bold">
                    No items found matching your search
                </div>
            )}

            {/* Footer */}
            <div className="px-2 py-2 flex justify-between items-center
                    text-xs font-mono font-semibold text-blue-950 
                    ">
                <span>
                    Showing {table.getRowModel().rows.length} of {activeQuestion?.choices?.length} choices
                </span>
                {selectedCount > 0 && (
                    <span>
                        {selectedCount} choice{selectedCount !== 1 ? 's' : ''} selected
                    </span>
                )}
            </div>

        </>
    )

}

const ProfilingQuestionTitle = () => {
    const activeQuestion = useSelector(selectActiveQuestion);
    const question_active_tasks = activeQuestion?.importance?.task_count ?? 0

    if (!activeQuestion) return null;

    let text = activeQuestion?.question_text

    if (activeQuestion.explanation_template && activeQuestion._validation?.isComplete && activeQuestion._metadata.answers.length == 1) {
        const template = activeQuestion.explanation_template;
        const pre_code = activeQuestion._metadata.answers[0];

        const choice = activeQuestion.choices?.find(c => c.choice_id === pre_code)
        const choice_text = choice ? choice.choice_text : "your answer"

        text = template.replace("{answer}", choice_text)
    }


    return (
        <div className="flex justify-between items-center px-2">

            <h3 className="text-left text-sm font-bold m-0 p-0
            inline-block
            ">
                {text}
            </h3>

            <div className="max-w-[70px] text-center m-0 p-0">
                <h4 className="text-xs font-bold">
                    {question_active_tasks.toLocaleString()}
                </h4>
                <h5 className="text-[10px]">
                    Surveys use
                    this question
                </h5>
            </div>
        </div>
    )
}

const ProfilingQuestionSubmitButton = () => {
    const dispatch = useAppDispatch()

    const activeQuestion = useSelector(selectActiveQuestion);
    const activeQuestionValidation = useSelector(selectActiveQuestionValidation)
    const bpuid = useAppSelector(state => state.app.bpuid)

    const handleOnClick = () => {
        if (!activeQuestion) return
        if (!activeQuestionValidation?.isComplete) return
        if (!bpuid) return;

        dispatch(saveAnswer({ questionId: activeQuestion.question_id!, bpuid: bpuid }))
    }

    return (
        <button
            type="submit"
            className="cursor-pointer text-sm font-semibold
                    bg-blue-700 text-white py-1 px-4 rounded
                    hover:bg-blue-900 min-w-[148px]

                    disabled:bg-blue-700 disabled:text-rose-300 
                    disabled:cursor-not-allowed
                    "
            disabled={!activeQuestionValidation?.isComplete}
            onClick={handleOnClick}
        >
            Answer Question
        </button>
    )
}


export const ProfileQuestionFull = () => {
    const activeQuestion = useSelector(selectActiveQuestion);

    const renderContent = () => {
        if (!activeQuestion) return null;
        switch (activeQuestion.question_type) {
            case 'TE':
                return <TextEntry />
            case 'MC':
                return <MultipleChoice />
            default:
                return <MultipleChoice />
        }
    };

    if (!activeQuestion) return null

    return (
        <>
            {/* {answer && answer.processing && (
                <motion.div
                    className="bg-gray-300"
                    initial={{ width: "0%" }}
                    animate={{ width: "100%" }}
                    transition={{ duration: 1, ease: "easeInOut" }}
                // onAnimationComplete={() => setLoading(false)}
                />
            )} */}

            {renderContent()}
        </>
    )
}

const PaginationIcon: React.FC<{
    question: ProfileQuestion, idx: number,
}> = ({ question, idx }) => {
    const dispatch = useAppDispatch()

    // const answers = useAppSelector(state => state.answers)
    const isActive = question._metadata?.isActive ?? false
    const completed = question._validation?.isComplete ?? false

    const handleSetQuestion = (evt: MouseEvent<HTMLAnchorElement>) => {
        if (completed) {
            evt.preventDefault()
        } else {
            dispatch(setActiveQuestion(question.question_id!))
        }
    }

    return (
        <PaginationItem>
            <PaginationLink
                href="#"
                title={question.question_text}
                isActive={isActive}
                aria-disabled={!!completed}

                onClick={handleSetQuestion}
                className={clsx("cursor-pointer rounded border border-blue-300 text-blue-300 text-[10px] w-7 h-4",
                    {
                        "pointer-events-none cursor-not-allowed": completed,
                        "bg-blue-800 border-blue-800": isActive,
                    })}
            >
                {idx + 1}
            </PaginationLink>
        </PaginationItem>
    )
}

const ProfilingQuestionPagination = () => {
    const dispatch = useAppDispatch()

    const questions = useSelector(selectAllQuestions)
    const activeQuestion = useSelector(selectActiveQuestion)

    // All the variables needed for a sliding window
    const q_idx = questions.findIndex(q => q.question_id === activeQuestion!.question_id)

    const handleNextClick = () => {
        dispatch(goToNextQuestion());
    };

    const questionsWindow = (
        items: ProfileQuestion[], currentIndex: number, windowSize: number = 5
    ): ProfileQuestion[] => {
        const half: number = Math.floor(windowSize / 2)
        const total: number = items.length
        let start: number = currentIndex - half
        let end: number = currentIndex + half + 1

        if (start < 0) {
            end += Math.abs(start)
            start = 0
        }

        // Adjust if window goes past the end
        if (end > total) {
            const overflow: number = end - total
            start = Math.max(0, start - overflow)
            end = total
        }

        return items.slice(start, end)
    }

    return (
        <Pagination>
            <PaginationContent>
                {
                    questionsWindow(questions, q_idx).map(q => {
                        return <PaginationIcon
                            key={q.question_id}
                            question={q}
                            idx={questions.findIndex(qq => qq.question_id === q.question_id)}
                        />
                    })
                }

                <PaginationItem>
                    <PaginationLink
                        aria-label="Go to next page"
                        size="default"

                        className="rounded text-[10px] p-0 m-0
                        text-blue-300 
                        border border-blue-100 text-blue-100
                        hover:bg-blue-800 hover:border-blue-800 hover:text-white
                        gap-1 px-2.5 sm:pr-2.5
                        h-4
                        w-13 sm:w-14
                        "
                        onClick={handleNextClick}
                        href="#"
                    >
                        <span className="block">Next</span>
                        <ChevronRightIcon />
                    </PaginationLink>

                </PaginationItem>
            </PaginationContent>
        </Pagination>
    )
}

const ProfilingHeader = () => {
    const questions = useSelector(questionsSelectors.selectAll);

    return (
        <h2 className="text-xs font-mono font-bold p-0 m-0">
            {questions.length} Profiling Questions
        </h2>
    )
}

const ProfilingModalBody = () => {
    const activeQuestion = useSelector(selectActiveQuestion);

    if (!activeQuestion) {
        return (
            <div className="p-5">
                <h3 className="text-lg font-bold">No Profiling Questions Available</h3>
                <p className="my-0 text-sm text-gray-600">Please check back later.</p>
            </div>
        )
    }

    return (
        <div className="relative flex flex-col">
            {/* <ProfilingQuestionPagination /> */}

            <div className="flex-shrink-0">
                <ProfilingQuestionTitle />
            </div>

            {/* Scrollable Content */}
            <div className="flex-1 p-1">
                <ProfileQuestionFull key={activeQuestion.question_id} />
            </div>

            {/* Sticky Footer */}
            <div className="flex-shrink-0 bg-blue-600 p-1 flex justify-between
            ">
                <div className="justify-start">
                    <ProfilingQuestionPagination />
                </div>
                <div className="justify-end">
                    <ProfilingQuestionSubmitButton />
                </div>
            </div>

        </div>
    )
}

const Profiling = () => {
    /* This is the main UI for any User Profiling (before entering a task). It's
        primary window and position should be dedictated by it's parent so this
        can be positioned as a window or a sidebar as needed.
    */
    const [showProfiling, setShowProfiling] = useState(false);

    const dispatch = useAppDispatch()
    const bpuid = useAppSelector(state => state.app.bpuid)

    useEffect(() => {
        if (!bpuid) return;
        dispatch(fetchNewQuestions(bpuid));
    }, [bpid, bpuid])

    if (!bpuid) return null;

    return (
        <div className={clsx(
            "fixed rounded bg-blue-500 text-white shadow-lg z-60 \
            bottom-1 sm:bottom-6  \
            left-1 sm:left-2",
            showProfiling ? "w-[98vw] sm:w-[400px]" : "w-[220px]"
        )}
        >

            <div className="bg-blue-600 rounded border-white-300 
            cursor-pointer py-1 px-4
            hover:bg-blue-700 transition-colors duration-200"
                onClick={() => setShowProfiling(!showProfiling)}
            >
                <ProfilingHeader />

                <h4 className="text-[10px] text-center italic text-white-300 py-0">
                    (Click to {showProfiling ? 'hide' : 'show'})
                </h4>
            </div>

            {showProfiling && (
                <ProfilingModalBody />
            )}

        </div>
    )
}

export {
    Profiling
};
