import os
import time
import requests
import cloudinary
from cloudinary import uploader, api
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

# Configure Cloudinary with your credentials
cloudinary.config(
    # cloud_name='df667rfp2',
    cloud_name='dhuti2qu7',

    # api_key='843839891244491',
    api_key='538825812971112',

    # api_secret='GUjP1I7lpjrig5Z7IXOF0WDzOyo'
    api_secret='HDbeJCSBUvoHhnyclj7aF_NW5a0'

)

local_folder_path_path = 'public/uploads'
cloudinary_folder_path_path = 'public/uploads'

def check_internet():
    try:
        response = requests.get('http://www.google.com', timeout=5)
        response.raise_for_status()
        return True
    except requests.RequestException:
        return False

def upload_folder(local_folder_path, cloudinary_folder_path):
    if not check_internet():
        print("You are offline. Cannot upload to Cloudinary.")
        return

    local_items = os.listdir(local_folder_path)
    cloudinary_items = api.resources(type="upload", prefix=cloudinary_folder_path, max_results=500)

    cloudinary_file_paths = [item['public_id'] for item in cloudinary_items['resources']]

    for item in local_items:
        item_path = os.path.join(local_folder_path, item)

        if os.path.isfile(item_path):
            cloudinary_file_path = os.path.join(cloudinary_folder_path, item)
            if cloudinary_file_path not in cloudinary_file_paths:
                upload_file(item_path, cloudinary_file_path)

# def upload_file(local_path, cloudinary_path):
#     public_id = os.path.basename(local_path)
#     full_public_id = os.path.join(cloudinary_path)

#     print(f'Checking if {full_public_id} exists on Cloudinary')

#     try:
#         existing_file = api.resource(full_public_id, type="upload", resource_type="image")
#     except cloudinary.exceptions.NotFound:
#         existing_file = None

#     if not existing_file:
#         print(f'Uploading {local_path} to {full_public_id}')
#         try:
#             uploader.upload(local_path, public_id=full_public_id, resource_type="image")
#         except cloudinary.exceptions.Error as e:
#             print(f'Error uploading file: {e}')
#     else:
#         print(f'{full_public_id} already exists on Cloudinary. Skipped.')
                


def upload_file(local_path, cloudinary_path):
    public_id = os.path.basename(local_path)
    full_public_id = os.path.join(cloudinary_path)

    print(f'Checking if {full_public_id} exists on Cloudinary')

    try:
        existing_file = api.resource(full_public_id, type="upload")
    except cloudinary.exceptions.NotFound:
        existing_file = None

    if not existing_file:
        print(f'Uploading {local_path} to {full_public_id}')

        # Determine the resource type based on file extension
        resource_type = 'image'  # default
        if local_path.endswith('.xlsx'):
            resource_type = 'raw'  # use 'raw' for non-image files like .xlsx

        try:
            uploader.upload(local_path, public_id=full_public_id, resource_type=resource_type)
        except cloudinary.exceptions.Error as e:
            print(f'Error uploading file: {e}')
    else:
        print(f'{full_public_id} already exists on Cloudinary. Skipped.')

                

def download_file(cloudinary_path, local_folder_path):
    try:
        cloudinary_url = cloudinary.utils.cloudinary_url(cloudinary_path)[0]
        filename = os.path.basename(cloudinary_path)
        local_file_path = os.path.join(local_folder_path, filename)

        print(f'Downloading {cloudinary_url} to {local_file_path}')

        response = requests.get(cloudinary_url)
        if response.status_code == 200:
            with open(local_file_path, 'wb') as local_file:
                local_file.write(response.content)
            print(f'Successfully downloaded {cloudinary_url} to {local_file_path}')
        else:
            print(f'Failed to download {cloudinary_url}. HTTP Status Code: {response.status_code}')
    except Exception as e:
        print(f'Error downloading file: {e}')

class MyHandler(FileSystemEventHandler):
    def on_created(self, event):
        if event.is_directory:
            self.sync_folder(event.src_path)

    def on_deleted(self, event):
        if event.is_directory:
            self.sync_folder(event.src_path)

    def on_modified(self, event):
        if event.is_directory:
            self.sync_folder(event.src_path)

    def sync_folder(self, local_folder_path):
        upload_folder(local_folder_path, cloudinary_folder_path_path)
        download_missing_files(local_folder_path, cloudinary_folder_path_path)

def download_missing_files(local_folder_path, cloudinary_folder_path):
    local_items = os.listdir(local_folder_path)
    cloudinary_items = api.resources(type="upload", prefix=cloudinary_folder_path, max_results=500)

    for item in cloudinary_items['resources']:
        cloudinary_path = item['public_id']
        if cloudinary_path.endswith('/'):
            continue  # Skip folders

        filename = os.path.basename(cloudinary_path)
        local_file_path = os.path.join(local_folder_path, filename)

        if filename not in local_items:
            download_file(cloudinary_path, local_folder_path)

if __name__ == "__main__":
    event_handler = MyHandler()
    observer = Observer()
    observer.schedule(event_handler, local_folder_path_path, recursive=True)

    print(f"Monitoring local folder: {local_folder_path_path}")
    observer.start()

    try:
        while True:
            time.sleep(60)
            upload_folder(local_folder_path_path, cloudinary_folder_path_path)
            download_missing_files(local_folder_path_path, cloudinary_folder_path_path)
    except KeyboardInterrupt:
        observer.stop()
        print("Observer stopped.")
        observer.join()
