package com.nokia.tsl_data.dao;

import com.nokia.tsl_data.entity.SysDataDictionary;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import java.sql.Types;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;

/**
 * 从 工作流数据库 读取
 */
/* cSpell: disable */
@Slf4j
@Component
public class WorkFlowDao {

        private final JdbcTemplate jdbcTemplate;

        public WorkFlowDao(@Qualifier("workFlowJdbcTemplate") JdbcTemplate jdbcTemplate) {
                this.jdbcTemplate = jdbcTemplate;
        }

        // 获取全部地市信息
        public List<SysDataDictionary> findSysDataDictionaryForCity() {
                return findSysDataDictionaries("city");
        }

        // 获取全部区县信息
        public List<SysDataDictionary> findSysDataDictionaryForRegion() {
                return findSysDataDictionaries("region");
        }

        // 读取某种类型的字典表
        public List<SysDataDictionary> findSysDataDictionaries(String type) {
                String sql = "select id, name, type_code from sys_data_dictionary sdd where type_code = ? ";
                return jdbcTemplate.query(sql,
                                (ps) -> {
                                        ps.setString(1, type);
                                },
                                (rs, rowNum) -> {
                                        SysDataDictionary sysDataDictionary = new SysDataDictionary();
                                        sysDataDictionary.setType("work_flow_" + rs.getString("type_code"));
                                        sysDataDictionary.setNickCode(rs.getString("id"));
                                        sysDataDictionary.setNickName(rs.getString("name"));
                                        return sysDataDictionary;
                                });
        }

        // 获取update_time在两个范围之间的全部工单信息
        // 20240205 不再使用
        @Deprecated
        public List<Map<String, Object>> findWorkFlowBasicDataByUpdateTime(Instant start, Instant end) {
                // 20240112 修改 使用 serv_order 替换了kfsn
                String sql = "select order_no, " + //
                                "city as city_id, " + //
                                "is_effctive as is_effctive, " + //
                                "form_basic_data->>'yh_region' as region_id, " + //
                                "form_basic_data->>'serv_order' as kfsn, " + //
                                "form_basic_data->>'kd_accepttime' as kd_accepttime, " + //
                                "form_basic_data->>'kd_requestreplytime' as kd_requestreplytime, " + //
                                "form_basic_data->>'re_is_status' as re_is_status_id, " + //
                                "form_basic_data->>'kf_file_time' as kf_file_time, " + //
                                "form_basic_data->>'kf_file_type' as kf_file_type, " + //
                                "create_time as work_flow_create_time,  " + //
                                "update_time as work_flow_update_time " + //
                                "from flow_form_basic " + //
                                "where update_time >= to_timestamp(?, 'yyyy-mm-dd hh24:mi:ss') " + //
                                "and update_time <= to_timestamp(?, 'yyyy-mm-dd hh24:mi:ss') ";
                DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
                                .withZone(ZoneId.of("Asia/Shanghai"));
                Object[] objects = new Object[] { dateFormat.format(start), dateFormat.format(end) };
                int[] argTypes = new int[] { Types.TIMESTAMP, Types.TIMESTAMP };
                return jdbcTemplate.queryForList(sql, objects, argTypes);
        }

        /**
         * 直接从工作流读取处理时长数据
         */
        @Deprecated
        public List<Map<String, Object>> selectTsDurationBasicData(Instant start, Instant end) {
                String sql = "with t1 as (select city as city_id, \r\n" + //
                                "form_basic_data->>'serv_order' as kfsn,\r\n" + //
                                "(extract(epoch from to_timestamp(form_basic_data->>'kf_file_time', 'YYYY-MM-DD HH24:MI:SS')) -\r\n"
                                + //
                                "extract(epoch from to_timestamp(form_basic_data->>'kd_accepttime', 'YYYY-MM-DD HH24:MI:SS'))) /\r\n"
                                + //
                                "3600 as cost_time \r\n" + //
                                "from flow_form_basic\r\n" + //
                                "where form_basic_data->>'re_is_status' != '06678b79185349b5bf0c24490a978fbb' \r\n" + //
                                "and form_basic_data->>'kf_file_time' is not null \r\n" + //
                                "and is_effctive = '1'\r\n" + //
                                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') >= ? \r\n"
                                + //
                                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') < ? \r\n" + //
                                "select city_id, kfsn, min(cost_time) as cost_time from t1 group by city_id, kfsn";
                DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
                                .withZone(ZoneId.of("Asia/Shanghai"));
                Object[] objects = new Object[] { dateFormat.format(start), dateFormat.format(end) };
                int[] argTypes = new int[] { Types.TIMESTAMP, Types.TIMESTAMP };
                Long startLong = System.currentTimeMillis();
                List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, objects, argTypes);
                log.debug("从工作流读取处理时长数据, 耗时 {} ms...", System.currentTimeMillis() - startLong);
                return result;
        }

        // 20240304 修改平均处理时长算法
        // 20240313 增加过滤条件 客服工单号不以 ZHX 开头
        public List<Map<String, Object>> selectTsDurationForDayV2(String start, String end) {
                String sql = "with t1 as (select order_no, city as city_id, form_basic_data->>'serv_order' as kfsn " +
                                ", form_basic_data->>'kd_accepttime' as kd_accepttime " +
                                "from flow_form_basic where is_effctive = '1' " +
                                "and substring(form_basic_data->>'serv_order' from 1 for 3) != 'ZHX' " +
                                "and create_time >= ? and create_time <= ? " +
                                "and form_basic_data->>'kd_accepttime' >= ? " +
                                "and form_basic_data->>'kd_accepttime' <= ?) " +
                                ", t2 as (select order_no, res_date " +
                                "from complaint.kf_log), " +
                                "t3 as (select t1.order_no, t1.city_id, t1.kfsn," +
                                "extract(epoch from coalesce(to_timestamp(max(t2.res_date), 'yyyy-mm-dd hh24:mi:ss'), now())) "
                                +
                                "- extract(epoch from to_timestamp(min(t1.kd_accepttime), 'yyyy-mm-dd hh24:mi:ss')) as cost_time "
                                +
                                "from t1 left join t2 " +
                                "on t1.order_no = t2.order_no " +
                                "group by t1.order_no, t1.city_id, t1.kfsn) " +
                                ", t4 as (select city_id, kfsn, min(cost_time) as cost_time from t3 group by city_id, kfsn) "
                                +
                                ", t5 as (select city_id, avg(cost_time)::float8/3600 as avg_duration from t4 group by city_id) "
                                +
                                ", t6 as (select '全省', avg(cost_time)::float8/3600 as avg_duration from t4) " +
                                "select * from t5 union select * from t6";
                Object[] objects = new Object[] { start, end, start, end };
                int[] argTypes = new int[] { Types.TIMESTAMP, Types.TIMESTAMP, Types.TIMESTAMP, Types.TIMESTAMP };
                Long startLong = System.currentTimeMillis();
                List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, objects, argTypes);
                log.debug("从工作流读取{}-{}平均处理时长数据, 耗时 {} ms, sql: {}",
                                start,
                                end,
                                System.currentTimeMillis() - startLong,
                                sql);
                return result;
        }

        // 20240304 之前获取平均处理时长的sql语句
        @Deprecated
        public List<Map<String, Object>> selectTsDurationForDay(Instant start, Instant end) {
                String sql = "with t1 as (select city as city_id, \r\n" + //
                                "form_basic_data->>'serv_order' as kfsn,\r\n" + //
                                "(extract(epoch from to_timestamp(form_basic_data->>'kf_file_time', 'YYYY-MM-DD HH24:MI:SS'))\r\n"
                                + //
                                "- extract(epoch from to_timestamp(form_basic_data->>'kd_accepttime', 'YYYY-MM-DD HH24:MI:SS')))\r\n"
                                + //
                                "/ 3600 as cost_time \r\n" + //
                                "from flow_form_basic\r\n" + //
                                "where form_basic_data->>'re_is_status' != '06678b79185349b5bf0c24490a978fbb'\r\n" + //
                                "and form_basic_data->>'kf_file_time' is not null \r\n" + //
                                "and is_effctive = '1'\r\n" + //
                                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') >= ?\r\n" + //
                                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') < ?),\r\n"
                                + //
                                "t2 as (select city_id, kfsn, min(cost_time) as cost_time from t1 group by city_id, kfsn),\r\n"
                                + //
                                "t3 as (select city_id, avg(cost_time)::float8 as avg_duration from t2 group by city_id),\r\n"
                                + //
                                "t4 as (select '全省' as city_id, avg(cost_time)::float8 as avg_duration from t2)\r\n" + //
                                "select * from  t3 union select * from t4";
                DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
                                .withZone(ZoneId.of("Asia/Shanghai"));
                Object[] objects = new Object[] { dateFormat.format(start), dateFormat.format(end) };
                int[] argTypes = new int[] { Types.TIMESTAMP, Types.TIMESTAMP };
                Long startLong = System.currentTimeMillis();
                List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, objects, argTypes);
                log.debug("从工作流读取{}-{}平均处理时长数据, 耗时 {} ms...",
                                start,
                                end,
                                System.currentTimeMillis() - startLong);
                return result;
        }

        // 20240326 要求修改为 使用 回单答复超时 字段统计，排除ZHX开头的工单
        // 
        public List<Map<String, Object>> selectTimeoutTsCountForDayV2(Instant start, Instant end) {
                String sql = "with t1 as (select order_no, city as city_id, \r\n" + //
                                "form_basic_data->>'serv_order' as kfno,\r\n" + //
                                "form_basic_data ->> 'res_is_timeout' as is_timeout, \r\n" + //
                                "form_basic_data->>'kd_accepttime' as kd_accepttime\r\n" + //
                                "from flow_form_basic\r\n" + //
                                "where is_effctive = '1'\r\n" + //
                                "and substring(form_basic_data->>'serv_order' from 1 for 3) != 'ZHX'\r\n" + //
                                "and form_basic_data->>'kd_accepttime' >= ? " + //
                                "and form_basic_data->>'kd_accepttime' <= ? ), " + //
                                "t2 as (select '全省' as city_id, count(1) as total_num, \r\n" + //
                                "count(is_timeout = 'ca9d5f1f8363440699f11b802150eb77' or null) as timeout_num,\r\n" + //
                                "count(is_timeout = 'ca9d5f1f8363440699f11b802150eb77' or null)::float8 / count(1) as timeout_ratio\r\n"
                                + "from t1),\r\n" + //
                                "t3 as (select city_id, count(1) as total_num, \r\n" + //
                                "count(is_timeout = 'ca9d5f1f8363440699f11b802150eb77' or null) as timeout_num,\r\n" + //
                                "count(is_timeout = 'ca9d5f1f8363440699f11b802150eb77' or null)::float8 / count(1) as timeout_ratio\r\n"
                                + "from t1 group by city_id)\r\n" + //
                                "select * from t2 union select * from t3";
                DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
                                .withZone(ZoneId.of("Asia/Shanghai"));
                Object[] objects = new Object[] { dateFormat.format(start), dateFormat.format(end) };
                int[] argTypes = new int[] { Types.TIMESTAMP, Types.TIMESTAMP };
                Long startLong = System.currentTimeMillis();
                List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, objects, argTypes);
                log.debug("从工作流读取{}-{}超时工单数据, 耗时 {} ms...",
                                start,
                                end,
                                System.currentTimeMillis() - startLong);
                return result;
        }

        // 20240326 要求修改为 使用 回单答复超时 字段统计，排除ZHX开头的工单
        @Deprecated
        public List<Map<String, Object>> selectTimeoutTsCountForDay(Instant start, Instant end, int target) {
                String sql = "with t1 as (select distinct city as city_id, \r\n" + //
                                "form_basic_data->>'serv_order' as kfsn,\r\n" + //
                                "to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') - \r\n" + //
                                "to_timestamp(form_basic_data->>'kd_accepttime', 'yyyy-mm-dd hh24:mi:ss') \r\n" + //
                                "> make_interval(hours => ?) as is_timeout \r\n" + //
                                "from flow_form_basic\r\n" + //
                                "where form_basic_data->>'re_is_status' != '06678b79185349b5bf0c24490a978fbb'\r\n" + //
                                "and form_basic_data->>'kf_file_time' is not null \r\n" + //
                                "and is_effctive = '1'\r\n" + //
                                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') >= ?\r\n" + //
                                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') <= ?),\r\n"
                                + //
                                "t2 as (select '全省' as city_id, count(1) as total_num, count(is_timeout or null) as timeout_num,\r\n"
                                + //
                                "count(is_timeout or null)::float8 / count(1) as timeout_ratio from t1),\r\n" + //
                                "t3 as (select city_id, count(1) as total_num, count(is_timeout or null) as timeout_num,\r\n"
                                + //
                                "count(is_timeout or null)::float8 / count(1) as timeout_ratio from t1 group by city_id)\r\n"
                                + //
                                "select * from  t2 union select * from t3";
                DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
                                .withZone(ZoneId.of("Asia/Shanghai"));
                Object[] objects = new Object[] { target, dateFormat.format(start), dateFormat.format(end) };
                int[] argTypes = new int[] { Types.INTEGER, Types.TIMESTAMP, Types.TIMESTAMP };
                Long startLong = System.currentTimeMillis();
                List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, objects, argTypes);
                log.debug("从工作流读取{}-{}超时工单数据, 耗时 {} ms...",
                                start,
                                end,
                                System.currentTimeMillis() - startLong);
                return result;
        }

        @Deprecated
        public List<Map<String, Object>> selectTsDurationForMonth(String month) {
                String sql = "with t1 as (select city as city_id, \r\n" + //
                                "form_basic_data->>'serv_order' as kfsn,\r\n" + //
                                "(extract(epoch from to_timestamp(form_basic_data->>'kf_file_time', 'YYYY-MM-DD HH24:MI:SS'))\r\n"
                                + //
                                "- extract(epoch from to_timestamp(form_basic_data->>'kd_accepttime', 'YYYY-MM-DD HH24:MI:SS')))\r\n"
                                + //
                                "/ 3600 as cost_time \r\n" + //
                                "from flow_form_basic\r\n" + //
                                "where form_basic_data->>'re_is_status' != '06678b79185349b5bf0c24490a978fbb'\r\n" + //
                                "and form_basic_data->>'kf_file_time' is not null \r\n" + //
                                "and is_effctive = '1'\r\n" + //
                                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') >= " +
                                "to_timestamp(concat(?, '01000000'), 'yyyymmddhh24miss') " +
                                "and to_timestamp(form_basic_data->>'kf_file_time', 'yyyy-mm-dd hh24:mi:ss') < " +
                                "(to_timestamp(concat(?, '01000000'), 'yyyymmddhh24miss') + interval '1 month'))," +
                                "t2 as (select city_id, kfsn, min(cost_time) as cost_time from t1 group by city_id, kfsn),\r\n"
                                + //
                                "t3 as (select ? as month_id, city_id, avg(cost_time)::float8 as avg_duration from t2 group by city_id),"
                                + "t4 as (select ? as month_id, '全省' as city_id, avg(cost_time)::float8 as avg_duration from t2)"
                                +
                                "select * from  t3 union select * from t4";
                Object[] objects = new Object[] { month, month, month, month };
                int[] argTypes = new int[] { Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR };
                Long startLong = System.currentTimeMillis();
                List<Map<String, Object>> result = jdbcTemplate.queryForList(sql, objects, argTypes);
                log.debug("从工作流读取{}月平均处理时长数据, 耗时 {} ms...",
                                month,
                                System.currentTimeMillis() - startLong);
                return result;
        }
}
