using Dapper;
using SolarPower.Helper;
using SolarPower.Models;
using SolarPower.Repository.Interface;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;

namespace SolarPower.Repository.Implement
{
    public class OperationRepository : RepositoryBase<Operation>, IOperationRepository
    {
        public OperationRepository(IDatabaseHelper databaseHelper) : base(databaseHelper)
        {
            tableName = "operation_plan_create";
        }
        public async Task<List<PowerStationIdList>> GetPowerStationIdList(int UserId)
        {
            List<PowerStationIdList> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = @$"SELECT tn.Id AS Value, tn.Name AS Text FROM power_station tn LEFT JOIN power_station_operation_personnel pp 
                                ON tn.Id=pp.PowerStationId
                                WHERE pp.UserId = @userid";
                    result = (await conn.QueryAsync<PowerStationIdList>(sql, new { userid = UserId })).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        public async Task AddOperationPlan(OperationCreatePlan OperationPlan, List<string> properties)
        {
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                try
                {
                    string sql = GenerateInsertQuery(properties);

                    await conn.ExecuteAsync(sql, OperationPlan);
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }

            }
        }
        public async Task<List<OperationPlanTable>> OperationPlanTable(List<int> id, int Type)
        {
            List<OperationPlanTable> result;
            var count = 0;
            string Wheresql = "oc.PowerStationId = ";
            if (id.Count > 0)
            {
                foreach (int too in id)
                {

                    if (count == id.Count - 1)
                    {
                        Wheresql += too.ToString();
                    }
                    else
                    {
                        Wheresql += too.ToString() + " OR oc.PowerStationId = ";
                    }
                    count++;
                }

            }
            else
            {
                Wheresql += "0";
            }

            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = "";
                    if (Type != 9)
                    {
                        sql = @$"SELECT oc.Id,oc.PlanId,oc.PowerStationId,oc.Type,
                                    oc.ScheduleNum,oc.ScheduleType,oc.WorkDay,oc.StartTime,
                                    oc.EmailType,oc.Description,oc.CreatedAt,ps.Name AS PowerStationName ,us.Name AS CreatedPerson FROM operation_plan_create oc LEFT JOIN power_station ps 
                                    ON oc.PowerStationId = ps.Id LEFT JOIN user us 
                                    ON us.Id = oc.CreatedBy WHERE ({Wheresql}) AND oc.Deleted = 0 AND oc.Type = {Type}";
                    }
                    else
                    {
                        sql = @$"SELECT oc.Id,oc.PlanId,oc.PowerStationId,oc.Type,
                                    oc.ScheduleNum,oc.ScheduleType,oc.WorkDay,oc.StartTime,
                                    oc.EmailType,oc.Description,oc.CreatedAt,ps.Name AS PowerStationName ,us.Name AS CreatedPerson FROM operation_plan_create oc LEFT JOIN power_station ps 
                                    ON oc.PowerStationId = ps.Id LEFT JOIN user us 
                                    ON us.Id = oc.CreatedBy WHERE ({Wheresql}) AND oc.Deleted = 0";
                    }


                    result = (await conn.QueryAsync<OperationPlanTable>(sql)).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }
        public async Task<OperationCreatePlan> GetOneOperation(int id)
        {
            OperationCreatePlan result;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                try
                {
                    var sql = @"SELECT * FROM operation_plan_create WHERE Deleted =0 AND Id = @Id";

                    result = await conn.QueryFirstOrDefaultAsync<OperationCreatePlan>(sql, new { Id = id });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }

                return result;
            }
        }

        public async Task UpdateOperationPlan(OperationCreatePlan OperationPlan, List<string> properties)
        {
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                var trans = conn.BeginTransaction();
                try
                {
                    var sql = GenerateUpdateQuery(properties);
                    await conn.ExecuteAsync(sql, OperationPlan, trans);

                    trans.Commit();
                }
                catch (Exception exception)
                {
                    trans.Rollback();
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }

            }
        }

        public async Task AddToRecord(PlanToRecord record, List<string> properties2)
        {
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                var trans = conn.BeginTransaction();
                try
                {
                    string sql = GenerateInsertQueryWithCustomTable(properties2, "operation_record");
                    await conn.ExecuteAsync(sql, record);
                    trans.Commit();
                }
                catch (Exception exception)
                {
                    trans.Rollback();
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }

            }
        }

        /// <summary>
        /// 透過搜尋條件，查詢過濾後的運維作業記錄
        /// </summary>
        /// <param name="filter"></param>
        /// <returns></returns>
        public async Task<List<OperationRecodeDataTable>> GetAllRecodeByFilterAsync(PostOperationRecodeFilter filter)
        {
            List<OperationRecodeDataTable> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = @$"SELECT
                                opr.*,
                                ps.Name AS PowerStationName,
                                u.Name AS WorkPersonName
                                FROM operation_record opr
                                LEFT JOIN power_station ps ON opr.PowerStationId = ps.Id
                                LEFT JOIN user u ON opr.WorkPersonId = u.ID
                                WHERE opr.Deleted = 0
                                AND ps.Id IN @PowerStationIds";

                    if (!string.IsNullOrEmpty(filter.Range))
                    {
                        filter.StartTime = filter.Range.Split('-')[0];
                        filter.EndTime = filter.Range.Split('-')[1];

                        sql += " AND opr.StartTime <= @EndDate";
                        sql += " AND opr.EndTime >= @StartDate";
                    }

                    if (filter.WorkType > 0)
                    {
                        filter.WorkType -= 1;
                        sql += @" AND opr.WorkType = @WorkType ORDER BY CreatedAt DESC";
                    }
                    else
                    {
                        sql += @" AND opr.WorkType IN (0, 1)";
                        sql += @" UNION";
                        sql += @" SELECT
                                opr.*,
                                ps.Name AS PowerStationName,
                                u.Name AS WorkPersonName
                                FROM operation_record opr
                                LEFT JOIN power_station ps ON opr.PowerStationId = ps.Id
                                LEFT JOIN user u ON opr.WorkPersonId = u.ID
                                WHERE opr.Deleted = 0
                                AND ps.Id IN @PowerStationIds
                                AND opr.WorkType = 2";
                        if (!string.IsNullOrEmpty(filter.Range))
                        {
                            filter.StartTime = filter.Range.Split('-')[0];
                            filter.EndTime = filter.Range.Split('-')[1];

                            sql += " AND opr.StartTime <= @EndDate";
                            sql += " AND opr.EndTime >= @StartDate";
                        }
                        else
                        {
                            var today = DateTime.Now.ToString("yyyy-MM-dd");
                            var dateLimit = DateTime.Now.AddDays(-30).ToString("yyyy-MM-dd");

                            sql += $" AND opr.CreatedAt BETWEEN '{dateLimit} 00:00:00' AND '{today} 23:59:59'";

                            //sql += $" AND opr.StartTime <= {today}";
                            //sql += $" AND opr.EndTime >= {dateLimit}";
                        }
                    }

                    result = (await conn.QueryAsync<OperationRecodeDataTable>(sql,
                            new { 
                                PowerStationIds = filter.PowerStationIds,
                                WorkType = filter.WorkType,
                                StartDate = filter.StartTime,
                                EndDate = filter.EndTime
                            })).ToList();

                    var sql_file = "SELECT * FROM operation_record_file WHERE Deleted = 0 AND RecordId = @RecordId";
                    foreach (var x in result)
                    {
                        x.RecodeFiles = (await conn.QueryAsync<OperationRecodeFile>(sql_file, new { RecordId = x.Id })).ToList();
                    }
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }

        /// <summary>
        /// 透過Id，取得單一筆運維作業記錄
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<OperationRecode> GetOneOperationRecodeAsync(int id)
        {
            OperationRecode result;

            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                conn.Open();
                try
                {
                    var sql = @$"SELECT opr.*, ps.Name AS PowerStationName
                                FROM operation_record opr 
                                LEFT JOIN power_station ps ON opr.PowerStationId = ps.Id
                                WHERE opr.Deleted = 0 AND opr.Id = @Id";

                    result = await conn.QueryFirstOrDefaultAsync<OperationRecode>(sql, new { Id = id });

                    if (result != null)
                    {
                        //取得圖片 or 檔案
                        var sql_file = @"SELECT * FROM operation_record_file WHERE Deleted = 0 AND RecordId = @RecordId";

                        result.RecodeFiles = (await conn.QueryAsync<OperationRecodeFile>(sql_file, new { RecordId = result.Id })).ToList();
                    }
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }
                return result;
            }
        }

        /// <summary>
        /// 新增一筆運維作業記錄
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="properties"></param>
        /// <returns></returns>
        public async Task<int> AddOneOperationRecodeAsync(OperationRecode entity, List<string> properties)
        {
            var id = 0;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        string sql = GenerateInsertQueryWithCustomTable(properties, "operation_record");

                        sql += "SELECT LAST_INSERT_ID();";

                        id = (await conn.QueryAsync<int>(sql, entity, trans)).Single();

                        trans.Commit();
                    }
                    catch (Exception exception)
                    {
                        trans.Rollback();
                        throw exception;
                    }
                    finally
                    {
                        conn.Close();
                    }
                }

                return id;
            }
        }

        /// <summary>
        /// 修改運維作業記錄
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="properties"></param>
        /// <param name="db_name"></param>
        /// <returns></returns>
        public async Task UpdateOperationRecodeAsync(UpdateOperationRecode entity, List<string> properties)
        {
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        var sql = GenerateUpdateQueryWithCustomTable(properties, "operation_record");
                        await conn.ExecuteAsync(sql, entity, trans);

                        trans.Commit();
                    }
                    catch (Exception exception)
                    {
                        trans.Rollback();
                        throw exception;
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
            }
        }

        public async Task DeleteOneOperationRecodeAsync(int id)
        {
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        var sql = $"UPDATE operation_record SET deleted = 1 WHERE Id = @Id";

                        await conn.ExecuteAsync(sql, new { Id = id }, trans);

                        trans.Commit();
                    }
                    catch (Exception exception)
                    {
                        trans.Rollback();
                        throw exception;
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
            }
        }

        /// <summary>
        /// 新增運維作業記錄的檔案
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="properties"></param>
        /// <returns></returns>
        public async Task<int> AddOperationRecodeFilesAsync(List<OperationRecodeFile> entity, List<string> properties)
        {
            int count;
            using (IDbConnection conn = _databaseHelper.GetConnection())
            {
                conn.Open();
                try
                {
                    string sql = GenerateInsertQueryWithCustomTable(properties, "operation_record_file");

                    count = await conn.ExecuteAsync(sql, entity);
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }

                return count;
            }
        }

        /// <summary>
        /// 透過Id，取得單一運維作業記錄檔案
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<OperationRecodeFile> GetOneOperationRecodeFileAsync(int id)
        {
            OperationRecodeFile result;

            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                conn.Open();
                try
                {
                    var sql = @$"SELECT *
                                FROM operation_record_file
                                WHERE Deleted = 0 AND Id = @Id";

                    result = await conn.QueryFirstOrDefaultAsync<OperationRecodeFile>(sql, new { Id = id });
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                finally
                {
                    conn.Close();
                }
                return result;
            }
        }

        /// <summary>
        /// 透過Id，軟刪除運維作業記錄檔案
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task DeleteOneOperationRecodeFile(int id)
        {
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                conn.Open();
                using (var trans = conn.BeginTransaction())
                {
                    try
                    {
                        var sql = $"UPDATE operation_record_file SET deleted = 1 WHERE id = @Id";

                        await conn.ExecuteAsync(sql, new { Id = id }, trans);

                        trans.Commit();
                    }
                    catch (Exception exception)
                    {
                        trans.Rollback();
                        throw exception;
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
            }
        }

        public async Task<List<OperationCreatePlan>> GetOperationSchedules()
        {
            List<OperationCreatePlan> result;
            using (IDbConnection conn = this._databaseHelper.GetConnection())
            {
                try
                {
                    var sql = @$"SELECT * FROM operation_plan_create opc 
                                WHERE opc.Deleted = 0";
                    result = (await conn.QueryAsync<OperationCreatePlan>(sql)).ToList();
                }
                catch (Exception exception)
                {
                    throw exception;
                }
                return result;
            }
        }
    }
}
