"""
统一数据源管理器
管理三种数据源：上传文件、本地路径、远程存储（Phase 5）
"""

import os
import logging
import streamlit as st
import pandas as pd

from super_datascope.utils.data_loader import DataLoader, scan_directory
from super_datascope.components.file_uploader import FileUploader

logger = logging.getLogger("super_datascope")


class DataSourceManager:
    """统一数据源管理器"""

    def __init__(self):
        self.loader = DataLoader()
        self.file_uploader = FileUploader()

    def render_source_selector(self) -> list[dict]:
        """渲染数据源选择界面（Tab 布局）

        Returns:
            list[dict]: 选中的文件信息列表
        """
        tab_upload, tab_local, tab_remote = st.tabs([
            "📤 文件上传", "💻 本地路径", "☁️ 远程存储"
        ])

        file_infos = []

        with tab_upload:
            file_infos = self.file_uploader.render()
            if file_infos:
                self.file_uploader.render_uploaded_files_list(file_infos)

        with tab_local:
            file_infos = self._render_local_path_selector() or file_infos

        with tab_remote:
            st.info("☁️ 远程存储（ObjStorage）将在后续版本中支持，敬请期待。")

        return file_infos

    def _render_local_path_selector(self) -> list[dict]:
        """渲染本地路径选择器"""
        input_path = st.text_input(
            "输入本地文件或目录路径",
            value=os.environ.get('DATASCOPE_INPUT_PATH', ''),
            placeholder="/path/to/data/ 或 /path/to/file.parquet",
            key="local_path_input"
        )

        if not input_path or not input_path.strip():
            return []

        input_path = input_path.strip()

        if os.path.isdir(input_path):
            try:
                files = scan_directory(input_path)
                if files:
                    st.success(f"📂 扫描到 {len(files)} 个数据文件")
                    for f in files:
                        st.caption(f"  {f['name']} ({f['size_human']})")
                    return files
                else:
                    st.warning("目录中没有找到支持的数据文件")
            except Exception as e:
                st.error(f"扫描目录失败: {e}")
        elif os.path.isfile(input_path):
            try:
                info = DataLoader.get_file_info(input_path)
                st.success(f"📄 {info['name']} ({info['size_human']})")
                return [info]
            except Exception as e:
                st.error(f"读取文件信息失败: {e}")
        else:
            st.warning("路径不存在，请检查输入")

        return []

    def load_files(self, file_infos: list[dict]) -> dict[str, dict]:
        """加载文件列表到内存

        Returns:
            dict: table_name -> {data: DataFrame, source: str, file_path: str}
        """
        tables = {}

        for info in file_infos:
            path = info['path']
            fmt = info['format']
            base_name = os.path.splitext(info['name'])[0]

            try:
                if fmt == 'sqlite':
                    # SQLite 文件可能包含多个表
                    sqlite_tables = info.get('tables', [])
                    if not sqlite_tables:
                        sqlite_tables = DataLoader.list_sqlite_tables(path)

                    for tbl in sqlite_tables:
                        table_key = f"{base_name}_{tbl}" if len(sqlite_tables) > 1 else base_name
                        df = DataLoader.load_sqlite(path, tbl)
                        tables[table_key] = {
                            'data': df,
                            'source': f"sqlite:{info['name']}:{tbl}",
                            'file_path': path,
                        }
                else:
                    df = DataLoader.load_file(path)
                    tables[base_name] = {
                        'data': df,
                        'source': f"{fmt}:{info['name']}",
                        'file_path': path,
                    }
            except Exception as e:
                logger.error(f"加载文件失败 {path}: {e}")
                st.error(f"加载 {info['name']} 失败: {e}")

        return tables

    def render_loaded_tables(self, tables: dict):
        """渲染已加载的数据表列表"""
        if not tables:
            return

        st.write(f"**已加载 {len(tables)} 个数据表:**")
        for name, info in tables.items():
            df = info['data']
            st.caption(f"📊 {name} — {df.shape[0]} 行 × {df.shape[1]} 列 ({info['source']})")


def render_sqlite_table_selector(db_path: str, key_prefix: str) -> str | None:
    """渲染 SQLite 表选择器"""
    tables = DataLoader.list_sqlite_tables(db_path)

    if not tables:
        st.warning("SQLite 文件中没有找到数据表")
        return None

    selected_table = st.selectbox(
        "选择数据表",
        tables,
        key=f"{key_prefix}_sqlite_table"
    )

    return selected_table
