import datetime
import os
import re
import uuid

from gavo import api

GBOT_UUID = uuid.UUID('cb155986-96c1-11ef-abc9-3cecefe321f0')


class Core(api.Core):
	inputTableXML = """
		<inputTable id="inFields">
			<inputKey name="File" type="file" required="True"
				tablehead="FITS to upload"
				description="This must be a space-calibrated FITS file with
					at least DATE_OBS (a UTC ISO timestamp) and FILTER keywords."/>
			<inputKey name="nick" type="text"
				multiplicity="single"
				description="Uploader nickname (choose whatever you want; we will
				add it as a header in the uploaded FITS)"/>
		</inputTable>
	"""

	def tryImport(self, conn, destDD, stagingPath):
		# try to ingest but roll back again if it does not work out.
		try:
			res = api.makeData(destDD,
				forceSource=stagingPath,
				connection=conn,
				runCommit=False)
		finally:
			conn.rollback()

	def run(self, service, inputTable, queryMeta):
		uplodedName, srcFile = inputTable.getParam("File")
		nick = re.sub("[^A-Za-z_0-9 ]+", "",
			inputTable.getParam("nick") or "Anonymous")
		imageName = str(uuid.uuid3(GBOT_UUID, nick))+".fits"

		destDD = service.rd.getById("import")
		stagingPath = service.rd.getAbsPath(f"staging/{imageName}")
		with open(stagingPath, "wb") as f:
			f.write(srcFile.read())

		hdus = api.pyfits.open(stagingPath, mode="update")
		if not hdus:
			raise api.ValidationError(
				"Sorry, your uploaded file seems to be empty",
				colName="File")
		try:
			hdus[0].header["GAVO-UPLOADED"] = datetime.datetime.utcnow().isoformat()
			hdus[0].header["GAVO-NICK"] = nick
			hdus.flush()
		finally:
			hdus.close()

		with api.getWritableAdminConn() as conn:
			try:
				self.tryImport(conn, destDD, stagingPath)
			except Exception as ex:
#				os.unlink(stagingPath)
				raise api.ValidationError(f"Cannot ingest your FITS file ({ex})."
					"  In all likelihood, this is because mandatory FITS header"
					" values are missing.  See the description above.  If you"
					" think these fields are present, please contact the operators.",
					colName="File")

			finalPath = service.rd.getAbsPath(f"data/{imageName}")
			os.rename(stagingPath, finalPath)
			res = api.makeData(destDD,
				forceSource=finalPath,
				connection=conn)

		return ("text/plain", b"Thank you!")
