import { useCallback, useEffect, useMemo, useState } from "react";
import axios from "axios";
import { Spinner, useDisclosure } from "@heroui/react";
import RoundEvaluationLogOverridesTable from "@/components/RoundEvaluationLogOverridesTable";
import RoundEvaluationLogOverridesModal from "@/components/RoundEvaluationLogOverridesModal";
import RoundEvaluationLogOverridesSearch from "@/components/RoundEvaluationLogOverridesSearch";
import type {
  LogOverride,
  LogResult,
  OverrideForm,
} from "@/components/RoundEvaluationLogOverrides.types";

type RoundDetail = {
  id: number;
  bands?: { id: number; name: string }[];
  categories?: { id: number; name: string }[];
  power_categories?: { id: number; name: string }[];
  powerCategories?: { id: number; name: string }[];
};

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

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

export default function RoundEvaluationLogOverrides({ roundId, evaluationRunId }: Props) {
  const { isOpen, onOpen, onOpenChange, onClose } = useDisclosure();
  const [items, setItems] = useState<LogResult[]>([]);
  const [overrides, setOverrides] = useState<Record<number, LogOverride>>({});
  const [forms, setForms] = useState<Record<number, OverrideForm>>({});
  const [loading, setLoading] = useState(false);
  const [search, setSearch] = useState("");
  const [roundDetail, setRoundDetail] = useState<RoundDetail | null>(null);
  const [activeLogId, setActiveLogId] = useState<number | null>(null);
  const perPage = 5000;

  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]
  );

  const resolveName = (list: { id: number; name: string }[], id?: number | null) => {
    if (!id) return "AUTO";
    return list.find((item) => item.id === id)?.name ?? `#${id}`;
  };

  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]);

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

  useEffect(() => {
    const active = { value: true };
    fetchOverrides(active);
    return () => {
      active.value = false;
    };
  }, [fetchOverrides]);

  const fetchItems = useCallback(async (active?: { value: boolean }) => {
    try {
      setLoading(true);
      const res = await axios.get<PaginatedResponse<LogResult>>("/api/log-results", {
        headers: { Accept: "application/json" },
        params: { evaluation_run_id: evaluationRunId, per_page: perPage },
        withCredentials: true,
      });
      if (active && !active.value) return;
      setItems(res.data.data);
    } catch {
      if (active && !active.value) return;
      setItems([]);
    } finally {
      if (!active || active.value) setLoading(false);
    }
  }, [evaluationRunId, perPage]);

  useEffect(() => {
    const active = { value: true };
    fetchItems(active);
    return () => {
      active.value = false;
    };
  }, [fetchItems]);

  useEffect(() => {
    if (!items.length) return;
    setForms((prev) => {
      const next = { ...prev };
      for (const item of items) {
        const override = overrides[item.log_id];
        if (!next[item.log_id]) {
          next[item.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) : "",
            reason: override?.reason ?? "",
            saving: false,
            error: null,
            success: null,
          };
        }
      }
      return next;
    });
  }, [items, overrides]);

  const filteredItems = useMemo(() => {
    const query = search.trim().toLowerCase();
    if (!query) return items;
    return items.filter((item) => {
      const log = item.log;
      const parts = [
        String(item.log_id),
        log?.pcall ?? "",
        log?.pband ?? "",
        log?.psect ?? "",
      ]
        .join(" ")
        .toLowerCase();
      return parts.includes(query);
    });
  }, [items, search]);

  const activeItem = useMemo(
    () => (activeLogId ? items.find((item) => item.log_id === activeLogId) ?? null : null),
    [items, activeLogId]
  );

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

  const handleFieldChange = (logId: number, field: keyof OverrideForm, value: string) => {
    const emptyForm: OverrideForm = {
      status: "AUTO",
      bandId: "",
      categoryId: "",
      powerCategoryId: "",
      reason: "",
      saving: false,
      error: null,
      success: null,
    };
    setForms((prev) => ({
      ...prev,
      [logId]: {
        ...(prev[logId] ?? emptyForm),
        [field]: value,
        error: null,
        success: null,
      },
    }));
  };

  const saveOverride = async (logId: number) => {
    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 hasAny = hasStatus || hasBand || hasCategory || hasPower;
    const reason = 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) : "",
    };
    const hasChanges =
      form.status !== baseline.status ||
      form.bandId !== baseline.bandId ||
      form.categoryId !== baseline.categoryId ||
      form.powerCategoryId !== baseline.powerCategoryId;

    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: "Bez změn." },
        }));
        return;
      }

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

      if (!reason) {
        setForms((prev) => ({
          ...prev,
          [logId]: { ...prev[logId], saving: false, error: "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,
        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: "Uloženo." },
      }));
      await Promise.all([fetchOverrides(), fetchItems()]);
      onClose();
    } catch (e: any) {
      const msg = e?.response?.data?.message || "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">Ruční zásahy po agregaci</div>
      <div className="text-xs text-foreground-500 mb-2">
        Slouží pro korekce klasifikace a statusu logu před publikací.
      </div>
      <RoundEvaluationLogOverridesSearch search={search} onChange={setSearch} />
      {loading && (
        <div className="flex items-center gap-2 text-xs text-foreground-600">
          <Spinner size="sm" /> Načítám výsledky…
        </div>
      )}
      {!loading && filteredItems.length === 0 && (
        <div className="text-xs text-foreground-600">Žádné položky k úpravě.</div>
      )}
      {filteredItems.length > 0 && (
        <div className="space-y-4">
          <RoundEvaluationLogOverridesTable
            items={filteredItems}
            overrides={overrides}
            onEdit={openEditor}
          />
        </div>
      )}
      <RoundEvaluationLogOverridesModal
        isOpen={isOpen}
        onOpenChange={onOpenChange}
        onClose={onClose}
        activeItem={activeItem}
        override={activeItem ? overrides[activeItem.log_id] : undefined}
        form={activeItem ? forms[activeItem.log_id] : undefined}
        bands={bands}
        categories={categories}
        powerCategories={powerCategories}
        onFieldChange={handleFieldChange}
        onSave={saveOverride}
        resolveName={resolveName}
      />
    </div>
  );
}
