using FrontendWebApi.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Repository.BackendRepository.Interface;
using Repository.FrontendRepository.Interface;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;

namespace FrontendWebApi.ApiControllers
{
    public class EmergencyDeviceController : MyBaseApiController<EmergencyDeviceController>
    {
        private readonly IBackendRepository backendRepository;
        private readonly IFrontendRepository frontendRepository;

        public EmergencyDeviceController
        (
            IBackendRepository backendRepository,
            IFrontendRepository frontendRepository
        )
        {
            this.backendRepository = backendRepository;
            this.frontendRepository = frontendRepository;
        }

        [HttpPost]
        [Route("api/DisasterList")]
        public async Task<ActionResult<ApiResult<List<KeyValue>>>> DisasterList()
        {
            ApiResult<List<KeyValue>> apiResult = new ApiResult<List<KeyValue>>();
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            List<KeyValue> Variable = new List<KeyValue>();

            try
            {
                var sqlString = @$"select system_value as Value, system_key as Name from variable a where a.system_type = 'disaster' and a.deleted = 0";
                Variable = await backendRepository.GetAllAsync<KeyValue>(sqlString);

                apiResult.Code = "0000";
                apiResult.Data = Variable;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return Ok(apiResult);
        }

        [HttpPost]
        [Route("api/BuildInfoList")]
        public async Task<ActionResult<ApiResult<List<BuildingToF>>>> BuildInfoList()
        {
            ApiResult<List<BuildingToF>> apiResult = new ApiResult<List<BuildingToF>>();
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            List<building_floor> Building_floor = new List<building_floor>();
            List<BuildingToF> buildingToF = new List<BuildingToF>();
            try
            {
                var sqlString = @$"select f.floor_guid ,f.full_name floorname,b.building_guid,b.full_name buildingname from floor f left join building b on b.building_guid = f.building_guid order by f.building_guid , f.priority";
                Building_floor = await backendRepository.GetAllAsync<building_floor>(sqlString);

                var builds = Building_floor.GroupBy(a => a.building_guid).ToList();
                foreach (var floor in builds)
                {
                    BuildingToF buildingToF1 = new BuildingToF()
                    {
                        building_guid = floor.Select(a => a.building_guid).FirstOrDefault(),
                        building_name = floor.Select(a => a.buildingname).FirstOrDefault(),
                        floors = new List<FloorForB>()
                    };
                    foreach (var f in floor)
                    {
                        FloorForB floorForB = new FloorForB()
                        {
                            floor_guid = f.floor_guid,
                            floor_name = f.floorname
                        };
                        buildingToF1.floors.Add(floorForB);
                    }
                    buildingToF.Add(buildingToF1);
                }
                apiResult.Code = "0000";
                apiResult.Data = buildingToF;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return Ok(apiResult);
        }

        [HttpPost]
        [Route("api/EmergencyDevice")]
        public async Task<ActionResult<ApiResult<List<deviceMenu>>>> EmergencyDevice(selectdevice selectdevice)
        {
            ApiResult<List<deviceMenu>> apiResult = new ApiResult<List<deviceMenu>>();
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            List<deviceMenu> Variable = new List<deviceMenu>();

            try
            {

                var sqlString = @$"select 
                                    d.device_guid,
                                    d.device_number,
                                    d.full_name AS device_name,
                                    d.building_guid,
                                    b.full_name AS building_name,
                                    CONCAT(b.ip_address , ':', b.ip_port) AS ip_address,
                                    v.layer2,
                                    v.layer2_name,
                                    v.system_value AS layer3,
                                    v.system_key AS layer3_name,
                                    dd.device_system_value AS disaster,
                                    ddd.system_key AS disaster_name,
                                    floor.full_name floorname,
                                    floor.floor_guid floorguid
                                    from 
                                        (SELECT * 
                                            FROM device d
                                        WHERE d.deleted = 0 
                                          AND d.building_guid = '{selectdevice.selectbuilding}'
                                          AND d.floor_guid in @floor
                                          AND d.device_system_category_layer3 IN @layer3) d
                                    left join floor on floor.floor_guid = d.floor_guid
                                    left join (
                                                SELECT 
                                                    v.*,
                                                    v2.system_key AS layer2_name,
                                                    v2.system_value AS layer2
                                                FROM (
                                                    select * 
                                                    from variable v 
                                                    where v.system_type = 'device_system_category_layer3') v
                                                LEFT JOIN variable v2 ON v2.deleted = 0 AND v.system_parent_id = v2.id
                                              ) v on v.system_value = d.device_system_category_layer3
                                    left join device_disaster dd on dd.device_guid = d.device_guid
                                    left join (select * from variable v where v.system_type = 'disaster') ddd on ddd.system_value = dd.device_system_value
                                    LEFT JOIN building b ON b.deleted = 0 AND d.building_guid = b.building_guid
                                    where dd.device_system_value IN @disasters
                                    ORDER BY d.device_number
                                    ";
                Variable = await backendRepository.GetAllAsync<deviceMenu>(sqlString, new { disasters= selectdevice.select_disasters, floor = selectdevice.select_Floors, layer3 = selectdevice.select_Layer3 });

                apiResult.Code = "0000";
                apiResult.Data = Variable;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return Ok(apiResult);
        }


        [HttpPost]
        [Route("api/EmergencyDevice/SaveAndOpenSimulationExercise")]
        public async Task<ActionResult<ApiResult<string>>> SaveAndOpenSimulationExercise(Eventpost eventpost)
        {
            ApiResult<string> apiResult = new ApiResult<string>();
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            try
            {
                var newguid = Guid.NewGuid();
                var dictionary = new Dictionary<string, object>()
                    {
                        {"@emergency_event_guid",newguid},
                        {"@disaster",eventpost.disaster},
                        {"@building_guid", eventpost.build},
                        {"@device_guid",eventpost.device },
                        {"@type",eventpost.type}
                    };
                await backendRepository.AddOneByCustomTable(dictionary, "emergency_event");
                apiResult.Data = newguid.ToString();
                apiResult.Code = "0000";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }
            return Ok(apiResult);
        }


        [HttpPost]
        [Route("api/EmergencyDevice/GetBigsetting")]
        public async Task<ActionResult<ApiResult<List<SaveGrouping>>>> GetBigsetting(int disaster)
        {
            ApiResult<List<SaveGrouping>> apiResult = new ApiResult<List<SaveGrouping>>();
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            try
            {
                var sql = $@"  
                      select 
                      v.id id,
                      v.system_key name,
                      f.system_value verify
                      from variable v 
                      join variable f on v.id = f.system_parent_id and f.system_type = 'Verify'
                      where v.system_type = 'DisasterSetting' 
                      and v.system_parent_id = '{disaster}' 
                      and v.deleted = 0 
                      order by v.system_priority";


                var list = await backendRepository.GetAllAsync<SaveGrouping>(sql);

                apiResult.Data = list;
                apiResult.Code = "0000";
                apiResult.Msg = "新增成功";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
            }
            return Ok(apiResult);
        }


        [HttpPost]
        [Route("api/EmergencyDevice/GetEmergencySetting")]
        public async Task<ActionResult<ApiResult<List<EmergencySettingTable>>>> GetEmergencySetting(int selectsetting)
        {
            List<EmergencySettingTable> Emergency_Setting_tables = new List<EmergencySettingTable>();
            ApiResult<List<EmergencySettingTable>> apiResult = new ApiResult<List<EmergencySettingTable>>();
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            try
            {
                Emergency_Setting_tables = await backendRepository.GetAllAsync<EmergencySettingTable>($@"
                    select v.system_key big_setting_name,* from emergency_setting es left join variable v on es.big_setting = v.id
                    where es.big_setting = {selectsetting} and es.deleted = 0 order by es.priority");
                apiResult.Code = "0000";
                apiResult.Data = Emergency_Setting_tables;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }
            return Ok(apiResult);
        }


        [HttpPost]
        [Route("api/EmergencyDevice/GetContentAndMakeItem")]
        public async Task<ActionResult<ApiResult<EmergencyitemWithguid>>> GetContentAndMakeItem(Emergencyitempost post)
        {

            ApiResult<EmergencyitemWithguid> apiResult = new ApiResult<EmergencyitemWithguid>();
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            try
            {
                var Emergency_Setting_tables = await backendRepository.GetOneAsync<EmergencyitemWithguid>($@"
                    select v.system_key big_setting_name,* from emergency_setting es left join variable v on es.big_setting = v.id
                    where es.emergency_guid = '{post.emergency_guid}'");

                if (post.make_item == 1)
                {
                    var haveguid = await backendRepository.GetOneAsync<string>($"select emergency_item_guid from emergency_item where event_guid = '{post.event_guid}' and big_setting = '{post.big_setting}' and step_setting = '{post.step_setting}'");
                    if (haveguid == null)
                    {
                        var newguid = Guid.NewGuid();
                        var dictionary = new Dictionary<string, object>()
                        {
                            {"@emergency_item_guid",newguid},
                            {"@event_guid",post.event_guid},
                            {"@big_setting", post.big_setting},
                            {"@step_setting",post.step_setting},
                            {"@created_by",myUser.userinfo_guid }
                        };
                        await backendRepository.AddOneByCustomTable(dictionary, "emergency_item");
                        Emergency_Setting_tables.emergency_item_guid = newguid.ToString();
                    }
                    else
                    {
                        Emergency_Setting_tables.emergency_item_guid = haveguid;
                    }
                }

                apiResult.Code = "0000";
                apiResult.Data = Emergency_Setting_tables;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }
            return Ok(apiResult);
        }

        [HttpPost]
        [Route("api/EmergencyDevice/NextStep")]
        public async Task<ActionResult<ApiResult<string>>> NextStep(Itempost item)
        {
            ApiResult<string> apiResult = new ApiResult<string>();
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            byte finish = 0;
            if (item.choose == 0)
            {
                finish = 1;
            }
            else
            {
                finish = 2;
            }
            try
            {
                var dictionary = new Dictionary<string, object>()
                {
                    {"@finished",finish},
                    {"@updated_by", myUser.userinfo_guid},
                    {"@updated_at", DateTime.Now}
                };
                if (item.choose == 1)
                {
                    dictionary.Add("@reason", item.reason);
                }
                await backendRepository.UpdateOneByCustomTable(dictionary, "emergency_item", $"emergency_item_guid = '{item.eventguid}'");
                apiResult.Code = "0000";
                apiResult.Msg = "更新成功";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                string json = System.Text.Json.JsonSerializer.Serialize(item);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }
            return Ok(apiResult);
        }

        [HttpPost]
        [Route("api/EmergencyDevice/GetGroupingList")]
        public async Task<ActionResult<ApiResult<List<KeyValueID>>>> GetGroupingList(int system_parent_id)
        {
            ApiResult<List<KeyValueID>> apiResult = new ApiResult<List<KeyValueID>>();
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            List<KeyValueID> keyvalue = new List<KeyValueID>();
            try
            {
                keyvalue = await backendRepository.GetAllAsync<KeyValueID>($"select id, system_key as name,system_value as value from variable where deleted = 0 and system_parent_id = {system_parent_id} and system_type = 'grouping' order by system_priority");
                apiResult.Data = keyvalue;
                apiResult.Code = "0000";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }
            return Ok(apiResult);
        }


        [HttpPost]
        [Route("api/EmergencyDevice/Dohistorytotable")]
        public async Task<ActionResult> Dohistorytotable(string eventguid)
        {
            List<Eventitem> eventitems = new List<Eventitem>();
            ApiResult<List<Eventitem>> apiResult = new ApiResult<List<Eventitem>>();
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            try
            {
                eventitems = await backendRepository.GetAllAsync<Eventitem>($"select * from emergency_item where event_guid = @Guid", new { Guid = $"{eventguid}" });
                apiResult.Data = eventitems;
                apiResult.Code = "0000";
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }
            var result = Json(new
            {
                data = apiResult
            });
            return result;
        }


        [HttpPost]
        [Route("api/EmergencyDevice/EmergencyContactTable")]
        public async Task<ActionResult> EmergencyContactTable(List<int> selectgroupidlist)
        {
            List<EmergencyContactTable> Emergency_member_tables = new List<EmergencyContactTable>();
            ApiResult<List<EmergencyContactTable>> apiResult = new ApiResult<List<EmergencyContactTable>>();
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            try
            {
                Emergency_member_tables = await backendRepository.GetAllAsync<EmergencyContactTable>($@"
                    select  v.system_key groupingName,va.system_key departmentName,* from emergency_member em left join variable v on em.grouping = v.id
                    left join (select * from variable vs where vs.system_type = 'department' and vs.deleted = 0) va on va.system_value = em.department
                    where em.grouping in @groupinglist and em.deleted = 0", new { groupinglist = selectgroupidlist });
                apiResult.Code = "0000";
                apiResult.Data = Emergency_member_tables;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }
            var result = Json(new
            {
                data = apiResult
            });
            return result;
        }


        [HttpPost]
        [Route("api/EmergencyDevice/GetDeviceGroup")]
        public async Task<ActionResult<ApiResult<List<GetDeviceGroup>>>> GetDeviceGroup()
        {
            List<EmergencyDeviceGroup> getDeviceGroup = new List<EmergencyDeviceGroup>();
            ApiResult<List<GetDeviceGroup>> apiResult = new ApiResult<List<GetDeviceGroup>>();
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            List<GetDeviceGroup> finalDeviceGroup = new List<GetDeviceGroup>();
            try
            {
                getDeviceGroup = await backendRepository.GetAllAsync<EmergencyDeviceGroup>($@"
                    select dg.*,vd.system_key disater_name,b.full_name building_name,f.full_name floor_name,v2.system_key system_category_layer2,v3.system_key system_category_layer3 from (SELECT * FROM device_group dg WHERE dg.device_disaster != 0) dg
                    left join (select * from variable v where v.system_type = 'disaster' and v.deleted = 0) vd on vd.system_value = dg.device_disaster
                    left join building b on b.building_guid = dg.device_building_guid
                    left join floor f on f.floor_guid = dg.device_floor_guid
                    left join (select * from variable v where v.system_type = 'device_system_category_layer2' and v.deleted = 0) v2 on v2.system_value = dg.device_system_category_layer2
                    left join (select * from variable v where v.system_type = 'device_system_category_layer3' and v.deleted = 0) v3 on v3.system_value = dg.device_system_category_layer3
                    order by vd.system_priority,b.priority,f.priority,v2.system_priority,v3.system_priority");

                var dis = getDeviceGroup.GroupBy(a => a.device_disaster);
                //finalDeviceGroup.disaster = new List<KeyValue>();
                foreach (var diss in dis)
                {
                    GetDeviceGroup getDeviceGroup1 = new GetDeviceGroup()
                    {
                        Value = diss.Key,
                        Name = diss.Select(a => a.disater_name).FirstOrDefault().ToString(),
                        groupBuildings = new List<GroupBuildings>()
                    };
                    var buds = diss.GroupBy(a => a.device_building_guid);
                    getDeviceGroup1.groupBuildings = new List<GroupBuildings>();
                    foreach (var bud in buds)
                    {
                        GroupBuildings groupBuildings = new GroupBuildings()
                        {
                            guid = bud.Key,
                            name = bud.Select(a => a.building_name).FirstOrDefault().ToString(),
                            device_amount = 0,
                            groupFloors = new List<GroupFloor>()
                        };
                        var floors = bud.GroupBy(a => a.device_floor_guid);
                        foreach (var floor in floors)
                        {
                            GroupFloor groupFloor = new GroupFloor()
                            {
                                guid = floor.Key,
                                name = floor.Select(a => a.floor_name).FirstOrDefault().ToString(),
                                groupLayer2s = new List<GroupLayer2>()
                            };

                            var layer2s = floor.GroupBy(a => a.device_system_category_layer2);
                            foreach (var layer2 in layer2s)
                            {

                                GroupLayer2 groupLayer2 = new GroupLayer2()
                                {
                                    value = layer2.Key,
                                    name = layer2.Select(a => a.system_category_layer2).FirstOrDefault().ToString(),
                                    device_amount = 0,
                                    groupLayer3s = new List<GroupLayer3>()
                                };

                                var layer3s = layer2.GroupBy(a => a.device_system_category_layer3);
                                foreach (var layer3 in layer3s)
                                {

                                    GroupLayer3 groupLayer3 = new GroupLayer3()
                                    {
                                        value = layer3.Key,
                                        name = layer3.Select(a => a.system_category_layer3).FirstOrDefault().ToString(),
                                        device_amount = layer3.Select(a => a.device_amount).FirstOrDefault()
                                    };
                                    groupLayer2.groupLayer3s.Add(groupLayer3);

                                }

                                groupFloor.groupLayer2s.Add(groupLayer2);
                            }

                            groupBuildings.groupFloors.Add(groupFloor);
                        }

                        getDeviceGroup1.groupBuildings.Add(groupBuildings);
                    }

                    finalDeviceGroup.Add(getDeviceGroup1);
                }

                apiResult.Code = "0000";
                apiResult.Data = finalDeviceGroup;
            }
            catch (Exception exception)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + exception.Message);
            }

            return Ok(apiResult);
        }


        [HttpPost]
        [Route("api/EmergencyDevice/CheckVerifybool")]
        public async Task<ActionResult<ApiResult<bool>>> CheckVerifybool(string pass)
        {
            ApiResult<bool> apiResult = new ApiResult<bool>();
            if (!jwtlife)
            {
                apiResult.Code = "5000";
                return BadRequest(apiResult);
            }
            try
            {
                EDFunction edFunction = new EDFunction();
                string passto = "";
                if (pass != null)
                {
                    passto = edFunction.GetSHA256Encryption(pass);
                }
                var Verify = await backendRepository.GetAllAsync<string>("userinfo", $" role_guid = 'B0556AD7-C1E1-47A1-A1F1-802E22714B33' and password = '{passto}'");

                if (Verify.Count == 0)
                {
                    apiResult.Data = false;
                }
                else
                {
                    apiResult.Data = true;
                }
                apiResult.Code = "0000";
            }
            catch (Exception ex)
            {
                apiResult.Code = "9999";
                apiResult.Msg = "系統內部錯誤,請聯絡管理者。";
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + pass);
                Logger.LogError("【" + controllerName + "/" + actionName + "】" + ex.Message);
            }
            return Ok(apiResult);
        }
    }
}