using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using NLog;
using System.Data.SqlClient;    // SqlCommand

namespace ProcessDatabase
{
    public class ProcessDB
    {
        static Logger log = LogManager.GetLogger("target_logger");
        public Struct.CmdStruct CreateQuery(List<Struct.DataStruct> data_list)
        {
            Console.WriteLine("create query start");
            log.Debug("create query start");
            Struct.CmdStruct cmd_struct = new Struct.CmdStruct();

            for (int i = 0; i < data_list.Count; i++)
            {
                Struct.DataStruct datastc = new Struct.DataStruct();
                string query = "";
                string schema = data_list[i].schema;
                string table = data_list[i].table;
                string type = data_list[i].type;

                int process_length = data_list[i].process_column_list.Count;
                int condition_length = data_list[i].condition_list.Count;

                string condition_list = "";
                log.Debug(type + " query create");

                if (type == "insert")
                {
                    if (process_length != 0)
                    {
                        string column_list = data_list[i].process_column_list[0].column_name;
                        string value_list = "\'" + data_list[i].process_column_list[0].column_value.Trim() + "\'";

                        for (int j = 1; j < process_length; j++)
                        {
                            column_list = column_list + ", " + data_list[i].process_column_list[j].column_name;
                            value_list = value_list + ", \'" + data_list[i].process_column_list[j].column_value.Trim() + "\'";
                        }

                        query = string.Format("insert into {0}.{1} ({2}) values({3})", schema, table, column_list, value_list);
                    }
                    else
                    {
                        Console.WriteLine("[INSERT] process_column_list missing");
                        log.Error("[INSERT] process_column_list missing");
                    }
                }
                else if (type == "update")
                {
                    if (process_length != 0)
                    {
                        string process_list = data_list[i].process_column_list[0].column_name + " = \'" + data_list[i].process_column_list[0].column_value.Trim() + "\'";
                        for (int j = 1; j < process_length; j++)
                        {
                            process_list = process_list + ", " + data_list[i].process_column_list[j].column_name + " = \'" + data_list[i].process_column_list[j].column_value.Trim() + "\'";
                        }

                        if (condition_length != 0)
                        {
                            condition_list = "where " + data_list[i].condition_list[0].column_name + " = \'" + data_list[i].condition_list[0].column_value.Trim() + "\'";
                            for (int j = 1; j < condition_length; j++)
                            {
                                condition_list = condition_list + " and " + data_list[i].condition_list[0].column_name + " = \'" + data_list[i].condition_list[0].column_value.Trim() + "\'";
                            }
                        }

                        query = string.Format("update {0}.{1} set {2} {3}", schema, table, process_list, condition_list);
                    }
                    else
                    {
                        Console.WriteLine("[UPDATE] process_column_list missing");
                        log.Error("[UPDATE] process_column_list missing");
                    }
                }
                else if (type == "delete")
                {
                    if (condition_length != 0)
                    {
                        condition_list = "where " + data_list[i].condition_list[0].column_name + " = \'" + data_list[i].condition_list[0].column_value.Trim() + "\'";
                        for (int j = 1; j < condition_length; j++)
                        {
                            condition_list = condition_list + " and " + data_list[i].condition_list[0].column_name + " = \'" + data_list[i].condition_list[0].column_value.Trim() + "\'";
                        }

                        query = string.Format("delete from {0}.{1} {2}", schema, table, condition_list);
                    }
                    else
                    {
                        Console.WriteLine("[DELETE] condition_list missing");
                        log.Error("[DELETE] condition_list missing");
                    }
                }
                else
                {
                    Console.WriteLine("incorrect dml type");
                    log.Error("incorrect dml type");
                }
                
                cmd_struct.type_list.Add(type);
                cmd_struct.cmd_list.Add(query);
            }

            Console.WriteLine("create query end");
            log.Debug("create query end");
            return cmd_struct;
        }

        public Struct.ExecuteResultStruct ExcuteQuery(Struct.CmdStruct cmd_struct, SqlConnection connection)
        {
            log.Debug("excute query start");
            Struct.ExecuteResultStruct execute_result_struct = new Struct.ExecuteResultStruct();

            using (SqlCommand cmd = connection.CreateCommand())
            {
                int total_count = cmd_struct.cmd_list.Count;
                execute_result_struct.total_count = total_count;

                for (int i = 0; i < total_count; i++)
                {
                    cmd.CommandText = cmd_struct.cmd_list[i];
                    log.Debug(String.Format("[ {0} ] {1}", cmd_struct.type_list[i], cmd.CommandText));
                    Console.WriteLine("cmd :: " + cmd.CommandText);
                    Console.WriteLine("type :: " + cmd_struct.type_list[i]);

                    try
                    {
                        if (cmd_struct.type_list[i] == "insert")
                        {
                            execute_result_struct.insert_count++;
                            execute_result_struct.insert_success += cmd.ExecuteNonQuery();
                        }
                        else if (cmd_struct.type_list[i] == "update")
                        {
                            execute_result_struct.update_count++;
                            execute_result_struct.update_success += cmd.ExecuteNonQuery();
                        }
                        else if (cmd_struct.type_list[i] == "delete")
                        {
                            execute_result_struct.delete_count++;
                            execute_result_struct.delete_success += cmd.ExecuteNonQuery();
                        }
                    }
                    catch (Exception e)
                    {
                        log.Error(e.ToString());
                    }
                }

            }

            log.Debug("excute query end");
            return execute_result_struct;
        }
    }
}
