"use client";

import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { apiClient, API_BASE_URL } from "@/lib/api/client";
import { useAuth } from "@/hooks/useAuth";

// ============================================
// Types
// ============================================
export interface Room {
  id: string;
  name: string;
  type: "dm" | "group" | "channel";
  lastMessage?: string;
  lastMessageAt?: string;
  unreadCount: number;
  participants: Participant[];
  description?: string;
}

export interface Participant {
  userId: string;
  userName: string;
  photo?: string | null;
}

export interface Message {
  id: string;
  roomId: string;
  senderId: string;
  senderName: string;
  senderPhoto?: string | null;
  content: string;
  type: "text" | "file" | "system";
  fileUrl?: string;
  fileName?: string;
  fileMimeType?: string | null;
  reactions: Reaction[];
  threadCount?: number;
  parentId?: string | null;
  isDeleted: boolean;
  createdAt: string;
}

export interface Reaction {
  emoji: string;
  users: { userId: string; userName: string }[];
}

export interface CompanyUser {
  userId: string;
  userName: string;
  deptName?: string;
  positionName?: string;
  photo?: string | null;
}

// ============================================
// API helpers
// ============================================
async function fetchApi<T>(url: string): Promise<T> {
  const res = await apiClient.get(url);
  return res.data?.data ?? res.data;
}

async function postApi<T>(url: string, data?: unknown): Promise<T> {
  const res = await apiClient.post(url, data);
  return res.data?.data ?? res.data;
}

// ============================================
// Hooks
// ============================================
export function useRooms() {
  const { user } = useAuth();
  const companyCode = user?.companyCode || user?.company_code;
  return useQuery<Room[]>({
    queryKey: ["messenger", "rooms", companyCode],
    queryFn: async () => {
      const data = await fetchApi<any[]>("/messenger/rooms");
      return data.map((r) => ({
        id: String(r.id),
        name: r.room_name ?? r.name ?? "",
        type: r.room_type ?? r.type,
        lastMessage: r.last_message ?? r.lastMessage,
        lastMessageAt: r.last_message_at ?? r.lastMessageAt,
        unreadCount: r.unread_count ?? r.unreadCount ?? 0,
        description: r.description,
        participants: (r.participants ?? []).map((p: any) => ({
          userId: p.user_id ?? p.userId,
          userName: p.user_name ?? p.userName,
          photo: p.photo ? `data:image/jpeg;base64,${p.photo}` : null,
        })),
      }));
    },
    refetchInterval: 30000,
  });
}

export function useMessages(roomId: string | null) {
  return useQuery<Message[]>({
    queryKey: ["messenger", "messages", roomId],
    queryFn: async () => {
      const data = await fetchApi<any[]>(`/messenger/rooms/${roomId}/messages`);
      return data.map((m) => ({
        id: String(m.id),
        roomId: String(m.room_id ?? m.roomId),
        senderId: m.sender_id ?? m.senderId,
        senderName: m.sender_name ?? m.senderName ?? m.sender_id,
        senderPhoto: m.sender_photo
          ? `data:image/jpeg;base64,${m.sender_photo}`
          : (m.senderPhoto ?? null),
        content: m.content ?? "",
        type: m.message_type ?? m.type ?? "text",
        fileUrl: m.files?.[0]?.id
          ? `${API_BASE_URL}/messenger/files/${m.files[0].id}`
          : (m.file_url ?? m.fileUrl),
        fileName: m.files?.[0]?.original_name ?? m.file_name ?? m.fileName,
        fileMimeType: m.files?.[0]?.mime_type ?? null,
        reactions: m.reactions ?? [],
        threadCount: m.thread_count ?? m.threadCount ?? 0,
        parentId: m.parent_message_id ?? m.parentId ?? null,
        isDeleted: m.is_deleted ?? m.isDeleted ?? false,
        createdAt: m.created_at ?? m.createdAt,
      }));
    },
    enabled: !!roomId,
  });
}

export function useCompanyUsers() {
  const { user } = useAuth();
  const companyCode = user?.companyCode || user?.company_code;
  return useQuery<CompanyUser[]>({
    queryKey: ["messenger", "users", companyCode],
    queryFn: async () => {
      const data = await fetchApi<any[]>("/messenger/users");
      return data.map((u) => ({
        userId: u.user_id ?? u.userId,
        userName: u.user_name ?? u.userName,
        deptName: u.dept_name ?? u.deptName,
        photo: u.photo ? `data:image/jpeg;base64,${u.photo}` : null,
      }));
    },
  });
}

export function useUnreadCount() {
  return useQuery<number>({
    queryKey: ["messenger", "unread"],
    queryFn: () => fetchApi("/messenger/unread"),
    refetchInterval: 15000,
  });
}

export function useSendMessage() {
  const qc = useQueryClient();
  const { user } = useAuth();
  return useMutation({
    mutationFn: (payload: { roomId: string; content: string; type?: string; parentId?: string | null; fileUrl?: string; fileName?: string }) =>
      postApi(`/messenger/rooms/${payload.roomId}/messages`, {
        content: payload.content,
        type: payload.type,
        parentId: payload.parentId,
        file_url: payload.fileUrl,
        file_name: payload.fileName,
      }),
    onMutate: async (variables) => {
      const queryKey = ["messenger", "messages", variables.roomId];
      await qc.cancelQueries({ queryKey });
      const previous = qc.getQueryData<Message[]>(queryKey);
      const optimistic: Message = {
        id: `optimistic-${Date.now()}`,
        roomId: variables.roomId,
        senderId: user?.userId ?? "me",
        senderName: "",
        content: variables.content,
        type: (variables.type as Message["type"]) ?? "text",
        reactions: [],
        isDeleted: false,
        createdAt: new Date().toISOString(),
      };
      qc.setQueryData<Message[]>(queryKey, (old) => [...(old ?? []), optimistic]);
      return { previous, queryKey };
    },
    onError: (_err, _vars, context) => {
      if (context) qc.setQueryData(context.queryKey, context.previous);
    },
    onSuccess: (_data, variables) => {
      qc.invalidateQueries({ queryKey: ["messenger", "messages", variables.roomId] });
      qc.invalidateQueries({ queryKey: ["messenger", "rooms"] });
    },
  });
}

export function useCreateRoom() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (payload: { type: "dm" | "group" | "channel"; name?: string; description?: string; participantIds: string[] }) =>
      postApi<Room>("/messenger/rooms", payload),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["messenger", "rooms"] });
    },
  });
}

export function useMarkAsRead() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (roomId: string) => postApi(`/messenger/rooms/${roomId}/read`),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["messenger", "unread"] });
      qc.invalidateQueries({ queryKey: ["messenger", "rooms"] });
    },
  });
}

export function useAddReaction() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (payload: { messageId: string; roomId: string; emoji: string }) =>
      postApi(`/messenger/messages/${payload.messageId}/reactions`, { emoji: payload.emoji }),
    onSuccess: (_data, variables) => {
      qc.invalidateQueries({ queryKey: ["messenger", "messages", variables.roomId] });
    },
  });
}

export function useUpdateRoom() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: ({ roomId, name }: { roomId: string; name: string }) =>
      apiClient.put(`/messenger/rooms/${roomId}`, { room_name: name }).then((res) => res.data?.data ?? res.data),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: ["messenger", "rooms"] });
    },
  });
}

export function useUploadFile() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async ({ file, roomId }: { file: File; roomId: string }) => {
      const formData = new FormData();
      formData.append("files", file);
      formData.append("room_id", roomId);
      const res = await apiClient.post("/messenger/files/upload", formData, {
        headers: { "Content-Type": "multipart/form-data" },
      });
      return res.data?.data ?? res.data;
    },
    onSuccess: (_data, variables) => {
      qc.invalidateQueries({ queryKey: ["messenger", "messages", variables.roomId] });
      qc.invalidateQueries({ queryKey: ["messenger", "rooms"] });
    },
  });
}
