using System;
using System.IO;
using com.itac.mes.imsapi.client.dotnet;

internal sealed class Probe : IMSApiDotNetBase
{
    public string Get(string key, string fallback = null) => Prop(key, fallback);
    public override int imsapiGetLibraryVersion(ref string libraryVersion)
    {
        libraryVersion = "probe";
        return 0;
    }
}

internal static class Program
{
    private static int Main(string[] args)
    {
        string assemblyLocation = typeof(IMSApiDotNetBase).Assembly.Location;
        string assemblyDirectory = Path.GetDirectoryName(Path.GetFullPath(assemblyLocation));
        if (string.IsNullOrWhiteSpace(assemblyDirectory))
        {
            Console.Error.WriteLine("Unable to resolve IMSApiDotNet.dll directory.");
            return 2;
        }

        string file = Path.Combine(assemblyDirectory, "ihas.properties");
        string oldCwd = Directory.GetCurrentDirectory();
        string wrongDirectory = Path.Combine(Path.GetTempPath(), "IMSApiDotNet-ihas-wrong-" + Guid.NewGuid().ToString("N"));
        Directory.CreateDirectory(wrongDirectory);

        try
        {
            // Correct file: it MUST be located next to the loaded IMSApiDotNet.dll.
            File.WriteAllText(file,
                "# FIX6 DLL-directory property smoke test\r\n" +
                "file.only=from-dll-directory\r\n" +
                "precedence=from-file\r\n" +
                "itac.appid=FromDllProperties\r\n" +
                "itac.artes.clusternodes=https://partner.itacsoftware.com:8181/mes\r\n");

            // Deliberately place conflicting files elsewhere. Neither the current
            // working directory nor itac.propdir may control the physical file
            // lookup anymore.
            File.WriteAllText(Path.Combine(wrongDirectory, "ihas.properties"),
                "file.only=WRONG-DIRECTORY\r\n" +
                "itac.appid=WrongDirectory\r\n");
            Directory.SetCurrentDirectory(wrongDirectory);
            IMSApiDotNet.setProperty("itac.propdir", wrongDirectory);

            // Programmatic values still override the same key from ihas.properties.
            IMSApiDotNet.setProperty("precedence", "from-setProperty");

            var p = new Probe();
            if (p.Get("file.only") != "from-dll-directory") return Fail("file.only", p.Get("file.only"), "from-dll-directory");
            if (p.Get("precedence") != "from-setProperty") return Fail("precedence", p.Get("precedence"), "from-setProperty");
            if (p.Get("missing", "fallback") != "fallback") return Fail("missing", p.Get("missing", "fallback"), "fallback");
            if (p.Get("itac.appid") != "FromDllProperties") return Fail("itac.appid", p.Get("itac.appid"), "FromDllProperties");
            if (p.Get("itac.artes.clusternodes") != "https://partner.itacsoftware.com:8181/mes")
                return Fail("itac.artes.clusternodes", p.Get("itac.artes.clusternodes"), "https://partner.itacsoftware.com:8181/mes");

            // Verify the real public API reports the raw file value. Programmatic
            // setProperty must not replace this diagnostic line.
            IMSApiDotNet.setProperty("itac.artes.clusternodes", "https://override.invalid/mes");
            string libraryVersion = null;
            var api = IMSApiDotNet.loadLibrary();
            int versionRc = api.imsapiGetLibraryVersion(ref libraryVersion);
            if (versionRc != 0) return Fail("imsapiGetLibraryVersion rc", versionRc.ToString(), "0");
            if (libraryVersion == null || libraryVersion.IndexOf("itac.artes.clusternodes=https://partner.itacsoftware.com:8181/mes", StringComparison.Ordinal) < 0)
                return Fail("libraryVersion cluster node", libraryVersion, "raw ihas.properties cluster node");
            if (libraryVersion.IndexOf(file, StringComparison.OrdinalIgnoreCase) < 0)
                return Fail("libraryVersion ihas.properties path", libraryVersion, file);

            Console.WriteLine("PASS dll-directory");
            Console.WriteLine(libraryVersion);
            Console.WriteLine("IMSApiDotNet.dll: " + assemblyLocation);
            Console.WriteLine("ihas.properties: " + file);
            return 0;
        }
        finally
        {
            Directory.SetCurrentDirectory(oldCwd);
            try { if (File.Exists(file)) File.Delete(file); } catch { }
            try { if (Directory.Exists(wrongDirectory)) Directory.Delete(wrongDirectory, true); } catch { }
        }
    }

    private static int Fail(string key, string actual, string expected)
    {
        Console.Error.WriteLine("FAIL " + key + ": actual=<" + actual + "> expected=<" + expected + ">");
        return 1;
    }
}
