using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlClient;
using System.Data;
using AR;

namespace Project
{
    public static class DBHelper
    {
        public static SqlConnection GetConnection()
        {
            var cs = SETTING.Data.WMS_DB_PROD ? Properties.Settings.Default.WMS_PRD : Properties.Settings.Default.WMS_DEV;
            return new SqlConnection(cs);
        }

        public static object ExecuteScalar(string sql, params SqlParameter[] p)
        {
            var cn = GetConnection();
            try
            {
                var cmd = new SqlCommand(sql, cn);
                if (p != null) cmd.Parameters.AddRange(p);
                cn.Open();
                return cmd.ExecuteScalar();
            }
            catch (Exception ex)
            {
                // 예외 처리 (필요에 따라 로깅 추가)
                return null;
            }
            finally
            {
                if (cn != null && cn.State != ConnectionState.Closed)
                    cn.Close();
            }
        }


        public static int ExecuteNonQuery(string sql, params SqlParameter[] p)
        {
            var cn = GetConnection();
            try
            {
                var cmd = new SqlCommand(sql, cn);
                if (p != null) cmd.Parameters.AddRange(p);
                cn.Open();
                return cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                // 예외 처리 (필요에 따라 로깅 추가)
                return -1;
            }
            finally
            {
                if (cn != null && cn.State != ConnectionState.Closed)
                    cn.Close();
            }
        }

        // CodeIgniter 스타일의 UPDATE 헬퍼 (Dictionary 방식)
        public static int Update(string tableName, Dictionary<string, object> data, string whereClause = "", params SqlParameter[] whereParams)
        {
            if (data == null || data.Count == 0)
                return 0;

            var setClause = new List<string>();
            var parameters = new List<SqlParameter>();
            int paramIndex = 0;

            // SET 절 생성
            foreach (var item in data)
            {
                string paramName = $"@set{paramIndex}";
                setClause.Add($"{item.Key} = {paramName}");
                parameters.Add(new SqlParameter(paramName, item.Value ?? DBNull.Value));
                paramIndex++;
            }

            // WHERE 절 파라미터 추가
            if (whereParams != null)
            {
                parameters.AddRange(whereParams);
            }

            string sql = $"UPDATE {tableName} SET {string.Join(", ", setClause)}";
            if (!string.IsNullOrEmpty(whereClause))
            {
                sql += $" WHERE {whereClause}";
            }

            return ExecuteNonQuery(sql, parameters.ToArray());
        }

        // SqlParameter 배열 방식의 UPDATE 헬퍼
        public static int Update(string tableName, string setClause, string whereClause = "", params SqlParameter[] parameters)
        {
            string sql = $"UPDATE {tableName} SET {setClause}";
            if (!string.IsNullOrEmpty(whereClause))
            {
                sql += $" WHERE {whereClause}";
            }

            return ExecuteNonQuery(sql, parameters);
        }


        // 여러 조건을 위한 헬퍼 (Dictionary 방식)
        public static int UpdateWhere(string tableName, Dictionary<string, object> data, Dictionary<string, object> whereConditions)
        {
            if (whereConditions == null || whereConditions.Count == 0)
                return Update(tableName, data);

            var whereClause = new List<string>();
            var whereParams = new List<SqlParameter>();
            int paramIndex = 0;

            foreach (var condition in whereConditions)
            {
                string paramName = $"@where{paramIndex}";
                whereClause.Add($"{condition.Key} = {paramName}");
                whereParams.Add(new SqlParameter(paramName, condition.Value ?? DBNull.Value));
                paramIndex++;
            }

            return Update(tableName, data, string.Join(" AND ", whereClause), whereParams.ToArray());
        }

        public static int UpdateWhere(string tableName, string setClause, string whereColumn, object whereValue)
        {
            return Update(tableName, setClause, $"{whereColumn} = @whereValue", new SqlParameter("@whereValue", whereValue));
        }

        // CodeIgniter 스타일의 DELETE 헬퍼
        public static int Delete(string tableName, string whereClause = "", params SqlParameter[] whereParams)
        {
            string sql = $"DELETE FROM {tableName}";
            if (!string.IsNullOrEmpty(whereClause))
            {
                sql += $" WHERE {whereClause}";
            }

            return ExecuteNonQuery(sql, whereParams);
        }

        // 간단한 WHERE 조건을 위한 DELETE 헬퍼
        public static int DeleteWhere(string tableName, string whereColumn, object whereValue)
        {
            return Delete(tableName, $"{whereColumn} = @whereValue", new SqlParameter("@whereValue", whereValue));
        }

        // 여러 조건을 위한 DELETE 헬퍼 (Dictionary 방식)
        public static int DeleteWhere(string tableName, Dictionary<string, object> whereConditions)
        {
            if (whereConditions == null || whereConditions.Count == 0)
                return Delete(tableName); // WHERE 절 없이 전체 삭제

            var whereClause = new List<string>();
            var whereParams = new List<SqlParameter>();
            int paramIndex = 0;

            foreach (var condition in whereConditions)
            {
                string paramName = $"@where{paramIndex}";
                whereClause.Add($"{condition.Key} = {paramName}");
                whereParams.Add(new SqlParameter(paramName, condition.Value ?? DBNull.Value));
                paramIndex++;
            }

            return Delete(tableName, string.Join(" AND ", whereClause), whereParams.ToArray());
        }

        // SqlParameter 배열을 받는 DELETE 헬퍼 오버로드
        public static int DeleteWhere(string tableName, string whereClause, params SqlParameter[] whereParams)
        {
            return Delete(tableName, whereClause, whereParams);
        }

        // 테이블 전체 삭제 (TRUNCATE 대신 DELETE 사용)
        public static int DeleteAll(string tableName)
        {
            return Delete(tableName);
        }

        // CodeIgniter 스타일의 SELECT 헬퍼
        public static DataTable Select(string tableName, string columns = "*", string whereClause = "", params SqlParameter[] whereParams)
        {
            string sql = $"SELECT {columns} FROM {tableName}";
            if (!string.IsNullOrEmpty(whereClause))
            {
                sql += $" WHERE {whereClause}";
            }

            return Get(sql, whereParams);
        }

        // 간단한 WHERE 조건을 위한 SELECT 헬퍼
        public static DataTable SelectWhere(string tableName, string columns = "*", string whereColumn = "", object whereValue = null)
        {
            if (string.IsNullOrEmpty(whereColumn) || whereValue == null)
                return Select(tableName, columns);

            return Select(tableName, columns, $"{whereColumn} = @whereValue", new SqlParameter("@whereValue", whereValue));
        }

        // SqlParameter 배열을 받는 SELECT 헬퍼 오버로드
        public static DataTable SelectWhere(string tableName, string columns, string whereClause, params SqlParameter[] whereParams)
        {
            return Select(tableName, columns, whereClause, whereParams);
        }

        // Dictionary로 WHERE 조건을 받는 SELECT 헬퍼 오버로드
        public static DataTable SelectWhere(string tableName, string columns, Dictionary<string, object> whereConditions)
        {
            if (whereConditions == null || whereConditions.Count == 0)
                return Select(tableName, columns);

            var whereClause = new List<string>();
            var whereParams = new List<SqlParameter>();
            int paramIndex = 0;

            foreach (var condition in whereConditions)
            {
                string paramName = $"@where{paramIndex}";
                whereClause.Add($"{condition.Key} = {paramName}");
                whereParams.Add(new SqlParameter(paramName, condition.Value ?? DBNull.Value));
                paramIndex++;
            }

            return Select(tableName, columns, string.Join(" AND ", whereClause), whereParams.ToArray());
        }

        // Dictionary로 WHERE 조건을 받는 SELECT 헬퍼 (기본 컬럼 *)
        public static DataTable SelectWhere(string tableName, Dictionary<string, object> whereConditions)
        {
            return SelectWhere(tableName, "*", whereConditions);
        }

        // ORDER BY가 포함된 SELECT 헬퍼
        public static DataTable SelectOrderBy(string tableName, string columns = "*", string whereClause = "", string orderBy = "", params SqlParameter[] whereParams)
        {
            string sql = $"SELECT {columns} FROM {tableName}";
            if (!string.IsNullOrEmpty(whereClause))
            {
                sql += $" WHERE {whereClause}";
            }
            if (!string.IsNullOrEmpty(orderBy))
            {
                sql += $" ORDER BY {orderBy}";
            }

            return Get(sql, whereParams);
        }

        // LIMIT이 포함된 SELECT 헬퍼 (TOP 사용)
        public static DataTable SelectLimit(string tableName, int limit, string columns = "*", string whereClause = "", string orderBy = "", params SqlParameter[] whereParams)
        {
            string sql = $"SELECT TOP {limit} {columns} FROM {tableName}";
            if (!string.IsNullOrEmpty(whereClause))
            {
                sql += $" WHERE {whereClause}";
            }
            if (!string.IsNullOrEmpty(orderBy))
            {
                sql += $" ORDER BY {orderBy}";
            }

            return Get(sql, whereParams);
        }

        public static DataRow SelectFirst(string tableName, string columns = "*", Dictionary<string, object> whereParams = null)
        {
            if (whereParams == null || whereParams.Count == 0)
                return SelectFirst(tableName, columns);

            var whereClause = new List<string>();
            var sqlParams = new List<SqlParameter>();
            int paramIndex = 0;

            foreach (var condition in whereParams)
            {
                string paramName = $"@where{paramIndex}";
                whereClause.Add($"{condition.Key} = {paramName}");
                sqlParams.Add(new SqlParameter(paramName, condition.Value ?? DBNull.Value));
                paramIndex++;
            }

            var dt = SelectLimit(tableName, 1, columns, string.Join(" AND ", whereClause), "", sqlParams.ToArray());
            return dt.Rows.Count > 0 ? dt.Rows[0] : null;
        }
        // 단일 행 조회 (첫 번째 행만)
        public static DataRow SelectFirst(string tableName, string columns = "*", string whereClause = "", params SqlParameter[] whereParams)
        {
            var dt = SelectLimit(tableName, 1, columns, whereClause, "", whereParams);
            return dt.Rows.Count > 0 ? dt.Rows[0] : null;
        }

        // 단일 값 조회 (첫 번째 행의 첫 번째 컬럼)
        public static object SelectValue(string tableName, string column, string whereClause = "", params SqlParameter[] whereParams)
        {
            var row = SelectFirst(tableName, column, whereClause, whereParams);
            return row != null ? row[0] : null;
        }

        public static T Get<T>(string sql, params SqlParameter[] p) where T : DataTable
        {
            var dt = (T)Activator.CreateInstance(typeof(T));
            var cn = GetConnection();
            try
            {
                var cmd = new SqlCommand(sql, cn);
                if (p != null) cmd.Parameters.AddRange(p);
                var da = new SqlDataAdapter(cmd);
                da.Fill(dt);
            }
            catch (Exception ex)
            {

            }
            finally
            {
                if (cn != null && cn.State != ConnectionState.Closed)
                    cn.Close();
            }
            return dt;
        }
        public static DataTable Get(string sql, params SqlParameter[] p)
        {
            var dt = new DataTable();
            var cn = GetConnection();
            try
            {
                var cmd = new SqlCommand(sql, cn);
                if (p != null) cmd.Parameters.AddRange(p);
                var da = new SqlDataAdapter(cmd);
                da.Fill(dt);
            }
            catch (Exception ex)
            {

            }
            finally
            {
                if (cn != null && cn.State != ConnectionState.Closed)
                    cn.Close();
            }

            return dt;
        }
        public static void Fill(string sql, DataTable dt, params SqlParameter[] p)
        {
            var cn = GetConnection();
            try
            {
                var cmd = new SqlCommand(sql, cn);
                if (p != null) cmd.Parameters.Add(p);
                var da = new SqlDataAdapter(cmd);
                dt = new DataTable();
                da.Fill(dt);
            }
            catch (Exception ex)
            {

            }
            finally
            {
                if (cn != null && cn.State != ConnectionState.Closed)
                    cn.Close();
            }
        }
    }
}
