#!python

"""
Update surveyops/ops/tile-specstatus.ecsv with spectro pipeline tiles.csv
"""

import os
import sys
import argparse
import numpy as np
from astropy.table import Table

from desiutil.log import get_logger

from desispec.io.meta import specprod_root
from desispec.io.util import get_tempfilename, is_svn_current
from desispec.specstatus import update_specstatus

#-------------------------------------------------------------------------

p = argparse.ArgumentParser()
p.add_argument('-s', '--specstatus', type=str, required=False,
        help='Input tiles-specstatus.ecsv file')
p.add_argument('-t', '--tilesfile', type=str, required=False,
        help='Input tiles.csv, default from $DESI_SPECTRO_REDUX/$SPECPROD/tiles.csv')
p.add_argument('--tileids', type=str, required=False,
        help='Comma separated list of TILEIDs to update; ignore others')
p.add_argument('-o', '--outfile', type=str, required=False,
        help='output file; default overrides --specstatus in-place')
p.add_argument('-n', '--lastnight', type=int, required=False,
        help='Only update tiles from this LASTNIGHT')
p.add_argument('--dry-run', action='store_true',
        help="Determine updates but don't write any files")
p.add_argument('--force', action='store_true',
        help="run even if input specstatus is svn out-of-date")
p.add_argument('--only', action='store_true',
        help="update tiles only if LASTNIGHT is updated")
p.add_argument('--clear-qa', action='store_true',
        help='Clear QA status.')

args = p.parse_args()
log = get_logger()

if args.specstatus is None:
    args.specstatus = 'tiles-specstatus.ecsv'

if args.tilesfile is None:
    args.tilesfile = os.path.join(specprod_root(), 'tiles.csv')

if args.outfile is None:
    args.outfile = args.specstatus

if not os.path.exists(args.specstatus):
    log.critical(f'Missing {args.specstatus}')
    sys.exit(1)

if not os.path.exists(args.tilesfile):
    log.critical(f'Missing {args.tilesfile}')
    sys.exit(1)

log.info(f'Input specstatus {args.specstatus}')
log.info(f'Updating with tiles from {args.tilesfile}')

svndir = os.path.dirname(os.path.abspath(args.specstatus))
try:
    if is_svn_current(svndir):
        log.info(f'svn dir {svndir} is up-to-date')
    elif args.force:
        log.warning(f'svn dir {svndir} NOT up-to-date, but --force to proceeding anyway')
    else:
        log.critical(f'svn dir {svndir} NOT up-to-date, svn update first or use --force')
        sys.exit(1)

except ValueError:
    if args.force:
        log.error(f'Unable to determine if {svndir} is up-to-date, but --force so proceeding anyway')
    else:
        log.critical(f'Unable to determine if {svndir} is up-to-date; use --force to proceed anyway')
        sys.exit(1)

tiles = Table.read(args.tilesfile)
specstatus = Table.read(args.specstatus)

if args.lastnight is not None:
    keep = tiles['LASTNIGHT'] == args.lastnight
    if np.sum(keep) > 0:
        tiles = tiles[keep]
    else:
        log.critical(f'No input tiles with LASTNIGHT={args.lastnight}')
        sys.exit(1)

if args.tileids is not None:
    tileids = [int(x) for x in args.tileids.split(',')]
    keep = np.isin(tiles['TILEID'], tileids)
    if np.sum(keep) > 0:
        tiles = tiles[keep]
    else:
        log.critical(f'TILEIDs {tileids} not found in {args.tilesfile}')
        sys.exit(1)

if args.only:
    log.info("Updating only tiles with new LASTNIGHT")

if args.clear_qa and args.tileids is None:
    log.critical('--clear-qa may only be set in conjunction with '
                 'a specific list of tiles.')
    sys.exit(1)

specstatus = update_specstatus(specstatus, tiles, update_only=args.only,
                               clear_qa=args.clear_qa)

if not args.dry_run:
    tmpfile = get_tempfilename(args.outfile)
    specstatus.write(tmpfile, overwrite=True)
    os.rename(tmpfile, args.outfile)
    log.info(f'Wrote {args.outfile}')
else:
    log.info('Dry run; no files were changed')
