<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.zcloud.personnel.positioning.persistence.mapper.TerminalMapper">
    <sql id="mappedCompanyJoins">
        LEFT JOIN (
            SELECT local_corpinfo_id, MAX(local_corpinfo_name) AS local_corpinfo_name
            FROM org_match
            WHERE match_status = 'MATCHED'
              AND (delete_enum IS NULL OR delete_enum = 'FALSE')
              AND local_corpinfo_id IS NOT NULL AND local_corpinfo_id != ''
            GROUP BY local_corpinfo_id
        ) mapped_org ON mapped_org.local_corpinfo_id = CAST(t.corpinfo_id AS CHAR)
        LEFT JOIN corp_info corp_uuid
          ON mapped_org.local_corpinfo_id IS NULL
         AND CAST(corp_uuid.corpinfo_id AS CHAR) = CAST(t.corpinfo_id AS CHAR)
         AND (corp_uuid.delete_enum IS NULL OR corp_uuid.delete_enum = 'FALSE')
        LEFT JOIN corp_info corp_internal
          ON mapped_org.local_corpinfo_id IS NULL
         AND corp_uuid.corpinfo_id IS NULL
         AND CAST(corp_internal.id AS CHAR) = CAST(t.corpinfo_id AS CHAR)
         AND (corp_internal.delete_enum IS NULL OR corp_internal.delete_enum = 'FALSE')
    </sql>

    <sql id="mappedCompanyId">
        COALESCE(mapped_org.local_corpinfo_id, CAST(corp_uuid.corpinfo_id AS CHAR),
                 CAST(corp_internal.corpinfo_id AS CHAR))
    </sql>

    <sql id="mappedCompanyName">
        COALESCE(mapped_org.local_corpinfo_name, corp_uuid.corp_name, corp_internal.corp_name)
    </sql>

    <sql id="cardCompanyJoinAndWhere">
        FROM terminal t
        <include refid="mappedCompanyJoins"/>
        WHERE (t.delete_enum IS NULL OR t.delete_enum = 'FALSE')
          AND t.device_type = 'CARD'
          AND <include refid="mappedCompanyId"/> IS NOT NULL
        <if test="params.eqCorpinfoId != null and params.eqCorpinfoId != ''">
            AND <include refid="mappedCompanyId"/> = #{params.eqCorpinfoId}
        </if>
        <if test="params.likeCorpinfoName != null and params.likeCorpinfoName != ''">
            AND (t.corpinfo_name LIKE CONCAT('%', #{params.likeCorpinfoName}, '%')
                OR t.org_name LIKE CONCAT('%', #{params.likeCorpinfoName}, '%')
                OR <include refid="mappedCompanyName"/> LIKE CONCAT('%', #{params.likeCorpinfoName}, '%'))
        </if>
        <if test="params.likeContactName != null and params.likeContactName != ''">
            AND (COALESCE(corp_uuid.contacts, corp_internal.contacts) LIKE CONCAT('%', #{params.likeContactName}, '%')
                OR COALESCE(corp_uuid.lr_name, corp_internal.lr_name) LIKE CONCAT('%', #{params.likeContactName}, '%'))
        </if>
        <if test="params.eqEnable != null">
            AND t.enable = #{params.eqEnable}
        </if>
    </sql>

    <select id="listCardCompanyStats"
            resultType="com.zcloud.personnel.positioning.persistence.dataobject.TerminalCardCompanyStatDO">
        SELECT <include refid="mappedCompanyId"/> AS corpinfo_id,
               <include refid="mappedCompanyName"/> AS corpinfo_name,
               MAX(NULLIF(t.org_code, '')) AS org_code,
               MAX(NULLIF(t.org_name, '')) AS org_name,
               COALESCE(MAX(NULLIF(corp_uuid.contacts, '')), MAX(NULLIF(corp_internal.contacts, '')),
                        MAX(NULLIF(corp_uuid.lr_name, '')), MAX(NULLIF(corp_internal.lr_name, ''))) AS contact_name,
               COUNT(1) AS card_count,
               SUM(CASE WHEN t.enable = 1 THEN 1 ELSE 0 END) AS enabled_count,
               MAX(t.last_sync_time) AS last_sync_time
        <include refid="cardCompanyJoinAndWhere"/>
        GROUP BY <include refid="mappedCompanyId"/>, <include refid="mappedCompanyName"/>
        ORDER BY MAX(t.last_sync_time) DESC, MAX(t.update_time) DESC
    </select>

    <sql id="cardDetailSelect">
        SELECT t.id, t.terminal_no, t.terminal_name, t.terminal_model, t.sim_card_no,
               <include refid="mappedCompanyId"/> AS corpinfo_id,
               <include refid="mappedCompanyName"/> AS corpinfo_name,
               t.org_code, t.org_name, t.enable, t.device_status,
               COALESCE(tb.id_card_no, t.bind_id_card_no) AS active_id_card_no,
               COALESCE(tb.staff_no_snapshot, u.username) AS staff_no,
               COALESCE(u.name, tb.staff_name_snapshot) AS staff_name,
               u.phone AS staff_phone, tb.bind_status, t.finds_terminal_id,
               t.last_location_time, t.last_location_name, t.last_sync_time,
               t.sync_status, t.remarks
    </sql>

    <sql id="cardDetailJoinAndWhere">
        FROM terminal t
        LEFT JOIN terminal_bind tb ON tb.id = (
            SELECT tb2.id
            FROM terminal_bind tb2
            WHERE tb2.terminal_no = t.terminal_no
              AND (tb2.delete_enum IS NULL OR tb2.delete_enum = 'FALSE')
              AND tb2.bind_status = 'BOUND'
            ORDER BY tb2.bind_time DESC, tb2.id DESC
            LIMIT 1
        )
        LEFT JOIN user_scope_v u
          ON u.user_id_card = COALESCE(tb.id_card_no, t.bind_id_card_no)
         AND (u.delete_enum IS NULL OR u.delete_enum = 'FALSE')
        <include refid="mappedCompanyJoins"/>
        WHERE (t.delete_enum IS NULL OR t.delete_enum = 'FALSE')
          AND t.device_type = 'CARD'
          AND <include refid="mappedCompanyId"/> IS NOT NULL
        <if test="params.id != null">
            AND t.id = #{params.id}
        </if>
        <if test="params.terminalNo != null and params.terminalNo != ''">
            AND t.terminal_no LIKE CONCAT('%', #{params.terminalNo}, '%')
        </if>
        <if test="params.staffName != null and params.staffName != ''">
            AND (u.name LIKE CONCAT('%', #{params.staffName}, '%')
                OR tb.staff_name_snapshot LIKE CONCAT('%', #{params.staffName}, '%'))
        </if>
        <if test="params.staffNo != null and params.staffNo != ''">
            AND (u.username = #{params.staffNo} OR tb.staff_no_snapshot = #{params.staffNo})
        </if>
        <if test="params.idCardNo != null and params.idCardNo != ''">
            AND COALESCE(tb.id_card_no, t.bind_id_card_no) = #{params.idCardNo}
        </if>
        <choose>
            <when test="params.eqCorpinfoId != null and params.eqCorpinfoId != '' and params.eqCorpinfoName != null and params.eqCorpinfoName != ''">
                AND <include refid="mappedCompanyId"/> = #{params.eqCorpinfoId}
            </when>
            <when test="params.eqCorpinfoId != null and params.eqCorpinfoId != ''">
                AND <include refid="mappedCompanyId"/> = #{params.eqCorpinfoId}
            </when>
            <when test="params.eqCorpinfoName != null and params.eqCorpinfoName != ''">
                AND <include refid="mappedCompanyName"/> = #{params.eqCorpinfoName}
            </when>
        </choose>
        <if test="params.likeCorpinfoName != null and params.likeCorpinfoName != ''">
            AND (t.corpinfo_name LIKE CONCAT('%', #{params.likeCorpinfoName}, '%')
                OR t.org_name LIKE CONCAT('%', #{params.likeCorpinfoName}, '%')
                OR <include refid="mappedCompanyName"/> LIKE CONCAT('%', #{params.likeCorpinfoName}, '%'))
        </if>
        <if test="params.orgCode != null and params.orgCode != ''">
            AND t.org_code = #{params.orgCode}
        </if>
        <if test="params.orgName != null and params.orgName != ''">
            AND t.org_name LIKE CONCAT('%', #{params.orgName}, '%')
        </if>
        <if test="params.enable != null">
            AND t.enable = #{params.enable}
        </if>
        <if test="params.deviceStatus != null and params.deviceStatus != ''">
            AND t.device_status = #{params.deviceStatus}
        </if>
    </sql>

    <select id="listCards"
            resultType="com.zcloud.personnel.positioning.persistence.dataobject.TerminalCardDetailDO">
        <include refid="cardDetailSelect"/>
        <include refid="cardDetailJoinAndWhere"/>
        ORDER BY t.update_time DESC, t.id DESC
    </select>

    <select id="getCardDetail"
            resultType="com.zcloud.personnel.positioning.persistence.dataobject.TerminalCardDetailDO">
        <include refid="cardDetailSelect"/>
        <include refid="cardDetailJoinAndWhere"/>
        LIMIT 1
    </select>

    <select id="listCardPersonOptions"
            resultType="com.zcloud.personnel.positioning.persistence.dataobject.TerminalCardPersonOptionDO">
        SELECT u.id AS user_id, u.username AS staff_no, u.name AS staff_name,
               u.user_id_card AS id_card_no, u.phone AS mobile_no,
               CAST(ci.corpinfo_id AS CHAR) AS corpinfo_id,
               ci.corp_name AS corpinfo_name, u.department_id AS department_id, u.post_name AS post_name
        FROM user_scope_v u
        LEFT JOIN corp_info ci ON ci.id = u.corpinfo_id
        WHERE (u.delete_enum IS NULL OR u.delete_enum = 'FALSE')
        <if test="params.keyword != null and params.keyword != ''">
            AND (u.name LIKE CONCAT('%', #{params.keyword}, '%')
                OR u.username LIKE CONCAT('%', #{params.keyword}, '%')
                OR u.user_id_card LIKE CONCAT('%', #{params.keyword}, '%')
                OR u.phone LIKE CONCAT('%', #{params.keyword}, '%'))
        </if>
        <if test="params.staffName != null and params.staffName != ''">
            AND u.name LIKE CONCAT('%', #{params.staffName}, '%')
        </if>
        <if test="params.staffNo != null and params.staffNo != ''">
            AND u.username = #{params.staffNo}
        </if>
        <if test="params.idCardNo != null and params.idCardNo != ''">
            AND u.user_id_card = #{params.idCardNo}
        </if>
        <if test="params.corpinfoId != null and params.corpinfoId != ''">
            AND CAST(ci.corpinfo_id AS CHAR) = #{params.corpinfoId}
        </if>
        <if test="params.corpinfoName != null and params.corpinfoName != ''">
            AND ci.corp_name LIKE CONCAT('%', #{params.corpinfoName}, '%')
        </if>
        ORDER BY u.name ASC, u.id DESC
    </select>

    <select id="listCardCompanyOptions"
            resultType="com.zcloud.personnel.positioning.persistence.dataobject.TerminalCardCompanyOptionDO">
        SELECT company_id AS corpinfo_id, MAX(company_name) AS corpinfo_name,
               MAX(credit_code) AS credit_code,
               MAX(contact_name) AS contact_name
        FROM (
            SELECT local_corpinfo_id AS company_id, local_corpinfo_name AS company_name,
                   NULL AS credit_code, NULL AS contact_name
            FROM org_match
            WHERE match_status = 'MATCHED'
              AND (delete_enum IS NULL OR delete_enum = 'FALSE')
              AND local_corpinfo_id IS NOT NULL AND local_corpinfo_id != ''
              AND local_corpinfo_name IS NOT NULL AND local_corpinfo_name != ''
            UNION ALL
            SELECT CAST(corpinfo_id AS CHAR), corp_name, code,
                   COALESCE(NULLIF(contacts, ''), lr_name)
            FROM corp_info
            WHERE (delete_enum IS NULL OR delete_enum = 'FALSE')
              AND corpinfo_id IS NOT NULL AND corp_name IS NOT NULL
        ) platform_company
        WHERE 1 = 1
        <if test="params.keyword != null and params.keyword != ''">
            AND (company_name LIKE CONCAT('%', #{params.keyword}, '%')
                OR credit_code LIKE CONCAT('%', #{params.keyword}, '%')
                OR contact_name LIKE CONCAT('%', #{params.keyword}, '%'))
        </if>
        GROUP BY company_id
        ORDER BY corpinfo_name ASC
        LIMIT 200
    </select>

    <select id="listAppCompanyStats"
            resultType="com.zcloud.personnel.positioning.persistence.dataobject.TerminalAppCompanyStatDO">
        SELECT <include refid="mappedCompanyId"/> AS corpinfo_id,
               <include refid="mappedCompanyName"/> AS corpinfo_name,
               MAX(NULLIF(t.org_code, '')) AS org_code,
               MAX(NULLIF(t.org_name, '')) AS org_name,
               COALESCE(MAX(NULLIF(corp_uuid.contacts, '')), MAX(NULLIF(corp_internal.contacts, '')),
                        MAX(NULLIF(corp_uuid.lr_name, '')), MAX(NULLIF(corp_internal.lr_name, ''))) AS contact_name,
               COUNT(1) AS app_count,
               SUM(CASE WHEN t.enable = 1 THEN 1 ELSE 0 END) AS enabled_count,
               MAX(t.last_sync_time) AS last_sync_time
        FROM terminal t
        <include refid="mappedCompanyJoins"/>
        WHERE (t.delete_enum IS NULL OR t.delete_enum = 'FALSE') AND t.device_type = 'APP'
          AND <include refid="mappedCompanyId"/> IS NOT NULL
        <if test="params.eqCorpinfoId != null and params.eqCorpinfoId != ''">
            AND <include refid="mappedCompanyId"/> = #{params.eqCorpinfoId}
        </if>
        <if test="params.likeCorpinfoName != null and params.likeCorpinfoName != ''">
            AND (t.corpinfo_name LIKE CONCAT('%', #{params.likeCorpinfoName}, '%')
                OR t.org_name LIKE CONCAT('%', #{params.likeCorpinfoName}, '%')
                OR <include refid="mappedCompanyName"/> LIKE CONCAT('%', #{params.likeCorpinfoName}, '%'))
        </if>
        <if test="params.likeContactName != null and params.likeContactName != ''">
            AND (COALESCE(corp_uuid.contacts, corp_internal.contacts) LIKE CONCAT('%', #{params.likeContactName}, '%')
                OR COALESCE(corp_uuid.lr_name, corp_internal.lr_name) LIKE CONCAT('%', #{params.likeContactName}, '%'))
        </if>
        <if test="params.eqEnable != null">
            AND t.enable = #{params.eqEnable}
        </if>
        GROUP BY <include refid="mappedCompanyId"/>, <include refid="mappedCompanyName"/>
        ORDER BY MAX(t.last_sync_time) DESC, MAX(t.update_time) DESC
    </select>

    <sql id="appDetailSelect">
        SELECT t.id, t.app_account, t.terminal_no, t.terminal_name,
               <include refid="mappedCompanyId"/> AS corpinfo_id,
               <include refid="mappedCompanyName"/> AS corpinfo_name,
               t.org_code, t.org_name, t.enable, t.device_status,
               COALESCE(tb.id_card_no, t.bind_id_card_no) AS active_id_card_no,
               COALESCE(tb.staff_no_snapshot, u.username) AS staff_no,
               COALESCE(u.name, tb.staff_name_snapshot) AS staff_name,
               u.phone AS staff_phone, tb.bind_status, t.finds_terminal_id,
               t.last_location_time, t.last_location_name, t.last_sync_time,
               t.sync_status, t.remarks
    </sql>

    <sql id="appDetailJoinAndWhere">
        FROM terminal t
        LEFT JOIN terminal_bind tb ON tb.id = (
            SELECT tb2.id FROM terminal_bind tb2
            WHERE tb2.terminal_no = t.terminal_no
              AND (tb2.delete_enum IS NULL OR tb2.delete_enum = 'FALSE')
              AND tb2.bind_status = 'BOUND'
            ORDER BY tb2.bind_time DESC, tb2.id DESC LIMIT 1
        )
        LEFT JOIN user_scope_v u
          ON u.user_id_card = COALESCE(tb.id_card_no, t.bind_id_card_no)
         AND (u.delete_enum IS NULL OR u.delete_enum = 'FALSE')
        <include refid="mappedCompanyJoins"/>
        WHERE (t.delete_enum IS NULL OR t.delete_enum = 'FALSE') AND t.device_type = 'APP'
          AND <include refid="mappedCompanyId"/> IS NOT NULL
        <if test="params.id != null">AND t.id = #{params.id}</if>
        <if test="params.appAccount != null and params.appAccount != ''">
            AND (t.app_account LIKE CONCAT('%', #{params.appAccount}, '%')
                OR t.terminal_no LIKE CONCAT('%', #{params.appAccount}, '%'))
        </if>
        <if test="params.terminalNo != null and params.terminalNo != ''">
            AND t.terminal_no LIKE CONCAT('%', #{params.terminalNo}, '%')
        </if>
        <if test="params.staffName != null and params.staffName != ''">
            AND (u.name LIKE CONCAT('%', #{params.staffName}, '%')
                OR tb.staff_name_snapshot LIKE CONCAT('%', #{params.staffName}, '%'))
        </if>
        <if test="params.staffNo != null and params.staffNo != ''">
            AND (u.username = #{params.staffNo} OR tb.staff_no_snapshot = #{params.staffNo})
        </if>
        <if test="params.idCardNo != null and params.idCardNo != ''">
            AND COALESCE(tb.id_card_no, t.bind_id_card_no) = #{params.idCardNo}
        </if>
        <choose>
            <when test="params.eqCorpinfoId != null and params.eqCorpinfoId != '' and params.eqCorpinfoName != null and params.eqCorpinfoName != ''">
                AND <include refid="mappedCompanyId"/> = #{params.eqCorpinfoId}
            </when>
            <when test="params.eqCorpinfoId != null and params.eqCorpinfoId != ''">
                AND <include refid="mappedCompanyId"/> = #{params.eqCorpinfoId}
            </when>
            <when test="params.eqCorpinfoName != null and params.eqCorpinfoName != ''">
                AND <include refid="mappedCompanyName"/> = #{params.eqCorpinfoName}
            </when>
        </choose>
        <if test="params.likeCorpinfoName != null and params.likeCorpinfoName != ''">
            AND (t.corpinfo_name LIKE CONCAT('%', #{params.likeCorpinfoName}, '%')
                OR t.org_name LIKE CONCAT('%', #{params.likeCorpinfoName}, '%')
                OR <include refid="mappedCompanyName"/> LIKE CONCAT('%', #{params.likeCorpinfoName}, '%'))
        </if>
        <if test="params.orgCode != null and params.orgCode != ''">AND t.org_code = #{params.orgCode}</if>
        <if test="params.orgName != null and params.orgName != ''">
            AND t.org_name LIKE CONCAT('%', #{params.orgName}, '%')
        </if>
        <if test="params.enable != null">AND t.enable = #{params.enable}</if>
        <if test="params.deviceStatus != null and params.deviceStatus != ''">
            AND t.device_status = #{params.deviceStatus}
        </if>
    </sql>

    <select id="listApps"
            resultType="com.zcloud.personnel.positioning.persistence.dataobject.TerminalAppDetailDO">
        <include refid="appDetailSelect"/>
        <include refid="appDetailJoinAndWhere"/>
        ORDER BY t.update_time DESC, t.id DESC
    </select>

    <select id="getAppDetail"
            resultType="com.zcloud.personnel.positioning.persistence.dataobject.TerminalAppDetailDO">
        <include refid="appDetailSelect"/>
        <include refid="appDetailJoinAndWhere"/>
        LIMIT 1
    </select>

    <select id="findPerson"
            resultType="com.zcloud.personnel.positioning.persistence.dataobject.TerminalPersonSnapshotDO">
        SELECT u.username AS staff_no, u.name AS staff_name, u.user_id_card AS id_card_no,
               u.phone AS mobile_no, CAST(ci.corpinfo_id AS CHAR) AS corpinfo_id,
               ci.corp_name AS corpinfo_name
        FROM user_scope_v u
        LEFT JOIN corp_info ci ON ci.id = u.corpinfo_id
        WHERE (u.delete_enum IS NULL OR u.delete_enum = 'FALSE')
        <choose>
            <when test="params.idCardNo != null and params.idCardNo != ''">
                AND u.user_id_card = #{params.idCardNo}
            </when>
            <when test="params.staffNo != null and params.staffNo != ''">
                AND u.username = #{params.staffNo}
            </when>
            <otherwise>
                AND u.name = #{params.staffName}
            </otherwise>
        </choose>
        LIMIT 1
    </select>

    <select id="findCorpInfo"
            resultType="com.zcloud.personnel.positioning.persistence.dataobject.CorpInfoSnapshotDO">
        SELECT CAST(corpinfo_id AS CHAR) AS corpinfo_id, corp_name,
               code AS credit_code, COALESCE(NULLIF(contacts, ''), lr_name) AS contact_name
        FROM corp_info
        WHERE (delete_enum IS NULL OR delete_enum = 'FALSE')
        <choose>
            <when test="params.corpinfoId != null and params.corpinfoId != ''">
                AND corpinfo_id = #{params.corpinfoId}
            </when>
            <when test="params.orgCode != null and params.orgCode != ''">
                AND code = #{params.orgCode}
            </when>
            <otherwise>
                AND corp_name = #{params.corpinfoName}
            </otherwise>
        </choose>
        LIMIT 1
    </select>

    <update id="updateBindIdCardNo">
        UPDATE terminal SET bind_id_card_no = #{params.idCardNo} WHERE id = #{params.id}
    </update>
</mapper>
