import argparse
import os, glob
import subprocess
from datetime import datetime, timedelta
import re
from gpsdate import mkdate, gpsdate
from nasa_gnss_data import local_nasa_gnss
from aiub_gnss_data import local_aiub_gnss
import shutil
from satellite_info import  sat_ant_info
from pathlib import Path

__authors__ = ["Ming Chen"]
__license__ = "Public Domain"
__maintainer__ = "Ming Chen"
__email__ = "ming.chen@noaa.gov"
__date__  = "April 22, 2026"

'''
#####################################################################
# 
# generate_bern_sessions.py
#
# Purpose:
# This python script is used to handle the BERNESE sessions.
##
# History:  
#       Created by: Ming Chen 2026/04/22
#                   ming.chen@noaa.gov
# 
# Usage: python .py start_datetime end_datetime
# the datetime in %Y-%m-%dT%H:%M:%S format
#
#
#####################################################################

'''
def bernese_datapool_subdir(mission, satidx,codcom='RTM'):
    leoinfo = sat_ant_info(mission, satidx=satidx)
    satname, satsvn= leoinfo['satname'], leoinfo['satsvn']
    subdir = f'{codcom}{satname}'
    return subdir
    

def remove_link_if_exists(link_path):
    """
    Checks if a symbolic link exists at the given path and removes it if it does.

    Args:
        link_path: The path to the symbolic link.
    """
    status = True
    if os.path.lexists(link_path):
       os.unlink(link_path)
       print(f"Symbolic link '{link_path}' removed.")

    return(status)

def bernese_path_exists():
   # bernese
   BERN_U,BERN_P,BERN_D = os.getenv("U"),os.getenv("P"),os.getenv("D")
   bern_path = os.path.isdir(BERN_U) and \
            os.path.isdir(BERN_P) and os.path.isdir(BERN_D)
   if not bern_path:
      print('BERN DataPool path, or Campaign path,not exist ...')
      return False
   else:
     return True

def bernese_gnss_inputs(gnss_prod, utc_time, data_source='nasa', codcom = 'RTM', **kwargs):
    
    gnss_latency = kwargs.get('gnss_latency', 3) 
    subdir = kwargs.get('datapool_subdir', codcom) 

    if not bernese_path_exists: return False
    pdate = utc_time.strftime('%Y%m%d')
    pdate = gpsdate(pdate)
    year, doy, ymd = pdate.year, pdate.doy, pdate.ymd
    gweek, gday = pdate.gweek, pdate.gday 
 
 
    if not bernese_path_exists: return False

    datapool = os.getenv("D")
    plink = codcom.upper() 
    gnss_flink = {
             'erp': f"{plink}{gweek}{gday}.ERP", 
             'orb': f"{plink}{gweek}{gday}.SP3", 
             'clk': f"{plink}_{year}{doy}.CLK",  
             'bia': f"{plink}_{year}{doy}.BIA"
            }
    fzip = ['.Z', '.gz']

    # gnss_prod = 'COD0OPSULT'
    gnss_time = utc_time - timedelta(hours=gnss_latency)
    ymd = gnss_time.strftime('%Y%m%d')
    h =  int(gnss_time.strftime('%H'))
    h = (h // 6) * 6
    hh = f'{h:02d}'
    if data_source.upper() == 'AIUB':
       gnss_flist = local_aiub_gnss(gnss_prod, ymd, hh=hh)
    else: 
       gnss_flist = local_nasa_gnss(gnss_prod, ymd, hh=hh)
    gnsspool_path = f"{datapool}/{subdir}/{year}{doy}"
    print(gnsspool_path)
    os.makedirs(gnsspool_path, exist_ok = True) 
    #print(gnss_flist)
    for k in gnss_flist:
       fn = gnss_flist[k] 
       fvalid = os.path.isfile(fn) and os.path.getsize(fn) > 0
       if not fvalid:
          print(f"{fn} not exists ....")
          return False

       fzip = ['.Z', '.gz']
       fsuffix = Path(fn).suffix
       fl = f'{gnsspool_path}/{gnss_flink[k]}'
       if fsuffix in fzip:
          fl = f'{fl}{fsuffix}'
   
       print(f'make link: {fn} {fl}')
       if remove_link_if_exists(fl):
             os.symlink(fn, fl)
    return True


def bernese_leornx_inputs(leo_conf:dict,**kwargs):
    if not bernese_path_exists: return False
    leo = leo_conf
    if 'mission' not in leo: return False
    
    mission = leo['mission']
    leoinfo = sat_ant_info(mission)
    if leoinfo is None:
       print(f"invalid mission {mission} ...")
       return False
    nsat = leoinfo['nsats'] ; nant =  leoinfo["nant"]
    leosats = [i+1 for i in range(nsat)]
    leoants = [i+1 for i in range(nant)]
    if leo['satidx'] > 0: leosats = [leo['satidx']]   
    if leo['antidx'] > 0: leoants = [leo['antidx']]   
    #session_tag = '0' # '0' '[A-Z]'
    session_tag = leo['session'].upper()
    mission_tag = leo['mission'].upper()
    tstart =  leo['tstart'].strftime("%Y%m%dT%H%M%S")
    tend =    leo['tend'].strftime("%Y%m%dT%H%M%S")
    mydate = leo['tend']
    year = mydate.strftime('%Y') ; doy = mydate.strftime('%j')
    yy =  mydate.strftime('%y')  
    HM = mydate.strftime('%H%M') 

    datapool = os.getenv("D"); BERN_P = os.getenv("P")
    umd_data_path  = os.getenv("umd_data") 
    leo_data_path  = os.path.join(umd_data_path,leo['mission'])
    leo_att_path = f'{leo_data_path}/leoAtt/{year}.{doy}'
    leo_rnx_path = f'{leo_data_path}/podRnx/{year}.{doy}'
    subdir = kwargs.get('datapool_subdir', mission_tag) 
    rnxpool_path  = f'{datapool}/{subdir}/{year}{doy}'
    os.makedirs(rnxpool_path, exist_ok = True) 
  
    for satidx in leosats:
       for antidx in leoants:
          leoinfo = sat_ant_info(mission, satidx=satidx, antidx=antidx)
          satname, satsvn, antsvn = leoinfo['satname'], leoinfo['satsvn'],leoinfo['antsvn'] 
 
          bernid = leoinfo['bernid']
          campaign = bernid.upper()+str(year)[2:4]+str(doy)

          # link leo files     
          frnx_file = f"{mission}_{tstart}_{tend}_{satsvn}_{antsvn}.rnx"
          frnx_link = f'{satname}{doy}{session_tag}.{year[2:]}O_{HM}_A{antsvn}'
          rnx_file0 = os.path.join(leo_rnx_path, frnx_file)
          rnx_file = os.path.join(leo_rnx_path, frnx_link)
          
          flink = os.path.join(rnxpool_path, frnx_link)
          remove_link_if_exists(flink)
          if os.path.isfile(rnx_file0):
              #shutil.move(rnx_file0,rnx_file)
              print(f'make link: {rnx_file0} {flink}')
              os.symlink(rnx_file0, flink)
              return True
          else:
              print(f'make link error: {rnx_file0} not exist ..')
              return False

def bernese_leoatt_inputs(leo_conf:dict,**kwargs):
    if not bernese_path_exists: return False
    leo = leo_conf
    if 'mission' not in leo: return False
    
    mission = leo['mission']
    leoinfo = sat_ant_info(mission)
    if leoinfo is None:
       print(f"invalid mission {mission} ...")
       return False
    nsat = leoinfo['nsats'] ; nant = leoinfo['nant']
    leosats = [i+1 for i in range(nsat)]
    leoants = [i+1 for i in range(nant)]
    if leo['satidx'] > 0: leosats = [leo['satidx']]   
    if leo['antidx'] > 0: leoants = [leo['antidx']]   
    #session_tag = '0' # '0' '[A-Z]'
    session_tag = leo['session'].upper()
    mission_tag = leo['mission'].upper()
    tstart =  leo['tstart'].strftime("%Y%m%dT%H%M%S")
    tend =    leo['tend'].strftime("%Y%m%dT%H%M%S")
    mydate = leo['tend']
    year = mydate.strftime('%Y') ; doy = mydate.strftime('%j')
    yy =  mydate.strftime('%y')  
    HM = mydate.strftime('%H%M') 
    datapool = os.getenv("D"); BERN_P = os.getenv("P")
    umd_data_path  = os.getenv("umd_data") 
    leo_data_path  = os.path.join(umd_data_path,leo['mission'])
    leo_att_path = f'{leo_data_path}/leoAtt/{year}.{doy}'
    subdir = kwargs.get('datapool_subdir', mission_tag) 
    attpool_path  = f'{datapool}/{subdir}/{year}{doy}'
    os.makedirs(attpool_path, exist_ok = True) 
 
    for satidx in leosats:
        leoinfo = sat_ant_info(mission, satidx=satidx)
        satname, satsvn= leoinfo['satname'], leoinfo['satsvn']
 
        # link leo files     
        fatt_file = f"{mission}_{tstart}_{tend}_{satsvn}.att"
        fatt_link = f'{satname}{year[2:]}{doy}{session_tag}_{HM}.ATT'
        att_file0 = os.path.join(leo_att_path, fatt_file)
        att_file = os.path.join(leo_att_path, fatt_link)

        flink = os.path.join(attpool_path, fatt_link)
        if os.path.isfile(att_file0):
           #flink = os.path.join(attpool_path, fatt_link)
           #shutil.move(att_file0,att_file)
           print(f'make link: {att_file0} {flink}')
           if remove_link_if_exists(flink): os.symlink(att_file0, flink)
           return True
              
        else:
           print(f'make link error: {att_file0} not exist ..')
           return False

if __name__ == "__main__":

   # Parse command-line arguments
   parser = argparse.ArgumentParser(description="Python equivalent of s06_run_bernese.bash")
   parser.add_argument("-m", "--codcom",   default="RTM", help="GNSS product")
   parser.add_argument("-t", "--session", choices=["daily", "hourly"], default="daily", help="Session type")
   parser.add_argument("--gnss-prod", choices=["COD0OPSULT","COD0OPSRAP" ],  default="COD0OPSULT", help="GNSS product")
   parser.add_argument("--gnss-latency", default=3,type=int, help="gnss productrelease latency")
   parser.add_argument("--gnss-source", choices=["NASA","AIUB"],  default="NASA", help="GNSS data source")
   parser.add_argument("--satidx", type=int, default=-1, help="Satellite index")
   parser.add_argument("--antidx", type=int, default=-1, help="Antenna index")
   parser.add_argument("mission", choices=["cosmic2", "spire"], help="Mission name")
   #parser.add_argument("sdate", help="processing date in yyyyddd or yyyymndd format")
   parser.add_argument("tstart", help="leo start time 'yyyymnddThhmmss'")
   parser.add_argument("tend", help="leo end time 'yyyymnddThhmmss'")
   args = parser.parse_args()

   stime = datetime.strptime(args.tstart, "%Y%m%dT%H%M%S")
   etime = datetime.strptime(args.tend, "%Y%m%dT%H%M%S")
   mytime = etime
   
   leo = {
     'mission': args.mission,
     'satidx':  args.satidx , 'antidx': args.antidx,
     'session': '0',
     'tstart': stime,
     'tend': tetime,
   }
   bern = {
     'codmgex': args.codcom,
     'session': args.session,
   }

   ## Date processing
   gnss_prod = 'COD0OPSULT'
   gnss_latency =  args.gnss_latency

   bernese_gnss_inputs(gnss_prod, mytime, data_source='nasa', gnss_latency = gnss_latency )
   bernese_leo_inputs_hourly(leo)
