import { useCallback, useEffect, useMemo, useState } from "react";
import axios from "axios";
import { useDisclosure } from "@heroui/react";
import { useTranslation } from "react-i18next";
import RoundEvaluationOverrideRow from "@/components/RoundEvaluationOverrideRow";
import RoundEvaluationOverrideDetailModal from "@/components/RoundEvaluationOverrideDetailModal";
import RoundEvaluationOverridesPagination from "@/components/RoundEvaluationOverridesPagination";
import type {
  LogItem,
  LogOverride,
  OverrideForm,
  RoundDetail,
} from "@/components/RoundEvaluationOverrides.types";

type PaginatedResponse<T> = {
    data: T[];
    current_page: number;
    last_page: number;
    total: number;
};

type Props = {
    roundId: number | null;
    evaluationRunId: number;
};

export default function RoundEvaluationOverrides({ roundId, evaluationRunId }: Props) {
    const [logs, setLogs] = useState<LogItem[]>([]);
    const [overrides, setOverrides] = useState<Record<number, LogOverride>>({});
    const [forms, setForms] = useState<Record<number, OverrideForm>>({});
    const [page, setPage] = useState(1);
    const [lastPage, setLastPage] = useState(1);
    const [roundDetail, setRoundDetail] = useState<RoundDetail | null>(null);
    const [loading, setLoading] = useState(false);
    const [activeLogId, setActiveLogId] = useState<number | null>(null);
    const perPage = 30;
    const { isOpen, onOpen, onOpenChange } = useDisclosure();
    const { t } = useTranslation("common");

    const bands = useMemo(() => roundDetail?.bands ?? [], [roundDetail?.bands]);
    const categories = useMemo(() => roundDetail?.categories ?? [], [roundDetail?.categories]);
    const powerCategories = useMemo(
        () => roundDetail?.powerCategories ?? roundDetail?.power_categories ?? [],
        [roundDetail?.powerCategories, roundDetail?.power_categories]
    );

    useEffect(() => {
        if (!roundId) return;
        let active = true;
        (async () => {
            try {
                const res = await axios.get<RoundDetail>(`/api/rounds/${roundId}`, {
                    headers: { Accept: "application/json" },
                    withCredentials: true,
                });
                if (!active) return;
                setRoundDetail(res.data);
            } catch {
                if (!active) return;
                setRoundDetail(null);
            }
        })();
        return () => {
            active = false;
        };
    }, [roundId]);

    useEffect(() => {
        if (!roundId) return;
        let active = true;
        (async () => {
            try {
                setLoading(true);
                const res = await axios.get<PaginatedResponse<LogItem>>("/api/logs", {
                    headers: { Accept: "application/json" },
                    params: { round_id: roundId, per_page: perPage, page },
                    withCredentials: true,
                });
                if (!active) return;
                setLogs(res.data.data);
                setLastPage(res.data.last_page ?? 1);
            } catch {
                if (!active) return;
                setLogs([]);
            } finally {
                if (active) setLoading(false);
            }
        })();
        return () => {
            active = false;
        };
    }, [roundId, page]);

    useEffect(() => {
        let active = true;
        (async () => {
            try {
                const res = await axios.get<PaginatedResponse<LogOverride>>("/api/log-overrides", {
                    headers: { Accept: "application/json" },
                    params: { evaluation_run_id: evaluationRunId, per_page: 500 },
                    withCredentials: true,
                });
                if (!active) return;
                const map: Record<number, LogOverride> = {};
                res.data.data.forEach((item) => {
                    map[item.log_id] = item;
                });
                setOverrides(map);
            } catch {
                if (!active) return;
                setOverrides({});
            }
        })();
        return () => {
            active = false;
        };
    }, [evaluationRunId]);

    useEffect(() => {
        if (!logs.length) return;
        setForms((prev) => {
            const next = { ...prev };
            for (const log of logs) {
                const override = overrides[log.id];
                if (!next[log.id]) {
                    next[log.id] = {
                        status: override?.forced_log_status ?? "AUTO",
                        bandId: override?.forced_band_id ? String(override.forced_band_id) : "",
                        categoryId: override?.forced_category_id ? String(override.forced_category_id) : "",
                        powerCategoryId: override?.forced_power_category_id ? String(override.forced_power_category_id) : "",
                        sixhrCategory:
                            override?.forced_sixhr_category === null || override?.forced_sixhr_category === undefined
                                ? ""
                                : override.forced_sixhr_category
                                    ? "1"
                                    : "0",
                        reason: override?.reason ?? "",
                        saving: false,
                        error: null,
                        success: null,
                    };
                }
            }
            return next;
        });
    }, [logs, overrides]);

    useEffect(() => {
        if (!isOpen) {
            setActiveLogId(null);
        }
    }, [isOpen]);

    const openDetail = useCallback(
        (logId: number) => {
            setActiveLogId(logId);
            onOpen();
        },
        [onOpen]
    );

    const handleFieldChange = useCallback(
        (logId: number, field: keyof OverrideForm, value: string) => {
            setForms((prev) => ({
                ...prev,
                [logId]: {
                    ...prev[logId],
                    [field]: value,
                    error: null,
                    success: null,
                },
            }));
        },
        []
    );

    const commitReason = useCallback((logId: number, reason: string) => {
        setForms((prev) => ({
            ...prev,
            [logId]: {
                ...prev[logId],
                reason,
                error: null,
                success: null,
            },
        }));
    }, []);

    const saveOverride = async (logId: number, reasonOverride?: string) => {
        const form = forms[logId];
        if (!form) return;
        const override = overrides[logId];

        const hasStatus = form.status && form.status !== "AUTO";
        const hasBand = form.bandId !== "";
        const hasCategory = form.categoryId !== "";
        const hasPower = form.powerCategoryId !== "";
        const hasSixhr = form.sixhrCategory !== "";
        const hasAny = hasStatus || hasBand || hasCategory || hasPower || hasSixhr;
        if (reasonOverride !== undefined) {
            commitReason(logId, reasonOverride);
        }
        const reason = (reasonOverride ?? form.reason).trim();
        const baseline = {
            status: override?.forced_log_status ?? "AUTO",
            bandId: override?.forced_band_id ? String(override.forced_band_id) : "",
            categoryId: override?.forced_category_id ? String(override.forced_category_id) : "",
            powerCategoryId: override?.forced_power_category_id ? String(override.forced_power_category_id) : "",
            sixhrCategory:
                override?.forced_sixhr_category === null || override?.forced_sixhr_category === undefined
                    ? ""
                    : override.forced_sixhr_category
                        ? "1"
                        : "0",
        };
        const hasChanges =
            form.status !== baseline.status ||
            form.bandId !== baseline.bandId ||
            form.categoryId !== baseline.categoryId ||
            form.powerCategoryId !== baseline.powerCategoryId ||
            form.sixhrCategory !== baseline.sixhrCategory;

        setForms((prev) => ({
            ...prev,
            [logId]: { ...prev[logId], saving: true, error: null, success: null },
        }));

        try {
            if (!hasChanges && !override) {
                setForms((prev) => ({
                    ...prev,
                [logId]: { ...prev[logId], saving: false, success: t("override_no_changes") ?? "Bez změn." },
            }));
            return;
        }

        if (!hasChanges && override) {
            setForms((prev) => ({
                ...prev,
                [logId]: { ...prev[logId], saving: false, success: t("override_no_changes") ?? "Bez změn." },
            }));
            return;
        }

        if (!reason) {
            setForms((prev) => ({
                ...prev,
                [logId]: {
                    ...prev[logId],
                    saving: false,
                    error: t("override_reason_required") ?? "Doplň důvod změny.",
                },
            }));
            return;
        }

            const payload = {
                evaluation_run_id: evaluationRunId,
                log_id: logId,
                forced_log_status: form.status || "AUTO",
                forced_band_id: form.bandId ? Number(form.bandId) : null,
                forced_category_id: form.categoryId ? Number(form.categoryId) : null,
                forced_power_category_id: form.powerCategoryId ? Number(form.powerCategoryId) : null,
                forced_sixhr_category: form.sixhrCategory === "" ? null : form.sixhrCategory === "1",
                reason,
            };

            if (override) {
                const res = await axios.put<LogOverride>(`/api/log-overrides/${override.id}`, payload, {
                    headers: { Accept: "application/json" },
                    withCredentials: true,
                    withXSRFToken: true,
                });
                setOverrides((prev) => ({ ...prev, [logId]: res.data }));
            } else {
                const res = await axios.post<LogOverride>("/api/log-overrides", payload, {
                    headers: { Accept: "application/json" },
                    withCredentials: true,
                    withXSRFToken: true,
                });
                setOverrides((prev) => ({ ...prev, [logId]: res.data }));
            }

            setForms((prev) => ({
                ...prev,
                [logId]: { ...prev[logId], saving: false, success: t("override_saved") ?? "Uloženo." },
            }));
        } catch (e: any) {
            const msg =
                e?.response?.data?.message ||
                (t("override_save_failed") ?? "Nepodařilo se uložit override.");
            setForms((prev) => ({
                ...prev,
                [logId]: { ...prev[logId], saving: false, error: msg },
            }));
        }
    };

    if (!roundId) return null;

    return (
        <div className="pt-2 border-t border-divider">
            <div className="font-semibold text-sm mb-2">
                {t("override_pre_match_title") ?? "Ruční zásahy před matchingem"}
            </div>
            <div className="text-xs text-foreground-500 mb-2">
                {t("override_pre_match_hint") ??
                    "Změny se projeví po kliknutí na „Pokračovat“. IGNORED vyřadí log z matchingu."}
            </div>
            {loading && (
                <div className="text-xs text-foreground-600">
                    {t("override_loading_logs") ?? "Načítám logy…"}
                </div>
            )}
            {!loading && logs.length === 0 && (
                <div className="text-xs text-foreground-600">
                    {t("override_no_logs") ?? "Žádné logy k úpravě."}
                </div>
            )}
            {logs.length > 0 && (
                <div className="space-y-3">
                    <div className="grid gap-2">
                        {logs.map((log) => (
                            <RoundEvaluationOverrideRow
                                key={log.id}
                                log={log}
                                form={forms[log.id]}
                                override={overrides[log.id]}
                                bands={bands}
                                categories={categories}
                                powerCategories={powerCategories}
                                onFieldChange={handleFieldChange}
                                onReasonCommit={commitReason}
                                onSave={saveOverride}
                                onOpenDetail={openDetail}
                            />
                        ))}
                    </div>
                    <RoundEvaluationOverridesPagination
                        page={page}
                        lastPage={lastPage}
                        onPrev={() => setPage((p) => Math.max(1, p - 1))}
                        onNext={() => setPage((p) => Math.min(lastPage, p + 1))}
                    />
                </div>
            )}
            <RoundEvaluationOverrideDetailModal
                isOpen={isOpen}
                logId={activeLogId}
                onOpenChange={onOpenChange}
            />
        </div>
    );
}
