#! /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 re
from datetime import datetime, timezone

INPUT_FILE = "bin/response-testcases.json"
OUTPUT_FILE = "go/typedef/generated_typedef_test.go"


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
# -----------------------------------------------------------------------------

# Set up logging.

logging.basicConfig(format="%(asctime)s %(message)s", level=logging.INFO)

# Prolog.

horizontal_rule = format("-" * 80)
logging.info("%s", horizontal_rule)
logging.info("--- %s - Begin", format(os.path.basename(__file__)))
logging.info("%s", horizontal_rule)

# Command line options.

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

# Load testcase metadata.

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

# Write testcase file.

with open(OUTPUT_FILE, "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.

logging.info("%s", horizontal_rule)
logging.info("--- %s - End", os.path.basename(__file__))
logging.info("%s", horizontal_rule)
