import {
    BucketTask,
    OfferwallApi,
    OfferwallReason,
    ReportApi, ReportTask, ReportValue, StatusApi,
    TasksStatusResponse, TaskStatusResponse, TopNPlusBlockOfferWall
} from "@/api_fsb";

import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
    Field,
    FieldDescription,
    FieldGroup,
    FieldLabel,
    FieldLegend,
    FieldSet,
} from "@/components/ui/field";
import { useAppDispatch, useAppSelector } from "@/hooks";
import { bpid, formatCentsToUSD, formatSource, truncate } from "@/lib/utils";
import {
    getAvailabilityCount, getLOIText,
    isLowBalance,
    selectBucket,
    setAttemptedLiveEligibleCount,
    setAvailabilityCount,
    setCurrentBuckets,
    setEnteredTimestamp, setLOI,
    setOfferwallReasons,
    setTaskStatus
} from "@/models/appSlice";
import {
    createColumnHelper, flexRender, getCoreRowModel,
    useReactTable
} from "@tanstack/react-table";
import { XIcon } from "lucide-react";
import moment from "moment/moment";
import { useEffect, useRef, useState } from "react";
import Markdown from 'react-markdown';

const Report = ({ onClose }: { onClose: () => void }) => {
    const [showComplete, setShowComplete] = useState(false);
    const [selectedValues, setSelectedValues] = useState<ReportValue[]>([]);

    const bpuid = useAppSelector(state => state.app.bpuid)
    const ts = useAppSelector(state => state.app.taskStatus)

    const handleCheckboxChange = (value: ReportValue, checked: boolean) => {
        setSelectedValues(prev =>
            checked
                ? [...prev, value]
                : prev.filter(v => v !== value)
        );
    };

    const clicked_submit = () => {
        if (!bpuid) return;
        // ReportValue.NUMBER_0
        console.log("selectedValues:", selectedValues);

        const rt: ReportTask = {
            'bpuid': bpuid,
            'reasons': selectedValues,
            'notes': ""
        };

        new ReportApi().reportTaskProductIdReportPost(
            bpid, // productId
            rt, // reportTask
        ).then(res => {
            console.log("Response:", res); // Check what's actually here

            if (res.status === 400) {
                // Handle error here instead
            } else {
                setShowComplete(true);
            }
        })
    }

    const reportReasons = [
        { id: 'TECHNICAL_ERROR', label: 'Technical Error', value: ReportValue.NUMBER_1 },
        { id: 'NO_REDIRECT', label: 'No Redirect', value: ReportValue.NUMBER_2 },
        { id: 'PRIVACY_INVASION', label: 'Privacy Invasion', value: ReportValue.NUMBER_3 },
        { id: 'UNCOMFORTABLE_TOPICS', label: 'Uncomfortable Topics', value: ReportValue.NUMBER_4 },
        { id: 'ASKED_FOR_NOT_ALLOWED_ACTION', label: 'Asked for Not Allowed Action', value: ReportValue.NUMBER_5 },
        { id: 'BAD_ON_MOBILE', label: 'Bad on Mobile', value: ReportValue.NUMBER_6 },
        { id: 'DIDNT_LIKE', label: "Didn't Like", value: ReportValue.NUMBER_7 },
    ];

    if (!ts?.finished) {
        return <p>Please finish a Task to report its status.</p>
    }

    if (showComplete) {
        return <SubimtAMT />
    }

    return (
        <div className="border-2 border-rose-200 rounded">
            <div className="flex justify-center">
                <FieldSet className="mt-2">
                    <FieldLegend variant="label" className="my-0 text-rose-950">
                        Please select all reasons why you are reporting this Task:
                    </FieldLegend>
                    <FieldDescription className="my-0 text-rose-950">
                        You must provide at least one reason to report a Task.
                    </FieldDescription>
                    <FieldGroup className="gap-2 my-0 py-0">

                        {reportReasons.map((reason) => (
                            <Field key={reason.id} orientation="horizontal" className="
                            hover:cursor-pointer">
                                <Checkbox
                                    id={reason.id}
                                    name={reason.id}
                                    onCheckedChange={(checked) =>
                                        handleCheckboxChange(reason.value, checked as boolean)
                                    }
                                />
                                <FieldLabel
                                    htmlFor={reason.id}
                                    className="font-medium text-rose-950
                                    hover:cursor-pointer hover:font-semibold"
                                >
                                    {reason.label}
                                </FieldLabel>
                            </Field>
                        ))}

                    </FieldGroup>
                </FieldSet>
            </div>
            <div className="flex justify-center my-2 space-x-5">
                <Button variant="outline" size="icon" aria-label="Submit"
                    className="
                    border-2 rounded border-zinc-800 text-zinc-800
                    hover:cursor-pointer hover:bg-zinc-800 hover:text-zinc-50"
                    onClick={onClose}>
                    <XIcon />
                </Button>
                <Button variant="outline"
                    className="
                    border-2 rounded border-rose-400 text-rose-950
                    hover:cursor-pointer hover:bg-rose-400 hover:text-rose-50"
                    onClick={clicked_submit}>Submit and Complete HIT</Button>
            </div>
        </div>
    )
}

const SubimtAMT = () => {
    const bpuid = useAppSelector(state => state.app.bpuid)
    const assignment_id = useAppSelector(state => state.app.assignment_id)
    const ts = useAppSelector(state => state.app.taskStatus)
    const turkSubmitTo = useAppSelector(state => state.app.turkSubmitTo)

    const formRef = useRef<HTMLFormElement>(null);

    useEffect(() => {
        if (!ts) return;
        if (!bpuid) return;
        if (!assignment_id) return;
        if (!turkSubmitTo) return;

        if (formRef.current) {
            formRef.current.submit();
        }
    }, [ts?.tsid, bpuid, assignment_id, turkSubmitTo]);

    return (
        <>
            <form
                ref={formRef}
                action={`${turkSubmitTo}/mturk/externalSubmit`}
                method="POST"
                style={{ display: 'none' }}>
                <input type="hidden" name="assignmentId" value={assignment_id} />
                <input type="hidden" name="tsid" value={ts?.tsid} />
                <input type="hidden" name="amt_assignment_id" value={assignment_id} />
                <input type="hidden" name="amt_worker_id" value={bpuid} />
                <button type="submit">Submit HIT</button>
            </form>
        </>
    )
}


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

    const [isPolling, setIsPolling] = useState(true);
    // const [timeAgo, setTimeAgo] = useState("");

    const [showComplete, setShowComplete] = useState(false);
    const [showReport, setShowReport] = useState(false);

    const bpuid = useAppSelector(state => state.app.bpuid)
    const entered = useAppSelector(state => state.app.currentBucketEntered)
    const isLow = useAppSelector(state => isLowBalance(state))

    const ts = useAppSelector(state => state.app.taskStatus)
    const isBaddie = ts?.status_code_1 === "SESSION_START_FAIL" || ts?.status_code_1 === "SESSION_START_QUALITY_FAIL" || ts?.status_code_1 === "SESSION_CONTINUE_QUALITY_FAIL";

    // useEffect(() => {
    //     if (!ts) return;

    //     const updateTimeAgo = () => {
    //         const time_ago = moment(ts.started).fromNow();
    //         setTimeAgo(time_ago);
    //     };

    //     // Update immediately
    //     updateTimeAgo();

    //     // Then update every minute
    //     const intervalId = setInterval(updateTimeAgo, 60 * 1000);

    //     return () => clearInterval(intervalId);
    // }, [ts]);

    useEffect(() => {
        if (!bpuid) return;
        if (!entered) return;
        if (!isPolling) return;

        const pollApi = async () => {
            new StatusApi().listTaskStatusesProductIdStatusGet(
                bpid,  // productId
                bpuid,  // Worker ID
                entered,  // startedAfter
                moment.utc().unix() // startedBefore    
            ).then(res => {
                const d = res.data as TasksStatusResponse;

                if (!d.tasks_status || d.tasks_status.length === 0) {
                    // Likely still in a GRS survey
                    return;
                }

                // if (d_len >= 2) Sentry.captureMessage("Results returned back multiple")
                const ts = d.tasks_status![0] as TaskStatusResponse;
                dispatch(setTaskStatus(ts))

                if (ts.status == 2 || ts.status == 3) {
                    // INCOMPLETE + COMPLETE
                    setIsPolling(false);
                }
            });

            // If there is already a TaskStatus, update the time ago
            // if (ts) {
            //     const time_ago = moment(ts.started).fromNow();
            //     setTimeAgo(time_ago);
            // }
        };

        // Call immediately on mount, then set up interval
        pollApi();
        const intervalId = setInterval(pollApi, 4 * 1000);

        // Cleanup: stop interval when component unmounts or isPolling changes
        return () => clearInterval(intervalId);
    }, [isPolling, entered]);

    if (!ts) {
        return (
            <p>Loading</p>
        )
    }

    // This is if they are actively in a survey or we can't determine the 
    // status yet. We want to show the timer and keep them on this page to 
    // monitor for completion. This gets shown no matter what regardless of 
    // balance.
    //
    // 0 - UNKNOWN, 1 - ENTER
    if (ts.status === 0 || ts.status === 1) {
        return (
            <>
                <div>
                    <h2 className="
                    bg-blue-500 rounded py-2
                    text-white text-2xl font-semibold text-center">
                        In Progress
                    </h2>
                    <p className="
                    py-4
                    text-zinc-500 text-2xl font-semibold text-center">
                        We're actively monitoring your Task status.
                    </p>
                </div>
            </>
        )
    }

    // This is if they have finished a survey complete and it resulted in a 
    // COMPLETE or a INCOMPLETE (doesn't matter). They can now submit the HIT.
    //
    // 2 - INCOMPLETE, 3 - COMPLETE
    return (
        <>
            <div>
                <h2 className="
                    bg-blue-500 rounded py-2
                    text-white text-2xl font-semibold text-center">
                    {ts.status === 3 ? "Survey Complete!" : "Survey Terminated."}
                </h2>

                {((ts.status === 3 || !isLow) && !isBaddie) && (
                    <p className="
                    py-2
                    text-zinc-500 text-md font-medium text-center">
                        You may now submit the HIT.
                    </p>
                )}
            </div>

            {(isBaddie) ? (
                <>
                    <div className="
                    border-2 border-rose-500 rounded py-2
                    bg-rose-400 text-rose-700">
                        <h2 className="text-center text-xl font-bold text-white">
                            Quality Check Failed.
                        </h2>
                        <p className="px-4 py-2 text-center text-sm font-medium text-white">
                            Unfortunately, it looks like you did not pass the quality check for this survey.
                        </p>

                        <p className="
                    pt-0 pb-4
                    text-red-950 text-sm font-semibold text-center">
                            Please return the HIT to avoid having your assignment rejected.
                        </p>
                    </div>
                </>

            ) : (
                <>
                    {(ts.status === 3 || !isLow) ? (
                        <>
                            <div className="flex justify-center my-4 space-x-5">

                                <button type="button" className="
                border-4 rounded border-emerald-400 py-1 px-3
                text-xl font-bold text-emerald-950
                hover:cursor-pointer hover:bg-emerald-400 hover:text-emerald-50"
                                    onClick={() => setShowComplete(true)}
                                >Submit HIT</button>

                                <button type="button" className="
                border-4 rounded border-rose-200 py-1 px-3
                text-xl font-bold text-rose-200
                hover:cursor-pointer hover:border-rose-500 hover:bg-rose-400 hover:text-rose-50"
                                    onClick={() => setShowReport(!showReport)}
                                >Report Survey</button>
                            </div>

                            {showComplete && <SubimtAMT />}
                            {showReport && <Report onClose={() => setShowReport(false)} />}
                        </>
                    ) : (
                        <div>
                            <p className="
                    text-red-600 text-lg font-semibold text-center">
                                Your balance is low. You cannot submit the HIT at this time.
                            </p>

                            <p className="
                    pt-0 pb-4
                    text-red-950 text-sm font-semibold text-center">
                                Please return the HIT to avoid having your assignment rejected.
                            </p>
                        </div>
                    )}
                </>

            )}


        </>
    )
}


const LOISelect = () => {
    // This is what's responsible for being able to click on the text 
    //  we set the global LOI times.

    const dispatch = useAppDispatch()
    const loi: number = useAppSelector(state => state.app.loi)
    const bucket = useAppSelector(state => selectBucket(state))

    const toggle_loi = function () {
        dispatch(setLOI(loi >= 1800 ? 600 : loi + 600))
    }

    const time_f = useAppSelector(state => getLOIText(state))

    const avg_time_f = ((bucket?.duration.q2 ?? 0) / 60).toLocaleString(
        'en-US', { minimumFractionDigits: 0, maximumFractionDigits: 1 })

    const formatter = new Intl.NumberFormat('en-US', {
        style: 'currency',
        currency: 'USD',
    });
    const avg_pay_f: string = formatter.format((bucket?.payout.q2 ?? 0) / 100)

    return (
        <div className="bg-zinc-100 rounded py-2 m-0">
            <p className="text-zinc-700 text-2xl text-center font-bold m-0">
                I have <span
                    className="cursor-pointer text-emerald-600 italic hover:text-emerald-700 hover:underline"
                    onClick={toggle_loi}>{time_f}</span> minutes
            </p>
            <p
                className="text-center text-xs font-thin m-0 text-zinc-500">
                The average time spent is {avg_time_f} minutes and pays {avg_pay_f}</p>
        </div>
    )

};

const SurveyLoading = () => {
    return (
        <div className="
            border-8 border-emerald-400 rounded py-0 my-2
            text-center text-3xl 
            hover:cursor-pointer hover:bg-green-500 hover:text-white">
            <p className="py-2 text-center text-3xl font-semibold">
                Survey Loading…
            </p>
        </div>
    )
}


const NoSurveys = () => {
    const offerwall_reasons = useAppSelector(state => state.app.offerwall_reasons)

    const REASON_DISPLAY: Record<OfferwallReason, { label: string; description: string }> = {
        [OfferwallReason.UserBlocked]: {
            label: "Account Restricted",
            description: "Your account has been restricted.",
        },
        [OfferwallReason.HighReconRate]: {
            label: "High Reconciliation Rate",
            description: "Your account has an unusually high reconciliation rate.",
        },
        [OfferwallReason.UncommonDemographics]: {
            label: "Demographic Mismatch",
            description: "No surveys require your current demographics.",
        },
        [OfferwallReason.UnderMinimumAge]: {
            label: "Age Requirement Not Met",
            description: "You must meet the minimum age requirement to participate.",
        },
        [OfferwallReason.ExhaustedHighValueSupply]: {
            label: "No Premium Offers Available",
            description: "You've attempted all premium surveys.",
        },
        [OfferwallReason.AllEligibleAttempted]: {
            label: "All Offers Attempted",
            description: "You've attempted all available surveys.",
        },
        [OfferwallReason.LowCurrentSupply]: {
            label: "Limited Availability",
            description: "There are currently limited opportunities available.",
        },
    };

    function formatReasons(reasons: OfferwallReason[]): { label: string; description: string }[] {
        return reasons.map((r) => REASON_DISPLAY[r]);
    }

    return (
        <>
            <div className="
            border-8 border-emerald-400 rounded py-0 my-2
            text-center text-3xl 
            hover:cursor-pointer hover:bg-green-500 hover:text-white">
                <p className="py-2 text-center text-3xl font-semibold">
                    No Surveys available…
                </p>
            </div>

            {formatReasons(offerwall_reasons).map(r => {
                return (
                    <div className="
                    border-6 border-rose-200 rounded py-0 my-2
                    text-center 
                    hover:cursor-pointer hover:bg-rose-200 hover:text-rose-950  ">
                        <p className="py-2 text-center text-md font-semibold text-rose-600">
                            {r.description}
                        </p>
                    </div>
                )
            })}
        </>
    )
}

const BucketDetails = () => {
    const bucket = useAppSelector(state => selectBucket(state))
    if (!bucket) return null;
    const [showDetails, setShowDetails] = useState(false);

    const columnHelper = createColumnHelper<BucketTask>()
    const columns = [
        columnHelper.display({
            id: 'index',
            header: '#',
            cell: ({ row }) => row.index + 1,
            size: 25,
            meta: {
                align: 'center'
            }
        }),
        columnHelper.accessor('source', {
            header: () => 'Marketplace',
            cell: (props) => {
                const s = props.getValue()
                return formatSource(s)
            },
            size: 85,
            meta: {
                align: 'left'
            }
        }),
        columnHelper.accessor('id', {
            header: () => 'Survey ID',
            cell: props => {
                return truncate(props.getValue(), 6, "*****").toUpperCase()
            },
            size: 70,
            meta: {
                align: 'left'
            }
        }),
        columnHelper.accessor('payout', {
            header: () => 'Amount',
            cell: (props) => {
                const val = props.renderValue() as number;
                return formatCentsToUSD(val)
            },
            size: 50,
            meta: {
                align: 'center'
            }
        }),
        columnHelper.accessor('loi', {
            header: () => 'Duration',
            cell: (props) => {
                const val = props.renderValue() as number;
                return `${Math.round(val / 60)} min`
            },
            size: 50,
            meta: {
                align: 'center'
            }
        }),
    ]

    const table = useReactTable({
        'data': bucket.contents,
        'columns': columns,
        getCoreRowModel: getCoreRowModel(),
    });

    return (
        <>
            <div className="w-full text-center text-[8px] text-emerald-600
            rounded py-2 my-1
            hover:cursor-pointer hover:text-emerald-700 hover:underline hover:bg-emerald-200 
            "
                onClick={() => setShowDetails(!showDetails)}
            >
                ({showDetails ? 'Hide' : 'Show'} details of surveys in this bucket)
            </div>

            {showDetails && (
                <div className="w-full border-t-1 border-emerald-200 py-1 my-0 flex justify-center">
                    <table className="text-[10px] text-emerald-900 table-fixed border-collapse">
                        <thead className="font-bold">
                            {table.getHeaderGroups().map((headerGroup) => (

                                <tr key={headerGroup.id}>
                                    {headerGroup.headers.map((header) => {
                                        const align = header.column.columnDef.meta?.align || 'left';
                                        const alignClass = align === 'center' ? 'text-center' : align === 'right' ? 'text-right' : 'text-left';

                                        return (
                                            <th
                                                key={header.id}
                                                className={`p-0 m-0 ${alignClass}`}
                                                style={{
                                                    width: `${header.column.getSize()}px`,
                                                }}
                                            >
                                                {flexRender(
                                                    header.column.columnDef.header,
                                                    header.getContext(),
                                                )}
                                            </th>
                                        )
                                    })}
                                </tr>
                            ))}
                        </thead>
                        <tbody>
                            {table.getRowModel().rows.map((row) => (
                                <tr key={row.id}>
                                    {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={`p-0 ${alignClass}`}
                                                style={{
                                                    width: `${cell.column.getSize()}px`,
                                                }}
                                            >
                                                {flexRender(cell.column.columnDef.cell, cell.getContext())}
                                            </td>
                                        )
                                    })}
                                </tr>
                            ))}
                        </tbody>

                    </table>
                </div>
            )}
        </>
    )
};

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

    const available_cnt = useAppSelector(state => getAvailabilityCount(state))
    const buckets = useAppSelector(state => state.app.currentBuckets)
    const bucket = useAppSelector(state => selectBucket(state))
    const isLow = useAppSelector(state => isLowBalance(state))

    useEffect(() => {
        if (!bpuid) return;

        new OfferwallApi().topNPlusBlockOfferwallProductIdOfferwallD48cce47Get(
            bpid,  // productId
            bpuid, // bpuid
            undefined,  // ip
            undefined,  // countryIso
            undefined,  // languages
            undefined,  // behavior
            undefined,  // minPayout
            loi,  //duration
            1  // nBins
        ).then(res => {
            const top_n_res = res.data.offerwall as TopNPlusBlockOfferWall;
            dispatch(setAvailabilityCount(top_n_res.availability_count))
            if (top_n_res.attempted_live_eligible_count) {
                dispatch(setAttemptedLiveEligibleCount(top_n_res.attempted_live_eligible_count))
            }
            dispatch(setCurrentBuckets(top_n_res.buckets))
            dispatch(setOfferwallReasons(top_n_res.offerwall_reasons ?? []))
        });
    }, [loi, bpuid]);


    const start_survey = () => {
        if (!bucket?.uri) return;

        dispatch(setEnteredTimestamp());
        window.open(bucket.uri, '_blank');
    }

    if (buckets === undefined) {
        return <SurveyLoading />
    }

    if (available_cnt === 0 || buckets.length === 0 || !bucket) {
        return <NoSurveys />
    }

    return (
        <>
            {isLow && (
                <div className="
                border-8 border-rose-500 rounded py-2
                bg-rose-400 text-rose-700">
                    <h2 className="text-center text-xl font-bold text-white">
                        Your balance is low.
                    </h2>
                    <p className="px-4 py-2 text-center text-sm font-medium text-white">
                        You may continue to attempt surveys, but you will be
                        advised to return the HIT if your survey attempt does
                        not result in a complete.
                    </p>
                    <p className="px-4 py-2 text-center text-sm font-bold text-white">
                        HIT submissions with a balance exceeding -$1.00 will
                        return in rejected assignments.
                    </p>
                </div>
            )}

            <LOISelect />
            <div
                onClick={start_survey}
                className="
                border-8 border-emerald-400 rounded py-0 my-2
                hover:cursor-pointer hover:bg-emerald-400 hover:text-emerald-50">
                <p className="py-2 text-center text-3xl font-semibold">
                    <a
                        target="_blank"
                        rel="noopener noreferrer">
                        Start Task
                    </a>
                </p>
            </div>
            <BucketDetails />

            <div className="border-2 border-emerald-200 rounded py-2 m-0">
                <p className="text-emerald-700 text-sm text-center font-medium px-2 m-0">
                    <Markdown>
                        {bucket.eligibility_explanation}
                    </Markdown>
                </p>
            </div>
        </>
    )
};


const Work = () => {
    const entered = useAppSelector(state => state.app.currentBucketEntered)
    const assignment_id = useAppSelector(state => state.app.assignment_id)

    if (!assignment_id) {
        return (
            <p className="text-center text-2xl py-3 text-red-800 font-semibold">
                No Assignment ID found. Please access this page through
                the Amazon Mechanical Turk platform.
            </p>
        )
    }

    return (
        <>
            {entered ? (
                <SurveyMonitor />
            ) : (
                <SurveyEnter />
            )}
        </>
    )
};


export default Work;