import {
  getDocs,
  query,
  orderBy,
  limit,
  CollectionReference,
  Timestamp,
  addDoc,
  updateDoc,
  doc,
  deleteDoc,
} from 'firebase/firestore';
import {
  ref as storageRef,
  uploadBytes,
  getDownloadURL,
  deleteObject,
} from 'firebase/storage';
import type { DocumentData } from 'firebase/firestore';
import { httpsCallable } from 'firebase/functions';
import type { CreateProgressResponse, CertificateResponse } from '@/types';
const FUNCTIONS_BASE_URL = import.meta.env.VITE_FUNCTIONS_BASE_URL;

export const fetchLatestDocumentNumber = async (
  collectionRef: CollectionReference<DocumentData>,
  orderByField: string
): Promise<number> => {
  try {
    const q = query(collectionRef, orderBy(orderByField, 'desc'), limit(1));
    const querySnapshot = await getDocs(q);

    if (!querySnapshot.empty) {
      const doc = querySnapshot.docs[0];
      if (!doc) return 1;
      const data = doc.data();
      const value = data[orderByField];
      return (typeof value === 'number' ? value : 0) + 1;
    } else {
      return 1;
    }
  } catch (error) {
    console.error('Error fetching the latest document number:', error);
    throw error;
  }
};
// Uploads a file to Firebase Storage and returns its download URL.
export const uploadFileAndGetURL = async (
  file: File | null,
  path: string
): Promise<string | null> => {
  const { $firebase } = useNuxtApp();
  const storage = $firebase.storage;

  try {
    if (!file) return null;
    const fileRef = storageRef(storage, path); // path inside the bucket
    await uploadBytes(fileRef, file); // upload the file
    return await getDownloadURL(fileRef); // get the URL after upload
  } catch (error) {
    console.error('Error uploading file:', error);
    throw error;
  }
};
// Delete a file from Firebase Storage by its path

export async function deleteFileFromStorage(path: string): Promise<void> {
  const { $firebase } = useNuxtApp();
  const storage = $firebase.storage;

  try {
    const fileRef = storageRef(storage, path);
    await deleteObject(fileRef);
  } catch (error) {
    console.error('Error deleting file from storage:', error);
    throw error;
  }
}
//Add a new document to Firestore

export async function uploadDataToFirestore(
  collectionRef: CollectionReference<DocumentData>,
  data: Record<string, any>
) {
  try {
    return await addDoc(collectionRef, data);
  } catch (error) {
    console.error('Error uploading data to Firestore:', error);
    throw error;
  }
}
//Update a document in Firestore by its ID

export async function updateDataInFirestore(
  collectionRef: CollectionReference<DocumentData>,
  id: string,
  data: Record<string, any>
): Promise<void> {
  try {
    const docRef = doc(collectionRef, id);
    await updateDoc(docRef, data);
  } catch (error) {
    console.error('Error updating data in Firestore:', error);
    throw error;
  }
}
// Deletes a specific document from a Firestore collection.
export async function deleteDataFromFirestore(
  collectionRef: CollectionReference,
  id: string
): Promise<void> {
  try {
    const docRef = doc(collectionRef, id);
    await deleteDoc(docRef);
  } catch (error) {
    console.error('Error deleting data from Firestore:', error);
    throw error;
  }
}

export const deleteUserFromAuthentication = async (uid: string) => {
  console.log('firebasefunctioncalled', uid);
  const { $firebase } = useNuxtApp();
  const functions = $firebase.functions;
  const deleteUserFunction = httpsCallable(functions, 'deleteUser');

  try {
    const result = await deleteUserFunction({ uid: 'some-user-id' });
    console.log(
      `User with UID: ${uid} has been deleted from Firebase Authentication.`
    );
    return result.data;
  } catch (error) {
    console.error('Error deleting user:', error);
    throw error;
  }
};
export function formatDate(timestamp: Timestamp): string {
  // Check if timestamp is not provided or not a valid Firebase Timestamp
  if (!timestamp || !(timestamp instanceof Timestamp)) {
    console.warn('Invalid timestamp provided to formatDate function.');
    return '';
  }

  let date;
  try {
    date = timestamp.toDate();
  } catch (error) {
    console.error('Error converting timestamp to date:', error);
    return '';
  }

  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0'); // Months are 0-indexed in JS
  const day = String(date.getDate()).padStart(2, '0');

  return `${year}-${month}-${day}`;
}
export function formatKoreanDate(timestamp: Timestamp): string {
  // Check if timestamp is not provided or not a valid Firebase Timestamp
  if (!timestamp || !(timestamp instanceof Timestamp)) {
    console.warn('Invalid timestamp provided to formatDate function.');
    return '';
  }

  let date;
  try {
    date = timestamp.toDate();
  } catch (error) {
    console.error('Error converting timestamp to date:', error);
    return '';
  }

  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0'); // Months are 0-indexed in JS
  const day = String(date.getDate()).padStart(2, '0');

  return `${year}년 ${month}월 ${day}일`;
}
//check email duplicate before Auth
export const checkEmailDuplicate = async (email: string) => {
  try {
    console.log('atfirebaseUtils,email is', email);
    console.log(
      'FUNCTIONS_BASE_URL',
      `${FUNCTIONS_BASE_URL}/checkEmailDuplicate`
    );
    const response = await $fetch<{ status: string; message?: string }>(
      `${FUNCTIONS_BASE_URL}/checkEmailDuplicate`,
      {
        method: 'POST',
        body: { email: email },
        credentials: 'include',
      }
    );

    if (response.status === 'exists') {
      return { status: 'exists' };
    } else if (response.status === 'available') {
      return { status: 'available' };
    } else {
      throw new Error(
        response.message || 'Unexpected response from the server.'
      );
    }
  } catch (error: any) {
    console.error('Error checking email:', error);
    return { status: 'error', message: error.message };
  }
};

export const generateCertificate = async (
  name: string,
  courseTitle: string,
  finishedDate: string
): Promise<{
  imageUrl?: string;
  pdfUrl?: string;
  uniqueId?: string;
  error?: string;
}> => {
  try {
    console.log(
      'generateFunction called with',
      name,
      'name',
      courseTitle,
      'coursetitle',
      finishedDate,
      'finishedDate'
    );
    const result = await certificateFunction({
      name,
      courseTitle,
      completeAt: finishedDate,
    });

    const responseData = result.data as CertificateResponse;

    if (responseData.status === 'success' && responseData.message) {
      console.log('Image URL:', responseData.message.imageUrl);
      console.log('PDF URL:', responseData.message.pdfUrl);
      console.log('Unique ID:', responseData.message.uniqueId);
      return {
        imageUrl: responseData.message.imageUrl,
        pdfUrl: responseData.message.pdfUrl,
        uniqueId: responseData.message.uniqueId,
      };
    } else {
      console.error('Failed to generate certificate');
      return {
        error: 'Failed to generate certificate',
      };
    }
  } catch (error: any) {
    console.error('Error calling the function:', error);
    return {
      error: error.message || 'Error calling the function',
    };
  }
};
export const createProgressFunction = async (
  data: any
): Promise<CreateProgressResponse> => {
  const { $firebase } = useNuxtApp();
  const functions = $firebase.functions;
  const callableFunction = httpsCallable(functions, 'createProgress');

  try {
    const response = await callableFunction(data);
    return response.data as CreateProgressResponse; // Type-casting the response data
  } catch (error) {
    console.error('Error calling createProgress function:', error);
    throw error;
  }
};
export const getResizedImageURL = async (
  originalURL: string,
  originalName: string
): Promise<string> => {
  const { $firebase } = useNuxtApp();
  const storage = $firebase.storage;

  // Decode the originalURL
  const decodedURL = decodeURIComponent(originalURL);

  // Extract the base part of the name without extension
  const baseName = originalName.split('.').slice(0, -1).join('.');

  // Construct the expected name for the resized image
  const resizedName = `${baseName}_500x500.webp`;

  // Extract the course name from the decoded URL
  const courseNameMatch = decodedURL.match(/thumbnail\/(.*?)\/[^/]+$/);
  const courseName = courseNameMatch ? courseNameMatch[1] : '';

  // Construct the expected path for the resized image
  const expectedPath = `boards/course/thumbnail/${courseName}/${resizedName}`;

  // Check if the resized image exists
  try {
    const resizedImageRef = storageRef(storage, expectedPath);
    const resizedImageURL = await getDownloadURL(resizedImageRef);
    return resizedImageURL;
  } catch (error) {
    // If the resized image does not exist, return the original URL
    return originalURL;
  }
};

//certificate generate call to firebase cloud functions
const certificateFunction = (data: {
  name: string;
  courseTitle: string;
  completeAt: string;
}) => {
  const { $firebase } = useNuxtApp();
  const functions = $firebase.functions;
  return httpsCallable(functions, 'generateCertificate')(data);
};
