import os
from datetime import datetime, timedelta
from copernicusmarine import subset
import subprocess

class CopernicusDownloader:
    def __init__(self, username="", password=""):
        self.dataset_id = "cmems_mod_ibi_phy_anfc_0.027deg-2D_PT1H-m"
        self.username = username
        self.password = password
        self.output_file   = os.path.join(os.getcwd(), "downloads", "download.nc")
        self.prepared_file = os.path.join(os.getcwd(), "downloads", "download_prepared.nc")
        self.output_grib   = os.path.join(os.getcwd(), "downloads", "download.grib2")
        
        self.lat_min = 0.0
        self.lat_max = 0.0
        self.lon_min = 0.0
        self.lon_max = 0.0
        self.days = 1
        
    def retrieve_grib2(self, lat_min, lat_max, lon_min, lon_max, days):
        self.lat_min = lat_min
        self.lat_max = lat_max
        self.lon_min = lon_min
        self.lon_max = lon_max
        self.days    = days
        # print(f"Démarage du téléchargement avec {lat_min} - {lat_max} - {lon_min} - {lon_max} - {days} ")
        
        self.download(self.output_file)
        self.apply_setreftime(self.output_file,self.prepared_file)
        self.convert_to_grib2(self.prepared_file,self.output_grib)
        self.file_remove(self.output_file)
        return self.output_grib
 
    def file_remove(self,file):
        if os.path.exists(file):
            os.remove(file)
            print(f"✅ File removed : {file}")
        else:
            print(f"❌ File {file} does not exist.")
 
    def download(self,outfile):
        today = datetime.utcnow()
        start_date = today.strftime("%Y-%m-%dT00:00:00")
        end_date = (today + timedelta(days=self.days)).strftime("%Y-%m-%dT23:00:00")

        save_dir = os.path.join(os.getcwd(), "downloads")
        os.makedirs(save_dir, exist_ok=True)

        subset(
            dataset_id=self.dataset_id,
            output_filename=outfile,
            variables=["uo", "vo"], # removed "thetao" (temperature) and "zos" (elevation)
            minimum_longitude=self.lon_min,
            maximum_longitude=self.lon_max,
            minimum_latitude=self.lat_min,
            maximum_latitude=self.lat_max,
            start_datetime=start_date,
            end_datetime=end_date,
            username=self.username,
            password=self.password
        )
        print(f"✅ File downloaded to : {outfile}")
        

    def extract_date_and_time(self,infile):
        # Extract the first timecode of the nc file
        try:
            result = subprocess.run(
                ["cdo", "showtimestamp", infile],
                check=True,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True
            )
    
            # Récupérer le premier timestamp : ex. 2025-05-21T00:00:00
            first_timestamp = result.stdout.strip().split()[0]
            date, time = first_timestamp.split('T')
            return date, time
    
        except subprocess.CalledProcessError as e:
            print(f"[CDO Error] {e.stderr}")
        except Exception as e:
            print(f"[Error] {e}")
        
        return None, None
    
    def apply_setreftime(self,infile,outfile):
        # Apply the command cdo -setreftime,<date>,<heure> <input> <output> to define a reference time
        date, time = self.extract_date_and_time(infile)
        if not date or not time:
            print("Cannot retrieve date/time from this file.")
            return
    
        try:
            subprocess.run(
                ["cdo", f"-setreftime,{date},{time}", infile, outfile],
                check=True
            )
            print(f"✅ File adapted with correct time ref {date} - {time} : {outfile}")
    
        except subprocess.CalledProcessError as e:
            print(f"[Error when setting reference time with CDO -setreftime] {e.stderr}")
    
    
    def convert_to_grib2(self,infile,outfile):
        if not os.path.exists(infile):
            raise FileNotFoundError(f"File not found : {infile}")
        try:
            subprocess.run(["cdo", "-f", "grb2", "copy", infile, outfile], check=True)
            print(f"✅ File converted to grib : {outfile}")
            return outfile
        except subprocess.CalledProcessError as e:
            raise RuntimeError(f"Error when converting with CDO : {e}")
