import { useRouter, useSearchParams } from "next/navigation";
import { useState, useEffect, useCallback, useRef } from "react";
import { toast } from "sonner";

import { useI18n } from "@/core/i18n/hooks";
import {
  POST_MESSAGE_TYPES,
  RECEIVE_MESSAGE_TYPES,
  isSelectedSkillMessage,
  isSelectedSkillsMessage,
  type SelectedSkillPayloadItem,
  sendToParent,
} from "@/core/iframe-messages";
import { bootstrapRemoteSkill } from "@/core/skills/api";

// Skill 数据类型
interface SkillData {
  skill_id: string;
  title: string;
}

const STORAGE_KEYS = {
  latest: "iframe:selectedSkills:latest",
  byThreadPrefix: "iframe:selectedSkills:thread:",
} as const;

function getThreadStorageKey(threadId?: string | null): string | null {
  const normalized = threadId?.trim();
  if (!normalized) return null;
  return `${STORAGE_KEYS.byThreadPrefix}${normalized}`;
}

function parseStoredSkills(raw: string | null): SkillData[] {
  if (!raw) return [];
  try {
    const parsed = JSON.parse(raw) as unknown;
    if (!Array.isArray(parsed)) return [];
    return parsed
      .map((item) => {
        if (typeof item !== "object" || item === null) return null;
        const record = item as Record<string, unknown>;
        const rawSkillId = record.skill_id;
        const skillId =
          typeof rawSkillId === "string"
            ? rawSkillId.trim()
            : typeof rawSkillId === "number"
              ? String(rawSkillId)
              : "";
        const rawTitle = record.title;
        const title =
          typeof rawTitle === "string"
            ? rawTitle.trim()
            : typeof rawTitle === "number"
              ? String(rawTitle)
              : "";
        if (!skillId || !title) return null;
        return { skill_id: skillId, title };
      })
      .filter((item): item is SkillData => item !== null);
  } catch {
    return [];
  }
}

function removeSkillsByIdsFromList(
  skills: SkillData[],
  skillIds: string[],
): SkillData[] {
  if (skillIds.length === 0) return skills;
  const idSet = new Set(skillIds.map((id) => String(id)));
  return skills.filter((skill) => !idSet.has(String(skill.skill_id)));
}

// Hook 返回类型
interface UseIframeSkillReturn {
  selectedSkill: SkillData | null;
  selectedSkills: SkillData[];
  isBootstrapping: boolean;
  sendSelectSkill: (selectedSkills: SelectedSkillPayloadItem[]) => void;
  bootstrapAndLockSkills: (params: {
    selectedSkills: SelectedSkillPayloadItem[];
    title: string;
  }) => Promise<boolean>;
  openSkillDialog: () => void;
  clearSkill: (skillId?: string) => void;
}

interface UseIframeSkillOptions {
  threadId?: string | null;
}

export function useIframeSkill(
  options?: UseIframeSkillOptions,
): UseIframeSkillReturn {
  const { t } = useI18n();
  const router = useRouter();
  const searchParams = useSearchParams();
  const threadIdFromQuery = searchParams.get("thread_id");
  const threadIdFromOptions = options?.threadId?.trim();
  const threadId =
    threadIdFromOptions && threadIdFromOptions.length > 0
      ? threadIdFromOptions
      : threadIdFromQuery;
  const isChattingFromQuery = searchParams.get("is_chatting");
  const lastThreadIdRef = useRef<string | null>(null);

  const [selectedSkill, setSelectedSkill] = useState<SkillData | null>(null);
  const [selectedSkills, setSelectedSkills] = useState<SkillData[]>([]);
  const [isBootstrapping, setIsBootstrapping] = useState(false);

  const removeFailedSkills = useCallback(
    (skillIds: string[]) => {
      if (skillIds.length === 0) return;

      // 1) 回滚内存状态：移除失败 skill，避免展示错误 tag
      setSelectedSkills((prev) => {
        const next = removeSkillsByIdsFromList(prev, skillIds);
        setSelectedSkill(next[0] ?? null);
        return next;
      });

      // 2) 回滚 sessionStorage（latest + thread）
      const latestSkills = parseStoredSkills(
        window.sessionStorage.getItem(STORAGE_KEYS.latest),
      );
      const nextLatestSkills = removeSkillsByIdsFromList(
        latestSkills,
        skillIds,
      );
      if (nextLatestSkills.length > 0) {
        window.sessionStorage.setItem(
          STORAGE_KEYS.latest,
          JSON.stringify(nextLatestSkills),
        );
      } else {
        window.sessionStorage.removeItem(STORAGE_KEYS.latest);
      }

      const threadKey = getThreadStorageKey(threadId);
      if (threadKey) {
        const threadSkills = parseStoredSkills(
          window.sessionStorage.getItem(threadKey),
        );
        const nextThreadSkills = removeSkillsByIdsFromList(
          threadSkills,
          skillIds,
        );
        if (nextThreadSkills.length > 0) {
          window.sessionStorage.setItem(
            threadKey,
            JSON.stringify(nextThreadSkills),
          );
        } else {
          window.sessionStorage.removeItem(threadKey);
        }
      }
    },
    [threadId],
  );

  // 1. 监听 query 参数变化（临时禁用）
  // TODO: 当前 skill 仅通过 iframe postMessage 传递，暂不从 URL 读取 skill_id/title。
  // useEffect(() => {
  //   const skillIdFromQuery = searchParams.get("skill_id");
  //   const titleFromQuery = searchParams.get("title");
  //   if (skillIdFromQuery && titleFromQuery) {
  //     setSelectedSkill({ skill_id: skillIdFromQuery, title: titleFromQuery });
  //   }
  // }, [searchParams]);

  // 0. 监听 query 中 is_chatting=true 且带 thread_id 时跳转到 thread 页面
  // useEffect(() => {
  //   if (!threadId) return;
  //   if (isChattingFromQuery !== "true") return;
  //   if (lastThreadIdRef.current === threadId) return;
  //   lastThreadIdRef.current = threadId;
  //   router.replace(`/workspace/chats/${threadId}`);
  // }, [isChattingFromQuery, router, threadId]);

  // 2. 监听宿主页 postMessage
  useEffect(() => {
    const handleMessage = (event: MessageEvent) => {
      if (isSelectedSkillMessage(event.data)) {
        const { id, title } = event.data;
        const singleSkill = { skill_id: String(id), title };
        setSelectedSkill(singleSkill);
        setSelectedSkills([singleSkill]);
        return;
      }
      if (isSelectedSkillsMessage(event.data)) {
        const normalizedSkills = event.data.selectedSkills.map((item) => ({
          skill_id: String(item.id),
          title: item.name,
        }));
        if (normalizedSkills.length === 0) {
          setSelectedSkill(null);
          setSelectedSkills([]);
          return;
        }
        setSelectedSkill(normalizedSkills[0] ?? null);
        setSelectedSkills(normalizedSkills);
        return;
      }
      if (event.data?.type === RECEIVE_MESSAGE_TYPES.SELECTED_SKILL) {
        console.warn(
          "[useIframeSkill] 忽略非法 selectedSkill 消息",
          event.data,
        );
      }
    };
    window.addEventListener("message", handleMessage);
    return () => window.removeEventListener("message", handleMessage);
  }, []);

  // 3. 首次进入时恢复 sessionStorage 中上次选择的 skill（线程优先，其次全局）
  // 已按需求注释：关闭页签后重新打开时，不再从 sessionStorage 自动恢复。
  // useEffect(() => {
  //   const threadKey = getThreadStorageKey(threadId);
  //   const threadSkills = threadKey
  //     ? parseStoredSkills(window.sessionStorage.getItem(threadKey))
  //     : [];
  //   const latestSkills = parseStoredSkills(
  //     window.sessionStorage.getItem(STORAGE_KEYS.latest),
  //   );
  //   const restoredSkills =
  //     threadSkills.length > 0 ? threadSkills : latestSkills;
  //   if (restoredSkills.length === 0) return;
  //   setSelectedSkills(restoredSkills);
  //   setSelectedSkill(restoredSkills[0] ?? null);
  // }, [threadId]);

  // 4. 选择变化时同步到 sessionStorage
  useEffect(() => {
    const threadKey = getThreadStorageKey(threadId);
    if (selectedSkills.length === 0) {
      // 空数组也要同步到存储，避免 UI 状态与缓存不一致
      window.sessionStorage.removeItem(STORAGE_KEYS.latest);
      if (threadKey) {
        window.sessionStorage.removeItem(threadKey);
      }
      return;
    }

    const payload = JSON.stringify(selectedSkills);
    window.sessionStorage.setItem(STORAGE_KEYS.latest, payload);
    if (threadKey) {
      window.sessionStorage.setItem(threadKey, payload);
    }
  }, [selectedSkills, threadId]);

  // 发送选择预定义 skill
  const sendSelectSkill = useCallback(
    (selectedSkills: SelectedSkillPayloadItem[]) => {
      const message = {
        type: POST_MESSAGE_TYPES.SELECT_SKILLS,
        selectedSkills,
      };
      console.log("[useIframeSkill] sendSelectSkill:", message);
      sendToParent(message);
    },
    [],
  );

  const bootstrapAndLockSkills = useCallback(
    async ({
      selectedSkills,
      title,
    }: {
      selectedSkills: SelectedSkillPayloadItem[];
      title: string;
    }) => {
      if (!threadId) {
        toast.error(t.skills.loadFailed, {
          description: t.skills.missingThreadId,
        });
        return false;
      }

      const content_ids = Array.from(
        new Set(
          selectedSkills
            .map((item) => Number(String(item.id).trim()))
            .filter((id) => Number.isFinite(id) && id > 0),
        ),
      );

      if (content_ids.length === 0) {
        toast.error(t.skills.loadFailed, {
          description: t.skills.invalidSkillId,
        });
        return false;
      }

      const languageTypeRaw =
        searchParams.get("languageType")?.trim() ??
        searchParams.get("language_type")?.trim();
      const languageType = languageTypeRaw ? Number(languageTypeRaw) : 0;

      setIsBootstrapping(true);
      toast.loading(t.skills.loading(title), {
        id: "suggest-skill-bootstrap",
      });

      try {
        const result = await bootstrapRemoteSkill({
          thread_id: threadId,
          content_ids,
          language_type: languageType,
          target_dir: "/mnt/user-data/uploads/skill",
          clear_target: true,
        });

        toast.dismiss("suggest-skill-bootstrap");

        if (!result.success) {
          const failedIds = selectedSkills.map((item) =>
            String(item.id).trim(),
          );
          removeFailedSkills(failedIds);
          toast.error(t.skills.loadFailedWithTitle(title), {
            description: result.message || t.skills.unknownError,
          });
          return false;
        }

        sendSelectSkill(selectedSkills);
        const normalizedSkills = selectedSkills.map((item) => ({
          skill_id: String(item.id),
          title: item.name,
        }));
        setSelectedSkill(normalizedSkills[0] ?? null);
        setSelectedSkills(normalizedSkills);

        toast.success(t.skills.loadSuccessWithTitle(title), {
          description:
            result.message || t.skills.createdFiles(result.created_files),
        });

        return true;
      } catch (error) {
        const failedIds = selectedSkills.map((item) => String(item.id).trim());
        removeFailedSkills(failedIds);
        toast.dismiss("suggest-skill-bootstrap");
        const message =
          error instanceof Error
            ? error.message
            : t.skills.networkRequestFailed;
        toast.error(t.skills.loadFailedWithTitle(title), {
          description: message,
        });
        return false;
      } finally {
        setIsBootstrapping(false);
      }
    },
    [removeFailedSkills, searchParams, sendSelectSkill, t.skills, threadId],
  );

  // 打开 skill 选择对话框
  const openSkillDialog = useCallback(() => {
    const message = {
      type: POST_MESSAGE_TYPES.OPEN_SKILL_DIALOG,
      openSkillDialog: true,
    } as const;
    console.log("[useIframeSkill] openSkillDialog:", message);
    sendToParent(message);
  }, []);

  // 清除选中并发送空 selectedSkills 数组给主页
  const clearSkill = useCallback(
    (skillId?: string) => {
      const removeAll = !skillId;
      const nextSelectedSkills = removeAll
        ? []
        : selectedSkills.filter((skill) => skill.skill_id !== String(skillId));

      setSelectedSkills(nextSelectedSkills);
      setSelectedSkill(nextSelectedSkills[0] ?? null);

      // 同步 latest 缓存：仅删除对应 skill（或全部清空）
      const latestSkills = parseStoredSkills(
        window.sessionStorage.getItem(STORAGE_KEYS.latest),
      );
      const nextLatestSkills = removeAll
        ? []
        : latestSkills.filter((skill) => skill.skill_id !== String(skillId));
      if (nextLatestSkills.length > 0) {
        window.sessionStorage.setItem(
          STORAGE_KEYS.latest,
          JSON.stringify(nextLatestSkills),
        );
      } else {
        window.sessionStorage.removeItem(STORAGE_KEYS.latest);
      }

      // 同步线程缓存：保存剩余数组，空则删除 key
      const threadKey = getThreadStorageKey(threadId);
      if (threadKey) {
        if (nextSelectedSkills.length > 0) {
          window.sessionStorage.setItem(
            threadKey,
            JSON.stringify(nextSelectedSkills),
          );
        } else {
          window.sessionStorage.removeItem(threadKey);
        }
      }

      // 通知宿主页当前剩余技能
      const message = {
        type: POST_MESSAGE_TYPES.SELECT_SKILLS,
        selectedSkills: nextSelectedSkills.map((skill) => ({
          id: skill.skill_id,
          name: skill.title,
        })),
      } as const;
      console.log("[useIframeSkill] clearSkill:", message);
      sendToParent(message);
    },
    [selectedSkills, threadId],
  );

  return {
    selectedSkill,
    selectedSkills,
    isBootstrapping,
    sendSelectSkill,
    bootstrapAndLockSkills,
    openSkillDialog,
    clearSkill,
  };
}
