#! /usr/bin/env python3

# pylint: disable=duplicate-code

"""
Used to generate go/typedef/generated_typedef_test.go
"""

import argparse
import json
import logging
import os
import pathlib
import re
from datetime import datetime, timezone

# Logging

logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
logger = logging.getLogger(__name__)

# Global variables.

CURRENT_PATH = pathlib.Path(__file__).parent.resolve()
INPUT_FILENAME = os.path.abspath(f"{CURRENT_PATH}/../bin/response-testcases.json")
OUTPUT_FILENAME = os.path.abspath(f"{CURRENT_PATH}/../go/typedef/generated_typedef_test.go")

# -----------------------------------------------------------------------------
# --- Functions
# -----------------------------------------------------------------------------


def spaces_not_tabs():
    """Because tabs are used in OUTPUT_HEADER, linters get confused with spaces vs. tabs.  This solves it."""


# -----------------------------------------------------------------------------
# --- Output templates
# -----------------------------------------------------------------------------

# noqa: E101
OUTPUT_HEADER = """// DO NOT EDIT.  This code is generated.
// Generated by: sz-sdk-json-type-definition/bin/make_go_typedef_generated_typedef_test_go.py
// Generated for: sz-sdk-json-type-definition/go/typedef/generated_typedef_test.go
"""  # noqa: E101,F541,W191


OUTPUT_HEADER += f"// Generated date: {datetime.now(timezone.utc).isoformat()}\n"

OUTPUT_HEADER += """
package typedef_test

import (
	"context"
	"encoding/json"
	"testing"

	"github.com/senzing-garage/sz-sdk-json-type-definition/go/typedef"
	"github.com/stretchr/testify/assert"
)

func testErr(test *testing.T, ctx context.Context, err error) {
	_ = ctx
	if err != nil {
		test.Log("Error:", err.Error())
		assert.FailNow(test, err.Error())
	}
}

// ----------------------------------------------------------------------------
// --- Test cases
// ----------------------------------------------------------------------------

"""  # noqa: E101,F541,W191


TEST_FUNCTION_TEMPLATE = f"""
	ctx := context.TODO()
	jsonString := `{{json}}`
	jsonStruct := typedef.{{struct}}{{parens}}
	err := json.Unmarshal([]byte(jsonString), &jsonStruct)
	testErr(test, ctx, err)
	_, err = json.Marshal(jsonStruct)
	testErr(test, ctx, err)
	// assert.Equal(test, jsonString, string(reconstructedString))
	// assert.JSONEq(test, jsonString, string(reconstructedString))
"""  # noqa: E101,F541,W191


OUTPUT_FOOTER = """
"""


# -----------------------------------------------------------------------------
# --- Helpers
# -----------------------------------------------------------------------------


def canonical_json(json_string):
    """Create compact JSON.  No spaces."""
    # json_object = json.loads(json_string)
    result = json.dumps(json_string, sort_keys=True, separators=(",", ":"))
    return result


def canonical_testcase_name(raw_testcase_name):
    """Normalize the testcase name."""
    return re.sub("[^0-9a-zA-Z]+", "", raw_testcase_name).capitalize()


# -----------------------------------------------------------------------------
# --- Main
# -----------------------------------------------------------------------------

if __name__ == "__main__":

    # Prolog.

    logger.info("Begin %s", os.path.basename(__file__))

    # Command line options.

    parser = argparse.ArgumentParser(prog="generate_go_typef_test.py")
    parser.add_argument(
        "--output",
        help=f"Output file. Default: {OUTPUT_FILENAME}",
        default=OUTPUT_FILENAME,
    )
    args = parser.parse_args()
    OUTPUT_FILENAME = args.output

    # Load testcase metadata.

    with open(INPUT_FILENAME, encoding="utf-8") as input_file:
        response_testcases = json.load(input_file)

    # Write testcase file.

    with open(OUTPUT_FILENAME, "w", encoding="utf-8") as file:
        file.write(OUTPUT_HEADER)
        for senzing_api_class, senzing_api_class_data in response_testcases.items():
            metadata = senzing_api_class_data.get("metadata", {})
            if metadata.get("goSkip", False):
                continue
            tests = senzing_api_class_data.get("tests", {})
            go_api_class = metadata.get("goClass", senzing_api_class)
            for testcase_name, testcase_json in tests.items():
                file.write(f"func Test{go_api_class}{canonical_testcase_name(testcase_name)}(test *testing.T) {{")
                file.write(
                    TEST_FUNCTION_TEMPLATE.format(json=canonical_json(testcase_json), struct=go_api_class, parens="{}")
                )
                file.write("}\n\n")
        file.write(OUTPUT_FOOTER)

    # Epilog.

    logger.info("End   %s", os.path.basename(__file__))
