import { useEffect, useState } from 'react';
import Header from '../views/articleeditor/Header';
import { PrimaryButton } from '../components/button/PrimaryButton';
import { Input } from '../components/input/Input';
import { useAppDispatch, useAppSelector } from '../redux/hooks';
import {
    CreateContestBody,
    deleteContest,
    fetchContestById,
    setContestStatus,
    updateContest,
} from '../redux/slices/contests';
import { useQuery } from '../hooks/useQuery';
import { Navigate, useNavigate } from 'react-router-dom';
import { fetchMissionById, fetchMissions } from '../redux/slices/missions';
import { ReverseButton } from '../components/button/ReverseButton';
import {
    DropDownList,
    DropDownListItem,
} from '../components/input/DropDownList';
import { NumberInput } from '../components/input/NumberInput';
import { cn } from '../lib/cn';
import DateInput from '../components/input/DateInput';
import { fetchMyGroups } from '../redux/slices/groups';

interface Mission {
    id: number;
    name: string;
}

const highlightZ = (name: string, filter: string) => {
    if (!filter) return name;

    const s = filter.toLowerCase();
    const t = name.toLowerCase();
    const n = t.length;
    const m = s.length;

    const mark = Array(n).fill(false);

    // Проходимся с конца и ставим отметки
    for (let i = n - 1; i >= 0; i--) {
        if (i + m <= n && t.slice(i, i + m) === s) {
            for (let j = i; j < i + m; j++) {
                if (mark[j]) break;
                mark[j] = true;
            }
        }
    }

    // === Формируем единые жёлтые блоки ===
    const result: any[] = [];
    let i = 0;

    while (i < n) {
        if (!mark[i]) {
            // обычный символ
            result.push(name[i]);
            i++;
        } else {
            // начинаем жёлтый блок
            let j = i;
            while (j < n && mark[j]) j++;

            const chunk = name.slice(i, j);
            result.push(
                <span key={i} className="bg-yellow-400 text-black rounded px-1">
                    {chunk}
                </span>,
            );

            i = j;
        }
    }

    return result;
};

function toUtc(localDateTime?: string): string {
    if (!localDateTime) return '';

    // Создаём дату (она автоматически считается как локальная)
    const date = new Date(localDateTime);

    // Возвращаем ISO-строку с 'Z' (всегда в UTC)
    return date.toISOString();
}

/**
 * Страница создания / редактирования контеста
 */
const ContestEditor = () => {
    const dispatch = useAppDispatch();
    const navigate = useNavigate();

    const query = useQuery();
    const back = query.get('back') ?? undefined;
    const contestId = Number(query.get('contestId') ?? undefined);
    const refactor = !!contestId;

    if (!refactor) {
        return <Navigate to="/home/account/acontest" />;
    }

    const status = useAppSelector(
        (state) => state.contests.createContest.status,
    );

    const [missionFindInput, setMissionFindInput] = useState<string>('');

    const now = new Date();
    const plus60 = new Date(now.getTime() + 60 * 60 * 1000);

    const toLocal = (d: Date) => {
        const off = d.getTimezoneOffset();
        const local = new Date(d.getTime() - off * 60000);
        return local.toISOString().slice(0, 16);
    };

    const visibilityItems: DropDownListItem[] = [
        { value: 'Public', text: 'Публичный' },
        { value: 'GroupPrivate', text: 'Для группы' },
    ];

    const scheduleTypeItems: DropDownListItem[] = [
        { value: 'AlwaysOpen', text: 'Всегда открыт' },
        { value: 'FixedWindow', text: 'Фиксированое окно' },
        { value: 'RollingWindow', text: 'Скользящее окно' },
    ];

    const [contest, setContest] = useState<CreateContestBody>({
        name: '',
        description: '',
        scheduleType: 'AlwaysOpen',
        visibility: 'Public',
        startsAt: toLocal(now),
        endsAt: toLocal(plus60),
        attemptDurationMinutes: 60,
        maxAttempts: 1,
        allowEarlyFinish: false,
        missionIds: [],
        articleIds: [],
    });
    const myname = useAppSelector((state) => state.auth.username);
    const [missions, setMissions] = useState<Mission[]>([]);

    const statusDelete = useAppSelector(
        (state) => state.contests.deleteContest.status,
    );
    const statusUpdate = useAppSelector(
        (state) => state.contests.updateContest.status,
    );

    const { contest: contestById, status: contestByIdstatus } = useAppSelector(
        (state) => state.contests.fetchContestById,
    );

    const globalMissions = useAppSelector((state) => state.missions.missions);

    const myGroups = useAppSelector(
        (state) => state.groups.fetchMyGroups.groups,
    ).filter((group) =>
        group.members.some(
            (member) =>
                member.username === myname &&
                member.role.includes('Administrator'),
        ),
    );

    function toLocalInputValue(utcString: string) {
        const d = new Date(utcString);

        const pad = (n: number) => n.toString().padStart(2, '0');

        return (
            `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}` +
            `T${pad(d.getHours())}:${pad(d.getMinutes())}`
        );
    }

    useEffect(() => {
        if (status === 'successful') {
        }
    }, [status]);

    const handleChange = (key: keyof CreateContestBody, value: any) => {
        setContest((prev) => ({ ...prev, [key]: value }));
    };

    const handleUpdateContest = () => {
        dispatch(
            updateContest({
                ...contest,
                endsAt: toUtc(contest.endsAt),
                startsAt: toUtc(contest.startsAt),
                contestId,
            }),
        );
    };

    const handleDeleteContest = () => {
        dispatch(deleteContest(contestId));
    };

    const addMission = () => {
        const mission = globalMissions
            .filter((v) => !contest?.missionIds?.includes(v.id))
            .filter((v) =>
                (v.id + ' ' + v.name)
                    .toLocaleLowerCase()
                    .includes(missionFindInput.toLocaleLowerCase()),
            )[0];
        if (!mission) return;
        const id = mission.id;
        if (!id || contest.missionIds?.includes(id)) return;
        dispatch(fetchMissionById(id))
            .unwrap()
            .then((mission) => {
                setMissions((prev) => [...prev, mission]);
                setContest((prev) => ({
                    ...prev,
                    missionIds: [...(prev.missionIds ?? []), id],
                }));
                setMissionFindInput('');
            })
            .catch((err) => {
                err;
            });
    };

    const removeMission = (removeId: number) => {
        setContest({
            ...contest,
            missionIds: contest.missionIds?.filter((v) => v !== removeId),
        });
        setMissions(missions.filter((v) => v.id != removeId));
    };

    useEffect(() => {
        if (statusDelete == 'successful') {
            dispatch(
                setContestStatus({ key: 'deleteContest', status: 'idle' }),
            );
            navigate('/home/account/contests');
        }
    }, [statusDelete]);

    useEffect(() => {
        if (statusUpdate == 'successful') {
            dispatch(
                setContestStatus({ key: 'updateContest', status: 'idle' }),
            );
            navigate('/home/account/contests');
        }
    }, [statusUpdate]);

    useEffect(() => {
        if (refactor) {
            dispatch(fetchContestById(contestId));
            dispatch(fetchMyGroups());
            dispatch(fetchMissions({}));
        }
    }, [refactor]);

    useEffect(() => {
        if (refactor && contestByIdstatus == 'successful' && contestById) {
            setContest({
                ...contestById,
                // groupIds: contestById.groups.map(group => group.groupId),
                missionIds: contestById.missions?.map((mission) => mission.id),
                articleIds: contestById.articles?.map(
                    (article) => article.articleId,
                ),
            });
            setMissions(contestById.missions ?? []);
        }
    }, [contestById]);

    const visibilityDefaultState =
        visibilityItems.find(
            (i) => contest && i.value === contest.visibility,
        ) ?? visibilityItems[0];

    const scheduleTypeDefaultState =
        scheduleTypeItems.find(
            (i) => contest && i.value === contest.scheduleType,
        ) ?? scheduleTypeItems[0];

    const groupItems = myGroups.map((v) => {
        return {
            value: '' + v.id,
            text: v.name,
        };
    });
    const groupIdDefaultState =
        myGroups.find((g) => g.id == contest?.groupId) ??
        myGroups[0] ??
        undefined;

    return (
        <div className="h-screen grid grid-rows-[60px,1fr] text-liquid-white">
            <Header backClick={() => navigate(back || '/home/contests')} />

            <div className="grid grid-cols-2 h-full min-h-0">
                {/* Левая панешь */}
                <div className="overflow-y-auto min-h-0 overflow-hidden">
                    <div className="p-4 border-r border-gray-700 flex flex-col h-full">
                        <h2 className="text-lg font-semibold mb-3 text-gray-100"></h2>

                        <div className="">
                            <div className="font-bold text-[30px] mb-[10px]">
                                {refactor
                                    ? `Редактирвоание контеста #${contestId} \"${contestById?.name}\"`
                                    : 'Создать контест'}
                            </div>

                            <Input
                                name="name"
                                type="text"
                                label="Название"
                                className="mt-[10px]"
                                placeholder="Введите название"
                                onChange={(v) => handleChange('name', v)}
                                defaultState={contest.name ?? ''}
                            />

                            <Input
                                name="description"
                                type="text"
                                label="Описание"
                                className="mt-[10px]"
                                placeholder="Введите описание"
                                onChange={(v) => handleChange('description', v)}
                                defaultState={contest.description ?? ''}
                            />

                            <div className="grid grid-cols-2 gap-[10px] mt-[10px]">
                                <div>
                                    <label className="block text-sm mb-1">
                                        Тип контеста
                                    </label>

                                    <DropDownList
                                        items={scheduleTypeItems}
                                        defaultState={scheduleTypeDefaultState}
                                        onChange={(v) => {
                                            handleChange('scheduleType', v);
                                        }}
                                        weight="w-full"
                                    />
                                </div>

                                <div>
                                    <label className="block text-sm mb-1">
                                        Видимость
                                    </label>
                                    <DropDownList
                                        items={visibilityItems}
                                        onChange={(v) => {
                                            handleChange('visibility', v);
                                        }}
                                        defaultState={visibilityDefaultState}
                                        weight="w-full"
                                    />
                                </div>
                            </div>

                            <div
                                className={cn(
                                    ' grid grid-flow-row grid-rows-[0fr] opacity-0 transition-all duration-200 mb-[10px]',
                                    contest.visibility == 'GroupPrivate' &&
                                        'grid-rows-[1fr] opacity-100',
                                )}
                            >
                                {groupIdDefaultState ? (
                                    <div
                                        className={cn(
                                            contest.visibility !=
                                                'GroupPrivate' &&
                                                'overflow-hidden',
                                        )}
                                    >
                                        <div>
                                            <label className="block text-sm mb-2 mt-[10px]">
                                                Группа для привязки
                                            </label>

                                            <DropDownList
                                                items={groupItems}
                                                defaultState={{
                                                    value:
                                                        '' +
                                                        groupIdDefaultState.id,
                                                    text: groupIdDefaultState.name,
                                                }}
                                                onChange={(v) => {
                                                    handleChange(
                                                        'groupId',
                                                        Number(v),
                                                    );
                                                }}
                                                weight="w-full"
                                            />
                                        </div>
                                    </div>
                                ) : (
                                    <div className="overflow-hidden">
                                        <div className="text-liquid-red my-[20px]">
                                            У вас нет группы вкоторой вы
                                            являетесь Администратором!
                                        </div>
                                    </div>
                                )}
                            </div>

                            {/* Даты */}
                            <div
                                className={cn(
                                    ' grid grid-flow-row grid-rows-[0fr] opacity-0 transition-all duration-200',
                                    contest.scheduleType != 'AlwaysOpen' &&
                                        'grid-rows-[1fr] opacity-100',
                                )}
                            >
                                <div className="overflow-hidden">
                                    <div className="grid grid-cols-2 gap-[10px] mt-[10px]">
                                        <DateInput
                                            label="Дата начала"
                                            value={
                                                contest.startsAt
                                                    ? toLocalInputValue(
                                                          contest.startsAt,
                                                      )
                                                    : ''
                                            }
                                            onChange={(v) =>
                                                handleChange('startsAt', v)
                                            }
                                        />

                                        <DateInput
                                            label="Дата окончания"
                                            value={
                                                contest.endsAt
                                                    ? toLocalInputValue(
                                                          contest.endsAt,
                                                      )
                                                    : ''
                                            }
                                            onChange={(v) =>
                                                handleChange('endsAt', v)
                                            }
                                        />
                                    </div>
                                </div>
                            </div>

                            {/* Продолжительность и лимиты */}
                            <div className="grid grid-cols-2 gap-[10px] mt-[10px]">
                                <NumberInput
                                    defaultState={
                                        contest.attemptDurationMinutes
                                    }
                                    name="attemptDurationMinutes"
                                    label="Длительность попытки (мин)"
                                    placeholder="Например: 60"
                                    minValue={1}
                                    maxValue={365 * 24 * 60}
                                    onChange={(v) =>
                                        handleChange(
                                            'attemptDurationMinutes',
                                            Number(v),
                                        )
                                    }
                                />
                                <NumberInput
                                    defaultState={contest.maxAttempts}
                                    name="maxAttempts"
                                    label="Макс. попыток"
                                    placeholder="Например: 3"
                                    minValue={1}
                                    maxValue={100}
                                    onChange={(v) =>
                                        handleChange('maxAttempts', Number(v))
                                    }
                                />
                            </div>

                            {/* Кнопки */}
                            <div className="flex flex-row w-full items-center justify-end mt-[20px] gap-[20px]">
                                <PrimaryButton
                                    onClick={handleUpdateContest}
                                    text="Сохранить"
                                    disabled={status === 'loading'}
                                />
                                <ReverseButton
                                    color="error"
                                    onClick={handleDeleteContest}
                                    text="Удалить"
                                    disabled={statusDelete === 'loading'}
                                />
                            </div>
                        </div>
                    </div>
                </div>

                {/* Правая панель */}
                <div className="min-h-0 ">
                    <div className="p-4 border-r border-gray-700 flex flex-col h-full">
                        {/* Блок для тегов */}
                        <div className="mt-[20px] max-w-[600px] relative">
                            <div className="grid grid-cols-[1fr,140px] items-end gap-2">
                                <Input
                                    name="missionId"
                                    autocomplete="missionId"
                                    className="mt-[20px] max-w-[600px]"
                                    label="Введите название или ID миссии"
                                    type="text"
                                    onChange={(v) => {
                                        setMissionFindInput(v);
                                    }}
                                    defaultState={missionFindInput}
                                    placeholder={`Наприме: \"458\" или \"Поиск наименьшего\"`}
                                    onKeyDown={(e) => {
                                        if (e.key == 'Enter') addMission();
                                    }}
                                />
                                <PrimaryButton
                                    onClick={addMission}
                                    text="Добавить"
                                    className="h-[40px] w-[140px]"
                                />

                                {/* Выпадающие задачи */}
                                <div
                                    className={cn(
                                        'absolute rounded-[10px] bg-liquid-background w-[590px] left-0 top-[100px] z-50 transition-all duration-300',
                                        'grid overflow-hidden border-liquid-lighter border-[3px] border-solid',
                                        missionFindInput
                                            ? 'grid-rows-[1fr] opacity-100'
                                            : 'grid-rows-[0fr] opacity-0 pointer-events-none',
                                    )}
                                >
                                    <div className="overflow-hidden p-[8px]">
                                        <div className="overflow-y-scroll max-h-[250px] thin-scrollbar grid gap-[20px]">
                                            {globalMissions
                                                .filter(
                                                    (v) =>
                                                        !contest?.missionIds?.includes(
                                                            v.id,
                                                        ),
                                                )
                                                .filter((v) =>
                                                    (v.id + ' ' + v.name)
                                                        .toLocaleLowerCase()
                                                        .includes(
                                                            missionFindInput.toLocaleLowerCase(),
                                                        ),
                                                )
                                                .map((v, i) => (
                                                    <div
                                                        key={i}
                                                        className="hover:bg-liquid-lighter rounded-[10px] px-[12px] py-[4px] transition-colors duration-300 cursor-pointer"
                                                        onClick={() => {
                                                            setMissionFindInput(
                                                                v.id +
                                                                    ' ' +
                                                                    v.name,
                                                            );
                                                            addMission();
                                                        }}
                                                    >
                                                        {highlightZ(
                                                            '#' +
                                                                v.id +
                                                                ' ' +
                                                                v.name,
                                                            missionFindInput,
                                                        )}
                                                    </div>
                                                ))}
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <div className="gap-[10px] mt-[20px]">
                                {missions.map((v, i) => (
                                    <div
                                        key={i}
                                        className="grid grid-cols-[60px,1fr,24px] gap-1 bg-liquid-lighter px-[16px] py-[8px] rounded-[10px] relative mb-[10px] items-center"
                                    >
                                        <div>{'#' + v.id}</div>
                                        <div>{v.name}</div>
                                        <button
                                            onClick={() => removeMission(v.id)}
                                            className="text-liquid-red font-bold ml-[5px] absolute right-[16px]"
                                        >
                                            ×
                                        </button>
                                    </div>
                                ))}
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    );
};

export default ContestEditor;
