import { useState, useEffect, useCallback } from "react";
import { supabase } from "@/integrations/supabase/client";
import { useToast } from "@/hooks/use-toast";

interface DriveFile {
  id: string;
  name: string;
  mimeType: string;
  iconLink?: string;
  webViewLink?: string;
  size?: string;
  modifiedTime?: string;
}

interface SharedDriveFile {
  id: string;
  drive_file_id: string;
  drive_file_name: string;
  drive_mime_type: string | null;
  drive_icon_link: string | null;
  drive_web_view_link: string | null;
  is_folder: boolean;
  shared_by: string | null;
  association_ids: string[];
  visibility: string[];
  created_at: string;
}

export function useGoogleDrive() {
  const [isConnected, setIsConnected] = useState(false);
  const [loading, setLoading] = useState(true);
  const [driveFiles, setDriveFiles] = useState<DriveFile[]>([]);
  const [browsing, setBrowsing] = useState(false);
  const [sharedFiles, setSharedFiles] = useState<SharedDriveFile[]>([]);
  const { toast } = useToast();

  const getAuthHeaders = useCallback(async () => {
    const { data: { session } } = await supabase.auth.getSession();
    if (!session?.access_token) throw new Error("Not logged in");
    return { Authorization: `Bearer ${session.access_token}` };
  }, []);

  const getRedirectUri = useCallback(() => {
    return `${window.location.origin}${window.location.pathname}`;
  }, []);

  const checkConnection = useCallback(async () => {
    try {
      const headers = await getAuthHeaders();
      const { data, error } = await supabase.functions.invoke("google-drive-auth", {
        body: { action: "check_status" },
        headers,
      });
      if (error) throw error;
      setIsConnected(data?.connected ?? false);
    } catch {
      setIsConnected(false);
    } finally {
      setLoading(false);
    }
  }, [getAuthHeaders]);

  useEffect(() => {
    checkConnection();
  }, [checkConnection]);

  const connect = useCallback(async () => {
    try {
      const headers = await getAuthHeaders();
      const redirectUri = getRedirectUri();
      const { data, error } = await supabase.functions.invoke("google-drive-auth", {
        body: { action: "get_auth_url", redirect_uri: redirectUri },
        headers,
      });
      if (error) throw error;
      if (data?.error) throw new Error(data.error);
      if (data?.url) {
        window.location.href = data.url;
      }
    } catch (err: any) {
      toast({ title: "Error", description: err.message, variant: "destructive" });
    }
  }, [getAuthHeaders, getRedirectUri, toast]);

  const handleOAuthCallback = useCallback(async (code: string) => {
    try {
      const headers = await getAuthHeaders();
      const redirectUri = getRedirectUri();
      const { data, error } = await supabase.functions.invoke("google-drive-auth", {
        body: { action: "exchange_code", code, redirect_uri: redirectUri },
        headers,
      });
      if (error) throw error;
      if (data?.error) throw new Error(data.error);
      setIsConnected(true);
      toast({ title: "Connected", description: "Google linked successfully." });
      window.history.replaceState({}, "", window.location.pathname);
    } catch (err: any) {
      toast({ title: "Connection Failed", description: err.message, variant: "destructive" });
    }
  }, [getAuthHeaders, getRedirectUri, toast]);

  const disconnect = useCallback(async () => {
    try {
      const headers = await getAuthHeaders();
      const { data, error } = await supabase.functions.invoke("google-drive-auth", {
        body: { action: "disconnect" },
        headers,
      });
      if (error) throw error;
      if (data?.error) throw new Error(data.error);
      setIsConnected(false);
      setDriveFiles([]);
      toast({ title: "Disconnected", description: "Google has been disconnected." });
    } catch (err: any) {
      toast({ title: "Error", description: err.message, variant: "destructive" });
    }
  }, [getAuthHeaders, toast]);

  const listSharedDrives = useCallback(async () => {
    setBrowsing(true);
    try {
      const headers = await getAuthHeaders();
      const { data, error } = await supabase.functions.invoke("google-drive-proxy", {
        body: { action: "list_shared_drives" },
        headers,
      });
      if (error) throw error;
      if (data?.error) throw new Error(data.error);
      const drives = (data?.drives || []).map((d: any) => ({
        id: d.id,
        name: d.name,
        mimeType: "application/vnd.google-apps.folder",
      }));
      setDriveFiles(drives);
    } catch (err: any) {
      toast({ title: "Error listing shared drives", description: err.message, variant: "destructive" });
      setDriveFiles([]);
    } finally {
      setBrowsing(false);
    }
  }, [getAuthHeaders, toast]);

  const browseFiles = useCallback(async (folderId?: string) => {
    setBrowsing(true);
    try {
      const headers = await getAuthHeaders();
      const { data, error } = await supabase.functions.invoke("google-drive-proxy", {
        body: { action: "list_files", folder_id: folderId || null },
        headers,
      });
      if (error) throw error;
      if (data?.error) throw new Error(data.error);
      setDriveFiles(data?.files || []);
    } catch (err: any) {
      toast({ title: "Error browsing Drive", description: err.message, variant: "destructive" });
      setDriveFiles([]);
    } finally {
      setBrowsing(false);
    }
  }, [getAuthHeaders, toast]);

  const fetchSharedFiles = useCallback(async (boardAssociationIds?: string[]) => {
    let query = supabase.from("shared_drive_files").select("*").order("created_at", { ascending: false });
    if (boardAssociationIds?.length) {
      // Restrict to files explicitly shared with the selected association(s)
      query = query.overlaps("association_ids", boardAssociationIds);
    }
    const { data, error } = await query;
    if (!error) setSharedFiles((data as SharedDriveFile[]) || []);
  }, []);

  const shareFiles = useCallback(async (
    files: DriveFile[],
    visibility: string[],
    associationIds: string[]
  ) => {
    try {
      const { data: { user } } = await supabase.auth.getUser();
      const records = files.map((f) => ({
        drive_file_id: f.id,
        drive_file_name: f.name,
        drive_mime_type: f.mimeType,
        drive_icon_link: f.iconLink || null,
        drive_web_view_link: f.webViewLink || null,
        is_folder: f.mimeType === "application/vnd.google-apps.folder",
        shared_by: user?.id,
        visibility,
        association_ids: associationIds,
      }));

      const { error } = await supabase.from("shared_drive_files").insert(records);
      if (error) throw error;
      toast({ title: "Files shared", description: `${files.length} item(s) shared successfully.` });
      await fetchSharedFiles();
    } catch (err: any) {
      toast({ title: "Error sharing files", description: err.message, variant: "destructive" });
    }
  }, [toast, fetchSharedFiles]);

  const unshareFile = useCallback(async (id: string) => {
    try {
      const { error } = await supabase.from("shared_drive_files").delete().eq("id", id);
      if (error) throw error;
      setSharedFiles((prev) => prev.filter((f) => f.id !== id));
      toast({ title: "Removed", description: "File is no longer shared." });
    } catch (err: any) {
      toast({ title: "Error", description: err.message, variant: "destructive" });
    }
  }, [toast]);

  const downloadFile = useCallback(async (driveFileId: string, fileName: string) => {
    try {
      const headers = await getAuthHeaders();
      const { data, error } = await supabase.functions.invoke("google-drive-proxy", {
        body: { action: "download_file", file_id: driveFileId },
        headers,
      });
      if (error) throw error;
      if (!(data instanceof Blob) && data?.error) throw new Error(data.error);

      const blob = data instanceof Blob ? data : new Blob([JSON.stringify(data)]);
      const { saveFile } = await import("@/lib/saveFile");
      await saveFile(blob, { suggestedName: fileName, mimeType: blob.type });
    } catch (err: any) {
      toast({ title: "Download failed", description: err.message, variant: "destructive" });
    }
  }, [getAuthHeaders, toast]);

  const uploadFile = useCallback(async (
    file: File,
    parentFolderId?: string
  ): Promise<{ success: boolean; fileId?: string }> => {
    try {
      const headers = await getAuthHeaders();
      const arrayBuffer = await file.arrayBuffer();
      const bytes = new Uint8Array(arrayBuffer);
      let binary = "";
      for (let i = 0; i < bytes.length; i++) {
        binary += String.fromCharCode(bytes[i]);
      }
      const base64 = btoa(binary);

      const { data, error } = await supabase.functions.invoke("google-drive-proxy", {
        body: {
          action: "upload_file",
          file_name: file.name,
          file_base64: base64,
          mime_type: file.type || "application/octet-stream",
          parent_folder_id: parentFolderId || null,
        },
        headers,
      });
      if (error) throw error;
      if (data?.error) throw new Error(data.error);
      return { success: true, fileId: data?.file?.id };
    } catch (err: any) {
      console.error("Drive upload failed:", err);
      return { success: false };
    }
  }, [getAuthHeaders]);

  const createFolder = useCallback(async (
    folderName: string,
    parentFolderId?: string
  ): Promise<string | null> => {
    try {
      const headers = await getAuthHeaders();
      const { data, error } = await supabase.functions.invoke("google-drive-proxy", {
        body: {
          action: "create_folder",
          folder_name: folderName,
          parent_folder_id: parentFolderId || null,
        },
        headers,
      });
      if (error) throw error;
      if (data?.error) throw new Error(data.error);
      return data?.folder?.id || null;
    } catch (err: any) {
      console.error("Drive folder creation failed:", err);
      return null;
    }
  }, [getAuthHeaders]);

  return {
    isConnected,
    loading,
    driveFiles,
    browsing,
    sharedFiles,
    connect,
    disconnect,
    handleOAuthCallback,
    listSharedDrives,
    browseFiles,
    fetchSharedFiles,
    shareFiles,
    unshareFile,
    downloadFile,
    uploadFile,
    createFolder,
    checkConnection,
  };
}
