Kaikai Chi

166 papers B 8C 6Journal 132Unranked 20
YearRankTypeTitle / Venue / Authors
2026 J jnl
IEEE Trans. Mob. Comput.
Bincheng Zhu, Shaojun Zhu, Kaikai Chi, Shahid Mumtaz, Wael Bazzi
2026 J jnl
IEEE Internet Things J.
Juncui Niu, Hongliang Zhou, Yingying An, Shubin Zhang, Kaikai Chi
2026 J jnl
IEEE Trans. Wirel. Commun.
Peipei Chen, Lailong Luo, Deke Guo, Jiaju Wu, Kaikai Chi, Chenggang Yan, Xudong Dong
2026 J jnl
IEEE Internet Things J.
Xiaoying Liu, Hongyu Wang, Kechen Zheng, Kaikai Chi
2026 J jnl
IEEE Trans. Wirel. Commun.
Ming Xia, Ziyang Lin, Jiaquan Jin, Yu Hen Hu, Zhen Cheng, Kaikai Chi
2025 J jnl
IEEE Trans. Veh. Technol.
Senlei Bao, Shubin Zhang, Kaikai Chi, Keping Yu, Shahid Mumtaz
2025 conf
ICIC (2)
Changquan He, Weihao Lin, Kaikai Chi, Keji Mao
2025 J jnl
IEEE Trans. Mob. Comput.
Liang Huang, Bincheng Zhu, Runkai Nan, Kaikai Chi, Yuan Wu
2025 J jnl
IEEE Trans. Mob. Comput.
Xiaoying Liu, Anping Chen, Kechen Zheng, Kaikai Chi, Bin Yang, Tarik Taleb
2025 J jnl
Ad Hoc Networks
Ke Wang, Kaikai Chi, Anwer Al-Dulaimi
2025 J jnl
IEEE Trans. Mob. Comput.
Liang Huang, Yuqi Li, Hongyuan Liang, Kaikai Chi, Yuan Wu
2025 J jnl
IEEE Trans. Wirel. Commun.
Bincheng Zhu, Liang Huang, Kaikai Chi, Abdullah Alharbi, Keping Yu, Mohsen Guizani
2025 J jnl
IEEE Trans. Mob. Comput.
Yuzhe Chen, Yanjun Li, Chung Shue Chen, Kaikai Chi
2025 J jnl
ACM Trans. Sens. Networks
Yufan Zhang, Hangliang Li, Yanjun Li, Zhi Ye, Yuzhe Chen, Zhe Yang, Kaikai Chi
2025 J jnl
IEEE Trans. Commun.
Shaojun Zhu, Bincheng Zhu, Kaikai Chi, Keping Yu, Shahid Mumtaz
2025 conf
ICC
Bincheng Zhu, Liang Huang, Kaikai Chi, Keping Yu, Shahid Mumtaz
2025 B conf
ICECCS
Tixin Chen, Guanqun Shen, Xinnan Zhu, Shaojun Zhu, Bincheng Zhu, Kaikai Chi
2025 J jnl
ACM Trans. Multim. Comput. Commun. Appl.
Shaojun Zhu, Bincheng Zhu, Kaikai Chi, Jiefan Qiu, Hailong Shi, Xingyu Gao
2025 J jnl
IEEE Trans. Intell. Transp. Syst.
Shubin Zhang, Xun Tong, Kaikai Chi, Wei Gao, Xiaolong Chen, Zhiguo Shi
2025 J jnl
Comput. Networks
Guanqun Shen, Xinchen Wei, Kaikai Chi, Fayez Alqahtani, Amr Tolba
2025 J jnl
IEICE Trans. Fundam. Electron. Commun. Comput. Sci.
Guanqun Shen, Kaikai Chi, Osama Alfarraj, Amr Tolba
2025 J jnl
IEEE Trans. Mob. Comput.
Ming Xia, Min Huang, Qiuqi Pan, Yunhan Wang, Xiaoyan Wang, Kaikai Chi
2025 C conf
CSCWD
Dongfu Zhu, Jiefan Qiu, Mengqi Jiang, Zhichao Shao, Xiaofu Chen, Kaikai Chi
2024 J jnl
IEEE Commun. Lett.
Zhen Cheng, Zhichao Zhang, Xuancheng Jin, Weihua Gong, Kaikai Chi
2024 J jnl
CoRR
Liang Huang, Bincheng Zhu, Runkai Nan, Kaikai Chi, Yuan Wu
2024 J jnl
IEEE Trans. Commun.
Wenchao Chen, Xinchen Wei, Kaikai Chi, Keping Yu, Amr Tolba, Shahid Mumtaz, Mohsen Guizani
2024 J jnl
IEEE Trans. Commun.
Shubin Zhang, Senlei Bao, Kaikai Chi, Keping Yu, Shahid Mumtaz
2024 J jnl
IEEE Trans. Mob. Comput.
Yufan Zhang, Yan-Jun Li, Bo Chen, Ertao Li, Kechen Zheng, Kaikai Chi, Yihua Zhu
2024 J jnl
CoRR
Xiaoying Liu, Anping Chen, Kechen Zheng, Kaikai Chi, Bin Yang, Tarik Taleb
2024 J jnl
IEEE Internet Things J.
Kechen Zheng, Qipeng Ye, Kaikai Chi, Xiaoying Liu, Aldosary Saad, Keping Yu, Shahid Mumtaz, Mohsen Guizani
2024 J jnl
Comput. Networks
Yue Li, Yanjun Li, Yuzhe Chen, Jiahui Tong, Xianzhong Tian, Kaikai Chi
2024 J jnl
IEEE Internet Things J.
Zhen Cheng, Jie Sun, Zhichao Zhang, Ming Xia, Kaikai Chi
2024 J jnl
IEEE Trans. Mol. Biol. Multi Scale Commun.
Zhen Cheng, Jun Yan, Jie Sun, Shubin Zhang, Kaikai Chi
2024 J jnl
IEEE Commun. Lett.
Xuancheng Jin, Zhen Cheng, Miaodi Chen, Heng Liu, Weihua Gong, Kaikai Chi
2023 conf
PRCV (4)
Hua Gao, Li Chen, Yi Zhou, Kaikai Chi, Sixian Chan
2023 J jnl
IEEE Trans. Commun.
Kechen Zheng, Xueli Jia, Kaikai Chi, Xiaoying Liu
2023 J jnl
IET Commun.
Guanqun Shen, Wenchao Chen, Bincheng Zhu, Kaikai Chi, Xiaolong Chen
2023 J jnl
IEEE Trans. Commun.
Kechen Zheng, Guodong Jiang, Xiaoying Liu, Kaikai Chi, Xinwei Yao, Jiajia Liu
2023 conf
ICA3PP (5)
Mingjie Zhu, Shubin Zhang, Kaikai Chi
2023 J jnl
Inf.
Feiyang Ye, Liang Huang, Senjie Liang, Kaikai Chi
2023 conf
PRCV (4)
Hua Gao, Yi Zhou, Li Chen, Kaikai Chi
2023 C conf
ICCC
Hongyuan Liang, Yuqi Li, Senyang Zhu, Liang Huang, Kaikai Chi
2023 J jnl
IEEE J. Sel. Areas Commun.
Kai Fang, Jiefan Qiu, Tingting Wang, Kailu Zheng, Liyao Xing, Keji Mao, Kaikai Chi
2023 J jnl
IEEE Trans. Veh. Technol.
Xiaoying Liu, Bin Xu, Xiong Wang, Kechen Zheng, Kaikai Chi, Xianzhong Tian
2023 conf
MSN
Senlei Bao, Shubin Zhang, Kaikai Chi, Xiaolong Chen, Wei Gao
2023 J jnl
IEICE Trans. Fundam. Electron. Commun. Comput. Sci.
Xi Chen, Guodong Jiang, Kaikai Chi, Shubin Zhang, Gang Chen, Jiang Liu
2023 J jnl
IET Commun.
Xi Chen, Guodong Jiang, Kaikai Chi, Shubin Zhang, Xinchen Wei, Gang Chen
2023 J jnl
ACM Trans. Sens. Networks
Ming Xia, Jiaquan Jin, Biqian Liu, Yu Hen Hu, Xiaoyan Wang, Kaikai Chi
2023 J jnl
IEEE Internet Things J.
Jiefan Qiu, Pan Zheng, Kaikai Chi, Ruiji Xu, Jiajia Liu
2023 J jnl
IET Commun.
Haijiang Ge, Kechen Zheng, Kaikai Chi, Xiaoying Liu
2023 J jnl
Telecommun. Syst.
Yuzhe Chen, Yanjun Li, Meihui Gao, Xianzhong Tian, Kaikai Chi
2023 J jnl
IEEE Trans. Intell. Transp. Syst.
Ming Xia, Junjie Lin, Linghao Ying, Jian Sun, Kaikai Chi, Kun Gao, Keping Yu
2022 J jnl
Symmetry
Keji Mao, Jinyu Xu, Xingda Yao, Jiefan Qiu, Kaikai Chi, Guanglin Dai
2022 C conf
HPSR
Weiwei Jin, Liang Huang, Kaikai Chi
2022 J jnl
Sensors
Xueli Jia, Kechen Zheng, Kaikai Chi, Xiaoying Liu
2022 J jnl
IET Commun.
Wenchao Chen, Bincheng Zhu, Kaikai Chi, Shubin Zhang
2022 J jnl
Comput. Networks
Wenchao Chen, Guanqun Shen, Kaikai Chi, Shubin Zhang, Xiaolong Chen
2022 J jnl
IEEE Trans. Wirel. Commun.
Shubin Zhang, Hui Gu, Kaikai Chi, Liang Huang, Keping Yu, Shahid Mumtaz
2022 J jnl
Comput. Networks
Juncui Niu, Shubin Zhang, Kaikai Chi, Guanqun Shen, Wei Gao
2022 J jnl
Comput. Commun.
Weiwei Jin, Juan Sun, Kaikai Chi, Shubin Zhang
2022 J jnl
IEEE Trans. Commun.
Bincheng Zhu, Kaikai Chi, Jiajia Liu, Keping Yu, Shahid Mumtaz
2022 J jnl
IEEE Internet Things J.
Shubin Zhang, Shuaiying Kong, Kaikai Chi, Liang Huang
2022 J jnl
Comput. Networks
Kechen Zheng, Haijiang Ge, Kaikai Chi, Xiaoying Liu
2022 conf
SmartWorld/UIC/ScalCom/DigitalTwin/PriComp/Meta
Ruiji Xu, Jiefan Qiu, Zehui Feng, Keji Mao, Liyao Xing, Kaikai Chi
2022 J jnl
IEEE Trans. Mol. Biol. Multi Scale Commun.
Zhen Cheng, Yuchun Tu, Kaikai Chi, Ming Xia
2022 conf
WOCC
Senlei Bao, Shubin Zhang, Kaikai Chi
2022 C conf
HPSR
Xun Tong, Shuaiying Kong, Guanqun Shen, Shubin Zhang, Kaikai Chi
2022 J jnl
IEEE Trans. Veh. Technol.
Liang Huang, Runkai Nan, Kaikai Chi, Qiaozhi Hua, Keping Yu, Neeraj Kumar, Mohsen Guizani
2021 J jnl
IEEE Trans. Veh. Technol.
Huimei Han, Lushun Fang, Weidang Lu, Kaikai Chi, Wenchao Zhai, Jun Zhao
2021 J jnl
Multim. Tools Appl.
Ruohong Huan, Ziwei Zhan, Luoqi Ge, Kaikai Chi, Peng Chen, Ronghua Liang
2021 J jnl
IEEE Trans. Wirel. Commun.
Baowen Liang, Xuxun Liu, Huan Zhou, Victor C. M. Leung, Anfeng Liu, Kaikai Chi
2021 B conf
WCNC
Ming Xia, Yunhan Wang, Xiaoyan Wang, Zhen Cheng, Kaikai Chi
2021 J jnl
IET Commun.
Juan Sun, Shubin Zhang, Kaikai Chi
2021 J jnl
IEEE Internet Things J.
Yihua Zhu, Siliang Gong, Kaikai Chi, Yanjun Li, Yuguang Fang
2021 J jnl
IEEE Trans. Syst. Man Cybern. Syst.
Xuxun Liu, Tian Wang, Weijia Jia, Anfeng Liu, Kaikai Chi
2021 J jnl
Comput. Commun.
Juan Sun, Shubin Zhang, Kaikai Chi
2021 J jnl
Sensors
Juan Sun, Shubin Zhang, Kaikai Chi
2021 J jnl
IEEE Trans. Veh. Technol.
Kechen Zheng, Xiaoying Liu, Biao Wang, Haifeng Zheng, Kaikai Chi, Yuan Yao
2021 J jnl
Multim. Tools Appl.
Ruohong Huan, Jia Shu, Shenglin Bao, Ronghua Liang, Peng Chen, Kaikai Chi
2020 J jnl
IEEE Trans. Veh. Technol.
Zhebiao Chen, Kaikai Chi, Kechen Zheng, Yanjun Li, Xuxun Liu
2020 J jnl
IEEE Trans. Wirel. Commun.
Xiaoying Liu, Kechen Zheng, Kaikai Chi, Yi-hua Zhu
2020 J jnl
IEEE Trans. Mob. Comput.
Xinggang Fan, Fengdan Hu, Tao Liu, Kaikai Chi, Jinshan Xu
2020 J jnl
Nano Commun. Networks
Zhen Cheng, Yuchun Tu, Ming Xia, Kaikai Chi
2020 J jnl
IET Commun.
Haijiang Ge, Zhanwei Yu, Kaikai Chi, Keji Mao, Qike Shao, Lijian Chen
2020 J jnl
IEEE Syst. J.
Xinggang Fan, Senyi Wang, Youhao Wang, Jinshan Xu, Kaikai Chi
2020 J jnl
IET Commun.
Shuwei Qiu, Yi-hua Zhu, Xianzhong Tian, Kaikai Chi
2020 J jnl
IEEE Trans. Veh. Technol.
Kechen Zheng, Xiaoying Liu, Yihua Zhu, Kaikai Chi, Yanjun Li
2020 J jnl
IEEE Internet Things J.
Zhebiao Chen, Kaikai Chi, Kechen Zheng, Guanglin Dai, Qike Shao
2020 J jnl
IEEE Trans. Wirel. Commun.
Ming Xia, Biqian Liu, Yu Hen Hu, Kaikai Chi, Xiaoyan Wang, Jiajia Liu
2020 J jnl
IET Image Process.
Ruohong Huan, Luoqi Ge, Peng Yang, Chaojie Xie, Kaikai Chi, Keji Mao, Yun Pan
2020 J jnl
Nano Commun. Networks
Zhen Cheng, Yuchun Tu, Ming Xia, Kaikai Chi
2020 J jnl
IEEE Trans. Wirel. Commun.
Kechen Zheng, Xiaoying Liu, Yihua Zhu, Kaikai Chi, Kangqi Liu
2019 J jnl
IEEE Trans. Commun.
Kaikai Chi, Zhebiao Chen, Kechen Zheng, Yi-hua Zhu, Jiajia Liu
2019 J jnl
IEEE Trans. Veh. Technol.
Zhanwei Yu, Kaikai Chi, Ping Hu, Yi-hua Zhu, Xuxun Liu
2019 J jnl
Sensors
Wenwei Lu, Yi-hua Zhu, Kaikai Chi
2019 J jnl
Nano Commun. Networks
Zhen Cheng, Yiming Zhang, Huiting Zhao, Fei Lin, Kaikai Chi
2019 J jnl
IEEE Wirel. Commun. Lett.
Yufan Zhang, Ertao Li, Yi-hua Zhu, Kaikai Chi, Xianzhong Tian
2019 J jnl
Comput. Networks
Ming Xia, Kaikai Chi, Xiaoyan Wang, Zhen Cheng
2019 B conf
GLOBECOM
Yinan Zhu, Xianzhong Tian, Kaikai Chi, Chenyiming Wen, Yi-hua Zhu
2019 J jnl
IET Commun.
Zhanwei Yu, Kaikai Chi, Kechen Zheng, Yanjun Li, Zhen Cheng
2019 J jnl
Peer-to-Peer Netw. Appl.
Yanjun Li, Chung Shue Chen, Kaikai Chi, Jianhui Zhang
2019 B conf
ICPADS
Yinan Zhu, Kaikai Chi, Xianzhong Tian
2019 J jnl
计算机科学
Kaikai Chi, Ronghui Cai, Weilong Ding, Ruohong Huan, Keji Mao
2019 J jnl
计算机科学
Kaikai Chi, Xingyuan Xu, Ping Hu
2019 J jnl
计算机科学
Kaikai Chi, Zefeng Tang, Yinan Zhu, Qike Shao
2018 J jnl
IET Commun.
Yi-hua Zhu, Ertao Li, Kaikai Chi, Xianzhong Tian
2018 J jnl
Comput. Commun.
Kaikai Chi, Yi-hua Zhu, Yanjun Li
2018 J jnl
IEEE Trans. Veh. Technol.
Yi-hua Zhu, Ertao Li, Kaikai Chi
2018 J jnl
IEEE Access
Kaikai Chi, Zhanwei Yu, Yanjun Li, Yi-hua Zhu
2018 J jnl
IEEE Internet Things J.
Yanjun Li, Kaikai Chi, Honglong Chen, Zhibo Wang, Yihua Zhu
2018 J jnl
Int. J. Commun. Syst.
Kaikai Chi, Xinchen Wei, Yanjun Li, Xianzhong Tian
2018 J jnl
IEEE Trans. Veh. Technol.
Yinan Zhu, Kaikai Chi, Ping Hu, Keji Mao, Qike Shao
2018 J jnl
计算机科学
Kaikai Chi, Xinchen Xu, Xinchen Wei
2018 J jnl
计算机科学
Kaikai Chi, Yimin Lin, Yanjun Li, Zhen Cheng
2018 J jnl
计算机科学
Kaikai Chi, Xinchen Wei, Yimin Lin
2017 J jnl
Nano Commun. Networks
Zhen Cheng, Yi-hua Zhu, Kaikai Chi, Yanjun Li, Ming Xia
2017 J jnl
IEEE Netw.
Kaikai Chi, Liang Huang, Yanjun Li, Yi-hua Zhu, Xianzhong Tian, Ming Xia
2017 J jnl
Peer-to-Peer Netw. Appl.
Yanjun Li, Lingkun Fu, You Ying, Yong Sun, Kaikai Chi, Yi-hua Zhu
2017 J jnl
IEEE Trans. Mob. Comput.
Yi-hua Zhu, Shuwei Qiu, Kaikai Chi, Yuguang Michael Fang
2017 J jnl
IEEE Internet Things J.
Kaikai Chi, Yi-hua Zhu, Yanjun Li, Liang Huang, Ming Xia
2017 J jnl
IEEE Syst. J.
Xianzhong Tian, Yi-hua Zhu, Kaikai Chi, Jiajia Liu, Daqiang Zhang
2017 J jnl
计算机科学
Kaikai Chi, Liushuan Zhu, Zhen Cheng, Xianzhong Tian
2017 J jnl
计算机科学
Kaikai Chi, Yimin Lin, Yanjun Li, Zhen Cheng
2016 J jnl
Mob. Networks Appl.
Kaikai Chi, Yi-hua Zhu, Yongchao Wu, Victor C. M. Leung
2016 J jnl
IEEE Internet Things J.
Kaikai Chi, Yi-hua Zhu, Yanjun Li, Daqiang Zhang, Victor C. M. Leung
2016 conf
NaNA
Shenji Luan, Yi-hua Zhu, Kaikai Chi
2016 conf
NaNA
Yi-hua Zhu, Hangyu Lv, Yanyan Li, Ertao Li, Kaikai Chi
2016 conf
MSN
Lijing Li, Yi-hua Zhu, Xianzhong Tian, Kaikai Chi, Lin Xu
2016 J jnl
计算机科学
Cong Sun, Yihua Zhu, Kaikai Chi, Liyong Yuan
2016 J jnl
IEEE Trans. Veh. Technol.
Yi-hua Zhu, Kaikai Chi, Xianzhong Tian, Victor C. M. Leung
2016 J jnl
Nano Commun. Networks
Zhen Cheng, Yi-hua Zhu, Kaikai Chi, Yanjun Li
2015 conf
NTMS
Cong Sun, Yi-hua Zhu, Liyong Yuan, Kaikai Chi
2015 J jnl
IEEE Trans. Veh. Technol.
Yi-hua Zhu, Shenji Luan, Victor C. M. Leung, Kaikai Chi
2015 J jnl
Int. J. Commun. Syst.
Jing Wang, Kaikai Chi, Yang Yang, Xinmei Wang
2015 J jnl
CoRR
Yanjun Li, Lingkun Fu, Min Chen, Kaikai Chi, Yi-hua Zhu
2015 J jnl
IEEE Commun. Lett.
Yanjun Li, Lingkun Fu, Min Chen, Kaikai Chi, Yi-hua Zhu
2015 J jnl
计算机科学
Kaikai Chi, Yimin Lin, Yanjun Li
2015 J jnl
计算机科学
Kaikai Chi, Zhiquan Dai, Yanjun Li, Zhen Cheng
2015 J jnl
计算机科学
Kaikai Chi, Wenjie Du, Yanjun Li, Zhen Cheng
2014 C conf
QSHINE
Kaikai Chi, Yongchao Wu, Yi-hua Zhu, Victor C. M. Leung
2014 conf
CWSN
Yi-hua Zhu, Yanyan Wang, Kaikai Chi, Lin Xu
2014 J jnl
IEEE Trans. Wirel. Commun.
Kaikai Chi, Yi-hua Zhu, Xiaohong Jiang, Victor C. M. Leung
2014 conf
CWSN
Yanjun Li, Kaifeng Xu, Jianji Shao, Kaikai Chi
2014 B conf
WCNC
Kaikai Chi, Zhijian Tian, Yi-hua Zhu
2014 J jnl
Comput. Networks
Kaikai Chi, Yi-hua Zhu, Xiaohong Jiang, Xianzhong Tian
2013 J jnl
Comput. Networks
Kaikai Chi, Xiaohong Jiang, Yi-hua Zhu, Jing Wang, Yanjun Li
2013 B conf
WCNC
Kaikai Chi, Yi-hua Zhu, Xiaohong Jiang, Xianzhong Tian
2013 J jnl
Nano Commun. Networks
Kaikai Chi, Yi-hua Zhu, Xiaohong Jiang, Xianzhong Tian
2012 J jnl
KSII Trans. Internet Inf. Syst.
Yanjun Li, Yueyun Shen, Kaikai Chi
2012 J jnl
J. Netw. Comput. Appl.
Yi-hua Zhu, Hui Xu, Kaikai Chi, Hua Hu
2012 J jnl
IEICE Trans. Commun.
Kaikai Chi, Xiaohong Jiang, Yi-hua Zhu, Yanjun Li
2012 conf
MSN
Kaikai Chi, Yi-hua Zhu, Zhen Cheng
2012 conf
CCIS
Jing Peng, Kaikai Chi, Yi-hua Zhu, Jing Wang
2012 conf
CCIS
Zhen Cheng, Kaikai Chi, Xianzhong Tian, Yanjun Li
2012 conf
CWSN
Yihua Zhu, Gan Chen, Kaikai Chi, Yanjun Li
2011 J jnl
Comput. Networks
Kaikai Chi, Xiaohong Jiang, Baoliu Ye, Yanjun Li
2010 J jnl
IEICE Trans. Commun.
Kaikai Chi, Xiaohong Jiang, Baoliu Ye, Susumu Horiguchi
2010 J jnl
IEEE Trans. Veh. Technol.
Kaikai Chi, Xiaohong Jiang, Susumu Horiguchi
2010 J jnl
Comput. Networks
Kaikai Chi, Xiaohong Jiang, Susumu Horiguchi
2009 J jnl
IEICE Trans. Commun.
Kaikai Chi, Xiaohong Jiang, Susumu Horiguchi
2009 conf
Internetware
Kaikai Chi, Xiaohong Jiang, Baoliu Ye
2008 B conf
WCNC
Kaikai Chi, Xiaohong Jiang, Susumu Horiguchi
2008 J jnl
IEEE Trans. Parallel Distributed Syst.
Kaikai Chi, Xiaohong Jiang, Susumu Horiguchi, Minyi Guo
2007 B conf
GLOBECOM
Kaikai Chi, Xiaohong Jiang, Susumu Horiguchi
2007 conf
ICC
Kaikai Chi, Xiaohong Jiang, Susumu Horiguchi
2006 C conf
BROADNETS
Kaikai Chi, Xiaohong Jiang, Susumu Horiguchi
redb/queries.py
← Index redb/queries.py python
"""
Database query functions for REDB.

Contains all functions that query ClickHouse for sample metadata,
deduplication checks, and catalog lookups.
"""
import os
import ast
import clickhouse_connect
from typing import List, Optional, Dict

from redb import settings
from redb.s3_utils import generate_s3_key_from_hash


def get_supported_formats(magika_filter: Optional[str] = None) -> List[str]:
    """
    Get supported file formats from SUPPORTED_FORMATS env variable or magika_filter override.
    Expected format: SUPPORTED_FORMATS=['pebin', 'elf']

    Args:
        magika_filter: Optional single format to filter by (overrides env var)

    Returns:
        List of supported format strings, defaults to ['pebin'] if not set
    """
    # If magika_filter is provided, use it as the only format
    if magika_filter:
        return [magika_filter]

    formats_str = os.getenv('SUPPORTED_FORMATS', "['pebin']")
    try:
        formats = ast.literal_eval(formats_str)
        if isinstance(formats, list) and all(isinstance(f, str) for f in formats):
            return formats
        else:
            print(f"[WARNING] SUPPORTED_FORMATS must be a list of strings, got: {formats_str}")
            return ['pebin']
    except (ValueError, SyntaxError) as e:
        print(f"[WARNING] Failed to parse SUPPORTED_FORMATS '{formats_str}': {e}")
        return ['pebin']


def get_db_catalog_connection():
    """Create and return a ClickHouse client for catalog queries"""
    return clickhouse_connect.get_client(
        host=os.getenv("DB_HOST"),
        port=int(os.getenv("DB_PORT", "8123")),
        verify=os.getenv("DB_ENFORCE_SSL", "False").lower() == "true",
        username=os.getenv("DB_USER"),
        password=os.getenv("DB_PASSWORD"),
        database=os.getenv("DB_NAME")
    )


def fetch_s3_objects_by_repository(repository: Optional[str], index_prefix: str, decompile: bool, notes: Optional[str] = None, magika_filter: Optional[str] = None, yara_scan: bool = False, force: bool = False) -> List[Dict]:
    """
    Query the ClickHouse repository_upload_sessions table to get samples.
    S3 bucket comes from env var, S3 key is derived from sha256.

    Args:
        repository: Repository name (e.g., "bazaar", "malshare"). If None or "all-repos", queries all repositories.
        index_prefix: Table prefix for checking existing samples
        decompile: Whether we're in decompile mode (affects which table to check for existing)
        notes: Optional filter for notes field
        magika_filter: Optional single filetype to filter by (overrides SUPPORTED_FORMATS)
        yara_scan: Whether we're in YARA-only mode (skips "already processed" check)

    Returns:
        List of dicts with sha256, s3_bucket, s3_key for each sample
    """
    try:
        client = get_db_catalog_connection()
        s3_bucket = os.getenv('S3_BUCKET')

        if not s3_bucket:
            print("[ERROR] S3_BUCKET environment variable is required")
            return []

        # Get supported formats from env or magika_filter override
        supported_formats = get_supported_formats(magika_filter)
        print(f"[INFO] Querying for supported formats: {supported_formats}")

        # Build query - repository filter is optional
        # Join with catalog_samples to get first_seen date
        if repository and repository != "all-repos":
            query = """
                SELECT DISTINCT rus.sha256, rus.filetype_magika, cs.first_seen
                FROM repository_upload_sessions rus
                LEFT JOIN catalog_samples cs ON rus.sha256 = cs.sha256
                WHERE rus.repository = %(repo)s
                  AND rus.filetype_magika IN %(formats)s
            """
            params = {"repo": repository, "formats": supported_formats}
        else:
            # Query all repositories
            query = """
                SELECT DISTINCT rus.sha256, rus.filetype_magika, cs.first_seen
                FROM repository_upload_sessions rus
                LEFT JOIN catalog_samples cs ON rus.sha256 = cs.sha256
                WHERE rus.filetype_magika IN %(formats)s
            """
            params = {"formats": supported_formats}

        if notes:
            query += " AND rus.notes LIKE %(notes)s"
            params["notes"] = f"%{notes}%"

        # Execute query and convert to list of dictionaries
        result = client.query(query, parameters=params)

        # Build rows with s3_bucket and s3_key derived from sha256
        rows = []
        for row in result.result_rows:
            sha256 = row[0]
            # Handle binary string if needed
            if isinstance(sha256, bytes):
                sha256 = sha256.decode('utf-8')

            rows.append({
                'sha256': sha256,
                's3_bucket': s3_bucket,
                's3_key': generate_s3_key_from_hash(sha256),
                'filetype_magika': row[1],
                'first_seen': row[2]  # From catalog_samples (None if not found)
            })

        print(f"[DEBUG] Found {len(rows)} objects in repository_upload_sessions for repository {repository}")

        # Extract SHA256 hashes from the results for bulk checking
        sha256_list = [row.get('sha256') for row in rows if row.get('sha256')]

        if sha256_list and not force:
            # Check which hashes are already in the database
            existing_hashes = is_in_db_bulk(sha256_list, index_prefix, decompile, yara_scan, magika_filter)
            print(f"[INFO] Found {len(existing_hashes)} objects already in database")

            # Filter out rows with existing hashes
            rows = [row for row in rows if row.get('sha256') not in existing_hashes]
            print(f"[INFO] After filtering, {len(rows)} objects remain to be processed")
        elif force:
            print(f"[INFO] Force mode: skipping deduplication check, processing all {len(sha256_list)} objects")

        # Randomize the order of rows before returning
        import random
        random.shuffle(rows)

        return rows
    except Exception as e:
        print(f"[ERROR] Failed to query repository_upload_sessions: {e}")
        return []
    finally:
        if 'client' in locals():
            client.close()


def fetch_s3_objects_by_date_range(
    index_prefix: str,
    decompile: bool,
    start_date: str,
    end_date: str,
    repository: Optional[str] = None,
    notes: Optional[str] = None,
    magika_filter: Optional[str] = None,
    yara_scan: bool = False,
    force: bool = False,
    analyzed: bool = False
) -> List[Dict]:
    """
    Query samples from catalog_samples by first_seen date range, filtered to only include
    samples that exist in repository_upload_sessions (bulk/repo uploads only).

    Args:
        index_prefix: Table prefix for checking existing samples
        decompile: Whether we're in decompile mode
        start_date: Start date (inclusive) in YYYY-MM-DD format
        end_date: End date (exclusive) in YYYY-MM-DD format
        repository: Optional repository filter
        notes: Optional notes filter
        magika_filter: Optional single filetype to filter by (overrides SUPPORTED_FORMATS)
        yara_scan: Whether we're in YARA-only mode (skips "already processed" check)
        analyzed: Filter to only samples already in basic_properties (cross-database join)

    Returns:
        List of dicts with sha256, s3_bucket, s3_key for each sample
    """
    try:
        client = get_db_catalog_connection()
        s3_bucket = os.getenv('S3_BUCKET')

        if not s3_bucket:
            print("[ERROR] S3_BUCKET environment variable is required")
            return []

        # Get supported formats from env or magika_filter override
        supported_formats = get_supported_formats(magika_filter)
        print(f"[INFO] Querying for supported formats: {supported_formats}")

        # Join catalog_samples with repository_upload_sessions to:
        # 1. Filter by first_seen date from catalog_samples
        # 2. Only include samples that exist in repository_upload_sessions (not user uploads)
        # 3. Optionally filter to only already-analyzed samples (in basic_properties)
        analyzed_join = ""
        if analyzed:
            basic_table = f"{index_prefix}_basic_properties"
            analyzed_join = f"INNER JOIN {basic_table} bp ON cs.sha256 = bp.sha256"
            print(f"[INFO] Filtering to already-analyzed samples in {basic_table}")

        query = f"""
            SELECT DISTINCT cs.sha256, rus.filetype_magika, cs.first_seen
            FROM catalog_samples cs
            INNER JOIN repository_upload_sessions rus ON cs.sha256 = rus.sha256
            {analyzed_join}
            WHERE cs.first_seen >= %(start_date)s
              AND cs.first_seen < %(end_date)s
              AND rus.filetype_magika IN %(formats)s
        """
        params = {
            "start_date": start_date,
            "end_date": end_date,
            "formats": supported_formats
        }

        if repository:
            query += " AND rus.repository = %(repo)s"
            params["repo"] = repository

        if notes:
            query += " AND rus.notes LIKE %(notes)s"
            params["notes"] = f"%{notes}%"

        # Execute query
        result = client.query(query, parameters=params)

        # Build rows with s3_bucket and s3_key derived from sha256
        rows = []
        for row in result.result_rows:
            sha256 = row[0]
            # Handle binary string if needed
            if isinstance(sha256, bytes):
                sha256 = sha256.decode('utf-8')

            rows.append({
                'sha256': sha256,
                's3_bucket': s3_bucket,
                's3_key': generate_s3_key_from_hash(sha256),
                'filetype_magika': row[1],
                'first_seen': row[2]  # From catalog_samples
            })

        date_info = f"from {start_date} to {end_date}"
        repo_info = f" for repository {repository}" if repository else ""
        print(f"[DEBUG] Found {len(rows)} objects in catalog_samples {date_info}{repo_info}")

        # Extract SHA256 hashes from the results for bulk checking
        sha256_list = [row.get('sha256') for row in rows if row.get('sha256')]

        if sha256_list and not force:
            # Check which hashes are already in the database
            existing_hashes = is_in_db_bulk(sha256_list, index_prefix, decompile, yara_scan, magika_filter)
            print(f"[INFO] Found {len(existing_hashes)} objects already in database")

            # Filter out rows with existing hashes
            rows = [row for row in rows if row.get('sha256') not in existing_hashes]
            print(f"[INFO] After filtering, {len(rows)} objects remain to be processed")
        elif force:
            print(f"[INFO] Force mode: skipping deduplication check, processing all {len(sha256_list)} objects")

        # Randomize the order of rows before returning
        import random
        random.shuffle(rows)

        return rows
    except Exception as e:
        print(f"[ERROR] Failed to query catalog_samples by date range: {e}")
        return []
    finally:
        if 'client' in locals():
            client.close()


def fetch_analyzed_samples(
    index_prefix: str,
    decompile: bool,
    magika_filter: Optional[str] = None,
    yara_scan: bool = False,
    force: bool = False,
    rerun: bool = False
) -> List[Dict]:
    """
    Query samples from basic_properties that have already been analyzed.
    Useful for reprocessing with decompilation or specific modules.

    Args:
        index_prefix: Table prefix for ClickHouse
        decompile: Whether we're in decompile mode (affects filtering)
        magika_filter: Optional single filetype to filter by (overrides SUPPORTED_FORMATS)
        yara_scan: Whether we're in YARA-only mode (skips decompile filtering)
        force: Skip all deduplication checks when True
        rerun: Query disassembled table directly (only already-disassembled samples)

    Returns:
        List of dicts with sha256, s3_bucket, s3_key for each analyzed sample
    """
    try:
        client = settings.create_clickhouse_client()
        s3_bucket = os.getenv('S3_BUCKET')

        if not s3_bucket:
            print("[ERROR] S3_BUCKET environment variable is required")
            return []

        # Rerun mode: query directly from disassembled_functions_references
        # instead of basic_properties. This targets only samples that already
        # went through binja successfully.
        if rerun:
            disassembled_table = _get_code_dedup_table(magika_filter)
            basic_table = f"{index_prefix}_basic_properties"

            # Join with basic_properties to get filetype_magika and apply format filters
            conditions = []
            params = {}

            if magika_filter:
                conditions.append("bp.filetype_magika = %(magika)s")
                params["magika"] = magika_filter
            else:
                supported_formats = get_supported_formats()
                conditions.append("bp.filetype_magika IN %(formats)s")
                params["formats"] = supported_formats

            query = (
                f"SELECT DISTINCT d.sha256, bp.filetype_magika "
                f"FROM {disassembled_table} d FINAL "
                f"INNER JOIN {basic_table} bp FINAL ON d.sha256 = bp.sha256"
            )
            if conditions:
                query += " WHERE " + " AND ".join(conditions)

            result = client.query(query, parameters=params)

            rows = []
            for row in result.result_rows:
                sha256 = row[0]
                if isinstance(sha256, bytes):
                    sha256 = sha256.decode('utf-8')
                rows.append({
                    'sha256': sha256,
                    's3_bucket': s3_bucket,
                    's3_key': generate_s3_key_from_hash(sha256),
                    'filetype_magika': row[1]
                })

            print(f"[INFO] Rerun mode: found {len(rows)} already-disassembled samples in {disassembled_table}")

            import random
            random.shuffle(rows)
            return rows

        basic_table = f"{index_prefix}_basic_properties"

        # Build query
        conditions = []
        params = {}

        if magika_filter:
            conditions.append("filetype_magika = %(magika)s")
            params["magika"] = magika_filter
        else:
            supported_formats = get_supported_formats()
            conditions.append("filetype_magika IN %(formats)s")
            params["formats"] = supported_formats

        query = f"SELECT DISTINCT sha256, filetype_magika FROM {basic_table} FINAL"
        if conditions:
            query += " WHERE " + " AND ".join(conditions)

        result = client.query(query, parameters=params)

        rows = []
        for row in result.result_rows:
            sha256 = row[0]
            if isinstance(sha256, bytes):
                sha256 = sha256.decode('utf-8')
            rows.append({
                'sha256': sha256,
                's3_bucket': s3_bucket,
                's3_key': generate_s3_key_from_hash(sha256),
                'filetype_magika': row[1]
            })

        print(f"[DEBUG] Found {len(rows)} analyzed samples in {basic_table}")

        # In YARA-only mode, filter out already-scanned samples (unless force)
        if yara_scan and not force:
            sha256_list = [r['sha256'] for r in rows]
            if sha256_list:
                already_scanned = _check_yara_matches_bulk(sha256_list)
                print(f"[INFO] Found {len(already_scanned)} already YARA-scanned samples")
                rows = [r for r in rows if r['sha256'].lower() not in already_scanned]
                print(f"[INFO] After filtering, {len(rows)} samples remain for YARA scanning")
        # In decompile mode, filter out already-disassembled samples (unless force)
        # We check disassembly (not decompilation) because disassembly is the ground truth:
        # disassembly always succeeds, decompilation may not, so a missing decompile
        # entry doesn't mean the sample wasn't analyzed.
        elif decompile and not force:
            sha256_list = [r['sha256'] for r in rows]
            if sha256_list:
                disassembled_table = _get_code_dedup_table(magika_filter)
                batch_size = 3900

                already_disassembled = set()
                for i in range(0, len(sha256_list), batch_size):
                    batch = sha256_list[i:i+batch_size]
                    placeholders = "','".join(batch)
                    check_query = f"SELECT DISTINCT sha256 FROM {disassembled_table} FINAL WHERE sha256 IN ('{placeholders}')"
                    check_result = client.query(check_query)
                    for check_row in check_result.result_rows:
                        hash_value = check_row[0]
                        if isinstance(hash_value, bytes):
                            hash_value = hash_value.decode('utf-8')
                        already_disassembled.add(hash_value)

                print(f"[INFO] Found {len(already_disassembled)} already-disassembled samples")
                rows = [r for r in rows if r['sha256'] not in already_disassembled]
                print(f"[INFO] After filtering, {len(rows)} samples remain for decompilation")
        elif force:
            print(f"[INFO] Force mode: returning all {len(rows)} analyzed samples")

        # Randomize the order of rows before returning
        import random
        random.shuffle(rows)

        return rows
    except Exception as e:
        print(f"[ERROR] Failed to query analyzed samples: {e}")
        return []
    finally:
        if 'client' in locals():
            client.close()


def is_in_db(sha256, index_prefix, client=None):
    """
    Check if a sample with given SHA256 already exists in the database

    Args:
        sha256: File's SHA256 hash
        index_prefix: Table prefix for ClickHouse
        client: Optional ClickHouse client instance

    Returns:
        bool: True if file exists, False otherwise
    """
    table = f"{index_prefix}_basic_properties"
    close_client = False

    try:
        if client is None:
            client = settings.create_clickhouse_client()
            close_client = True

        # No need for FINAL when checking existence with LIMIT 1
        # Any version of the row proves the sample exists
        query = f"SELECT 1 FROM {table} WHERE sha256 = %(sha256)s LIMIT 1"
        result = client.query(query, parameters={"sha256": sha256})

        return len(result.result_rows) > 0
    except Exception as e:
        print(f"[ERROR] Failed to check if file is in DB: {e}")
        return False
    finally:
        if close_client and client:
            client.close()


def _get_code_dedup_table(magika_filter: Optional[str] = None) -> str:
    """
    Return the code-analysis table used for deduplication based on filetype.

    APK samples are disassembled into code_apk_smali_methods_references;
    everything else uses {CLICKHOUSE_CODE_PREFIX}_disassembled_functions_references.
    """
    if magika_filter == "apk":
        return "code_apk_smali_methods_references"
    code_prefix = os.getenv("CLICKHOUSE_CODE_PREFIX", "code_binja")
    return f"{code_prefix}_disassembled_functions_references"


def is_in_code_db(sha256, client=None, filetype=None):
    """
    Check if a sample with given SHA256 has already been disassembled.

    Args:
        sha256: File's SHA256 hash
        client: Optional ClickHouse client instance
        filetype: Magika filetype label (e.g. 'apk') to pick the right code table

    Returns:
        bool: True if file has been disassembled, False otherwise
    """
    table = _get_code_dedup_table(filetype)
    close_client = False

    try:
        if client is None:
            client = settings.create_clickhouse_client()
            close_client = True

        query = f"SELECT 1 FROM {table} WHERE sha256 = %(sha256)s LIMIT 1"
        result = client.query(query, parameters={"sha256": sha256})

        return len(result.result_rows) > 0
    except Exception as e:
        print(f"[ERROR] Failed to check if file is in code DB: {e}")
        return False
    finally:
        if close_client and client:
            client.close()


def _check_yara_matches_bulk(sha256_list):
    """
    Check which samples have already been YARA-scanned by querying yara_matches.

    The yara_matches table uses FixedString(32) binary sha256, so we convert
    hex strings with unhex().

    Args:
        sha256_list: List of hex SHA256 strings to check

    Returns:
        set: Set of hex SHA256 hashes that already have YARA matches
    """
    # unhex('64hexchars') adds 9 chars overhead per entry vs plain '64hexchars'.
    # 3900 works for plain strings (~67 chars each = 261K) but overflows
    # max_query_size (262144) with unhex() wrapping (~73 chars each = 285K).
    # 3500 × 73 = 255K stays safely under the limit.
    batch_size = 3500
    already_scanned = set()

    try:
        client = settings.create_clickhouse_client()

        total_batches = (len(sha256_list) + batch_size - 1) // batch_size
        for batch_num, i in enumerate(range(0, len(sha256_list), batch_size), 1):
            batch = sha256_list[i:i+batch_size]
            unhex_list = ",".join(f"unhex('{h}')" for h in batch)
            query = f"SELECT DISTINCT hex(sha256) FROM yara_matches FINAL WHERE sha256 IN ({unhex_list})"
            result = client.query(query)
            for row in result.result_rows:
                hash_value = row[0]
                if isinstance(hash_value, bytes):
                    hash_value = hash_value.decode('utf-8')
                already_scanned.add(hash_value.lower())

            if batch_num % 100 == 0 or batch_num == total_batches:
                print(f"[INFO] YARA dedup progress: batch {batch_num}/{total_batches}, found {len(already_scanned)} so far")

        print(f"[INFO] YARA dedup: found {len(already_scanned)} already-scanned samples")
        return already_scanned

    except Exception as e:
        raise RuntimeError(f"YARA dedup query failed — aborting to prevent reprocessing all samples: {e}")
    finally:
        if 'client' in locals():
            client.close()


def is_in_db_bulk(sha256_list, index_prefix, decompile, yara_scan=False, magika_filter=None):
    """
    Check which samples from a list of SHA256 hashes should be skipped.

    Args:
        sha256_list: List of SHA256 hashes to check
        index_prefix: Table prefix for ClickHouse
        decompile: Whether we're in decompile mode
        yara_scan: Whether we're in YARA-only mode (checks yara_matches table)
        magika_filter: Magika filetype label (e.g. 'apk') to pick the right code table

    Returns:
        set: Set of SHA256 hashes that should be skipped
    """
    if not sha256_list:
        return set()

    # YARA-only mode: check yara_matches table for already-scanned samples
    if yara_scan:
        return _check_yara_matches_bulk(sha256_list)

    basic_table = f"{index_prefix}_basic_properties"
    batch_size = 3900

    try:
        client = settings.create_clickhouse_client()

        # Step 1: Check basic_properties (required for both modes)
        in_basic_properties = set()
        for i in range(0, len(sha256_list), batch_size):
            batch = sha256_list[i:i+batch_size]
            placeholders = "','".join(batch)
            query = f"SELECT DISTINCT sha256 FROM {basic_table} FINAL WHERE sha256 IN ('{placeholders}')"
            result = client.query(query)
            for row in result.result_rows:
                hash_value = row[0]
                if isinstance(hash_value, bytes):
                    hash_value = hash_value.decode('utf-8')
                in_basic_properties.add(hash_value)

        if not decompile:
            # Analysis mode: skip samples already in basic_properties
            return in_basic_properties

        # Decompile mode: skip samples NOT in basic_properties + already decompiled
        not_in_basic = set(sha256_list) - in_basic_properties

        if not in_basic_properties:
            return set(sha256_list)  # None ready for decompilation

        # Step 2: Check disassembled table for samples that ARE in basic_properties
        # Disassembly is the ground truth for code analysis (it always succeeds,
        # unlike decompilation which may fail).
        disassembled_table = _get_code_dedup_table(magika_filter)

        already_disassembled = set()
        samples_to_check = list(in_basic_properties)
        for i in range(0, len(samples_to_check), batch_size):
            batch = samples_to_check[i:i+batch_size]
            placeholders = "','".join(batch)
            query = f"SELECT DISTINCT sha256 FROM {disassembled_table} FINAL WHERE sha256 IN ('{placeholders}')"
            result = client.query(query)
            for row in result.result_rows:
                hash_value = row[0]
                if isinstance(hash_value, bytes):
                    hash_value = hash_value.decode('utf-8')
                already_disassembled.add(hash_value)

        return not_in_basic | already_disassembled

    except Exception as e:
        print(f"[ERROR] Failed to check hashes in DB: {e}")
        return set()
    finally:
        if 'client' in locals():
            client.close()