using System.Windows.Forms;

namespace AutorentWinForms;

internal static class Program
{
    [STAThread]
    private static void Main(string[] args)
    {
        ApplicationConfiguration.Initialize();

        var connectionString = AppSettings.LoadConnectionString();
        using var db = new Database(connectionString);

        if (args.Contains("--probe"))
        {
            var perms = db.Query("""
                SELECT current_database() AS db,
                       has_database_privilege(current_user, current_database(), 'CREATE') AS can_create_db,
                       has_schema_privilege(current_user, 'public', 'CREATE') AS can_create_public
                """);
            Console.WriteLine($"CURRENT {perms.Rows[0]["db"]} CREATE_DB={perms.Rows[0]["can_create_db"]} CREATE_PUBLIC={perms.Rows[0]["can_create_public"]}");
            var databases = db.Query("SELECT datname FROM pg_database WHERE datallowconn ORDER BY datname");
            Console.WriteLine("DATABASES");
            foreach (System.Data.DataRow row in databases.Rows)
                Console.WriteLine(row["datname"]);
            Console.WriteLine("SCHEMAS");
            var schemas = db.Query("SELECT schema_name FROM information_schema.schemata ORDER BY schema_name");
            foreach (System.Data.DataRow row in schemas.Rows)
                Console.WriteLine(row["schema_name"]);
            Console.WriteLine("TABLES");
            var tables = db.Query("""
                SELECT table_schema, table_name
                FROM information_schema.tables
                WHERE table_schema NOT IN ('pg_catalog', 'information_schema')
                ORDER BY table_schema, table_name
                LIMIT 80
                """);
            foreach (System.Data.DataRow row in tables.Rows)
                Console.WriteLine($"{row["table_schema"]}.{row["table_name"]}");
            Console.WriteLine("COLUMNS");
            var columns = db.Query("""
                SELECT table_name, column_name, data_type
                FROM information_schema.columns
                WHERE table_schema = current_schema()
                  AND table_name IN ('brand','car','client','rental','app_user','audit_log')
                ORDER BY table_name, ordinal_position
                """);
            foreach (System.Data.DataRow row in columns.Rows)
                Console.WriteLine($"{row["table_name"]}.{row["column_name"]}:{row["data_type"]}");
            return;
        }

        db.Initialize();

        if (args.Contains("--smoke-test"))
        {
            var clients = db.ExecuteScalarInt("SELECT COUNT(*) FROM client");
            var audit = db.ExecuteScalarInt("SELECT COUNT(*) FROM audit_log");
            var adminAuth = db.Authenticate("garanin_gi", "6qw#6xUyG%#")?.Role == "admin";
            var managerAuth = db.Authenticate("manager", "Manager123!")?.Role == "manager";
            var viewerAuth = db.Authenticate("shagavaliev_iv", "75&n057$380")?.Role == "viewer";
            Console.WriteLine($"OK: clients={clients}, audit={audit}, adminAuth={adminAuth}, managerAuth={managerAuth}, viewerAuth={viewerAuth}");
            return;
        }

        if (args.Contains("--insert-test"))
        {
            var stamp = DateTime.Now.ToString("yyyyMMddHHmmss");
            db.ExecuteNonQuery("BEGIN");
            try
            {
                db.ExecuteNonQuery(
                    """
                    INSERT INTO client(full_name, phone, address, license_no)
                    VALUES(@name, @phone, @address, @license)
                    """,
                    new()
                    {
                        ["@name"] = "Проверка sequence",
                        ["@phone"] = "+7999" + stamp,
                        ["@address"] = "Тест",
                        ["@license"] = "TEST" + stamp
                    });
                var id = db.ExecuteScalarInt("SELECT MAX(client_id) FROM client");
                Console.WriteLine($"OK: inserted client_id={id}");
            }
            finally
            {
                db.ExecuteNonQuery("ROLLBACK");
            }
            return;
        }

        using var login = new LoginForm(db);
        if (login.ShowDialog() != DialogResult.OK || login.Session is null)
            return;

        Application.Run(new MainForm(db, login.Session));
    }
}
