import inspect
import migrations.versions
import os
import subprocess

from files.__main__ import app

APP_PATH = app.root_path
BASE_PATH = os.path.join(*os.path.split(APP_PATH)[:-1])
VERSIONS_PATH = migrations.versions.__path__._path[0];

def test_migrations_up_to_date():
	def get_versions():
		all_versions = [f.path for f in os.scandir(VERSIONS_PATH)]
		filtered_versions = []
		for entry in all_versions:
			if not os.path.isfile(entry):
				continue
			*dir_parts, filename = os.path.split(entry)
			base, ext = os.path.splitext(filename)
			if ext == '.py':
				filtered_versions.append(entry)
		return filtered_versions

	def get_method_body_lines(method):
		method_lines, _ = inspect.getsourcelines(method)
		return [l.strip() for l in method_lines if not l.strip().startswith('#')][1:]

	versions_before = get_versions()
	result = subprocess.run(
		[
			'python3',
			'-m',
			'flask',
			'db',
			'revision',
			'--autogenerate',
			'--rev-id=ci_verify_empty_revision',
			'--message=should_be_empty',
		],
		cwd=BASE_PATH,
		env={
			**os.environ,
			'FLASK_APP': 'files/cli:app',
		},
		capture_output=True,
		text=True,
		check=True
	)
	versions_after = get_versions()
	new_versions = [v for v in versions_after if v not in versions_before]
	try:
		for version in new_versions:
			filename = os.path.split(version)[-1]
			base, ext = os.path.splitext(filename)
			__import__(f'migrations.versions.{base}')
			migration = getattr(migrations.versions, base)
			upgrade_lines = get_method_body_lines(migration.upgrade)
			assert ["pass"] == upgrade_lines, "\n".join([
				"",
				"Expected upgrade script to be empty (pass) but got",
				*[f"\t>\t{l}" for l in upgrade_lines],
				"To fix this issue, please run",
				"\t$ flask db revision --autogenerate --message='short description of schema changes'",
				"to generate a candidate migration, and make any necessary changes to that candidate migration (e.g. naming foreign key constraints)",
			])
			downgrade_lines = get_method_body_lines(migration.downgrade)
			assert ["pass"] == downgrade_lines, "\n".join([
				"",
				"Expected downgrade script to be empty (pass) but got",
				*[f"\t>{l}" for l in downgrade_lines],
				"To fix this issue, please run",
				"\tflask db revision --autogenerate --message='short description of schema changes'",
				"to generate a candidate migration, and make any necessary changes to that candidate migration (e.g. naming foreign key constraints)",
			])
	finally:
		for version in new_versions:
			os.remove(version)
