#!/usr/bin/env python3
"""
高光谱图像地理变换工具

功能：
- 读取地理校正后的高光谱航带图像 (dat格式，11个波段：前3个光谱波段、列号、行号、航带号、后5个光谱波段)
- 读取原始高光谱图像 (bil格式)
- 通过行列号进行地理变换匹配
- 保存变换后的高光谱图像

文件命名格式：
- 地理校正文件：2025_9_2_3_53_45_202592_35252_0_rad_rgbxyz_geo1.dat
- 原始文件：2025_9_2_3_53_45_202592_35252_0_rad.bil

依赖：
- numpy
- spectral (pip install spectral)
- pathlib
"""

import numpy as np
import os
from pathlib import Path
import re
from typing import Tuple, Optional, List
try:
    import spectral
    SPECTRAL_AVAILABLE = True
except ImportError:
    SPECTRAL_AVAILABLE = False
    print("警告: spectral库不可用，请安装: pip install spectral")

# 可选：GDAL库用于保存ENVI格式文件
try:
    from osgeo import gdal
    GDAL_AVAILABLE = True
except ImportError:
    GDAL_AVAILABLE = False
    print("警告: GDAL不可用，将使用numpy保存")


def _format_geo_info_for_envi(geo_value):
    """
    直接返回地理信息的原始格式（已经是从HDR文件直接复制的）
    """
    if not geo_value:
        return None
    return geo_value


def extract_file_key(filename: str) -> str:
    """
    从文件名中提取用于匹配的关键字

    匹配规则：按"2025_9_2_3_53_45_202592_35252_0"这一部分完全相同进行匹配
    即匹配模式为：数字_数字_..._数字_rad

    示例：
    "2025_9_2_3_53_45_202592_35252_2_rad_rgbxyz_geo1.dat" -> "2025_9_2_3_53_45_202592_35252_2"
    "2025_9_2_3_53_45_202592_35252_9_rad.bil" -> "2025_9_2_3_53_45_202592_35252_9"
    """
    # 提取_rad之前的部分作为匹配键
    if '_rad' in filename:
        key = filename.split('_rad')[0]
        return key
    else:
        # 如果没有_rad，尝试其他方式
        return filename


def load_geo_corrected_dat(dat_file: str) -> Tuple[np.ndarray, dict]:
    """
    读取地理校正后的dat文件

    dat文件包含11个波段的原始数据：
    - 波段0-2: 前三个光谱波段
    - 波段3: 列号
    - 波段4: 行号
    - 波段5: 航带号
    - 波段6-10: 后五个光谱波段

    使用spectral库读取dat文件

    参数:
    -----------
    dat_file : str
        dat文件路径

    返回:
    -----------
    data : np.ndarray
        图像数据 (pixels, 11)，每个像素11个波段
    metadata : dict
        元数据信息
    """
    if not SPECTRAL_AVAILABLE:
        raise RuntimeError("需要spectral库来读取dat文件，请安装: pip install spectral")

    try:
        # 查找对应的头文件
        dat_path = Path(dat_file)
        hdr_file = dat_path.with_suffix('.hdr')

        if not hdr_file.exists():
            # 首先读取数据大小来推断图像尺寸
            data_temp = np.fromfile(dat_file, dtype=np.float32)
            if data_temp.size % 11 != 0:
                raise ValueError(f"数据大小 {data_temp.size} 不能被11整除，可能不是正确的dat文件格式")

            num_pixels = data_temp.size // 11

            # 尝试推断图像尺寸
            possible_rows = []
            for rows in range(1000, int(np.sqrt(num_pixels)) + 1000, 100):
                if num_pixels % rows == 0:
                    cols = num_pixels // rows
                    if cols > 0 and cols < 10000:
                        possible_rows.append((rows, cols))

            if not possible_rows:
                rows = int(np.sqrt(num_pixels))
                cols = (num_pixels + rows - 1) // rows
            else:
                rows, cols = possible_rows[0]

            # 创建临时的头文件
            hdr_content = f"""ENVI
description = {{
高光谱地理校正数据 - 11波段格式
前3个光谱波段、列号、行号、航带号、后5个光谱波段}}
samples = {cols}
lines = {rows}
bands = 11
header offset = 0
file type = ENVI Standard
data type = 4
interleave = bip
byte order = 0
band names = {{
波段1, 波段2, 波段3, 列号, 行号, 航带号, 波段7, 波段8, 波段9, 波段10, 波段11}}
"""

            with open(hdr_file, 'w', encoding='utf-8') as f:
                f.write(hdr_content)

        # 使用spectral读取
        image_data = spectral.open_image(str(hdr_file))
        data = image_data.load()

        # 如果数据是3D的，需要重新整形为2D (pixels, bands)
        if data.ndim == 3:
            data_reshaped = data.reshape(-1, data.shape[2])
        else:
            data_reshaped = data

        # 确保是11波段
        if data_reshaped.shape[1] != 11:
            raise ValueError(f"数据波段数 {data_reshaped.shape[1]} 不等于期望的11波段")

        # 检查坐标是否全部为0（第4、5波段为列号、行号）
        all_coords_zero = (data_reshaped[:, 3].max() == 0 and data_reshaped[:, 4].max() == 0)

        # 如果坐标都为0，显示警告
        if all_coords_zero:
            print(f"警告: dat文件中的所有行列号都是0，可能需要重新解释数据格式")

        # 读取HDR文件中的地理信息（直接复制原始格式）
        geo_info = {}
        try:
            # 直接读取HDR文件内容，保留原始格式
            with open(str(hdr_file), 'r', encoding='utf-8', errors='ignore') as f:
                hdr_content = f.read()

            # 提取map info行
            import re
            map_info_match = re.search(r'^map info\s*=\s*(.+)$', hdr_content, re.MULTILINE | re.IGNORECASE)
            if map_info_match:
                geo_info['map_info'] = map_info_match.group(1).strip()

            # 提取coordinate system string行
            coord_sys_match = re.search(r'^coordinate system string\s*=\s*(.+)$', hdr_content, re.MULTILINE | re.IGNORECASE)
            if coord_sys_match:
                geo_info['coordinate_system_string'] = coord_sys_match.group(1).strip()

            # 提取projection info行（如果有）
            proj_info_match = re.search(r'^projection info\s*=\s*(.+)$', hdr_content, re.MULTILINE | re.IGNORECASE)
            if proj_info_match:
                geo_info['projection_info'] = proj_info_match.group(1).strip()

        except Exception as e:
            print(f"警告: 无法读取geo文件的HDR地理信息: {e}")

        metadata = {
            'file_path': dat_file,
            'hdr_file': str(hdr_file),
            'data_type': str(data_reshaped.dtype),
            'bands': 11,
            'pixels': len(data_reshaped),
            'lines': image_data.nrows,
            'samples': image_data.ncols,
            'band_names': ['band1', 'band2', 'band3', 'column', 'row', 'strip', 'band7', 'band8', 'band9', 'band10', 'band11'],
            'col_idx': 3,
            'row_idx': 4,
            'strip_idx': 5,
            'all_coords_zero': all_coords_zero,
            'wavelengths': getattr(image_data.bands, 'centers', None),
            'interleave': getattr(image_data, 'interleave', 'unknown'),
            'geo_info': geo_info
        }

        return data_reshaped, metadata

    except Exception as e:
        print(f"spectral读取失败: {e}")
        print("回退到numpy直接读取...")

        # 备用方案：使用numpy直接读取
        try:
            data = np.fromfile(dat_file, dtype=np.float32)

            if data.size % 11 != 0:
                raise ValueError(f"数据大小 {data.size} 不能被11整除，可能不是正确的dat文件格式")

            num_pixels = data.size // 11
            data_reshaped = data.reshape(num_pixels, 11)

            print(f"numpy直接读取成功: {dat_file}")
            print(f"数据形状: {data_reshaped.shape} (pixels, bands)")

            # 分析坐标信息
            all_coords_zero = (data_reshaped[:, 3].max() == 0 and data_reshaped[:, 4].max() == 0)

            metadata = {
                'file_path': dat_file,
                'data_type': 'float32',
                'bands': 11,
                'pixels': num_pixels,
                'band_names': ['band1', 'band2', 'band3', 'column', 'row', 'strip', 'band7', 'band8', 'band9', 'band10', 'band11'],
                'col_idx': 3,
                'row_idx': 4,
                'strip_idx': 5,
                'all_coords_zero': all_coords_zero
            }

            return data_reshaped, metadata

        except Exception as e2:
            raise RuntimeError(f"读取dat文件失败: spectral错误: {e}, numpy错误: {e2}")


def load_original_bil(bil_file: str) -> Tuple[np.ndarray, dict]:
    """
    读取原始高光谱bil文件

    使用spectral库通过hdr头文件读取ENVI格式的高光谱数据

    参数:
    -----------
    bil_file : str
        bil文件路径

    返回:
    -----------
    data : np.ndarray
        高光谱数据 (lines, samples, bands)
    metadata : dict
        元数据信息
    """
    if not SPECTRAL_AVAILABLE:
        raise RuntimeError("需要spectral库来读取bil文件，请安装: pip install spectral")

    try:
        # 查找对应的头文件
        bil_path = Path(bil_file)
        hdr_file = bil_path.with_suffix('.hdr')

        if not hdr_file.exists():
            hdr_file = bil_path.parent / f"{bil_path.name}.hdr"
            if not hdr_file.exists():
                hdr_file = bil_path.parent / f"{bil_path.stem}.hdr"
                if not hdr_file.exists():
                    possible_hdrs = list(bil_path.parent.glob(f"{bil_path.stem}*.hdr"))
                    if possible_hdrs:
                        hdr_file = possible_hdrs[0]
                    else:
                        raise FileNotFoundError(f"未找到对应的头文件")

        # 使用spectral读取ENVI格式文件
        image_data = spectral.open_image(str(hdr_file))
        data = image_data.load()

        # 获取元数据
        metadata = {
            'file_path': bil_file,
            'hdr_file': str(hdr_file),
            'lines': image_data.nrows,
            'samples': image_data.ncols,
            'bands': image_data.nbands,
            'wavelengths': image_data.bands.centers if hasattr(image_data.bands, 'centers') else None,
            'data_type': str(data.dtype),
            'interleave': getattr(image_data, 'interleave', 'unknown')
        }

        return data, metadata

    except Exception as e:
        raise RuntimeError(f"读取高光谱文件失败: {bil_file}, 错误: {e}")


def perform_geometric_transform(original_data: np.ndarray,
                                geo_data: np.ndarray,
                                geo_metadata: dict,
                                output_shape: Optional[Tuple[int, int]] = None,
                                chunk_size: Optional[int] = None) -> np.ndarray:
    """
    向量化版本的地理变换

    核心逻辑：
    1. geo_data[:, 3]和geo_data[:, 4]是原始bil文件中的列号和行号（geo从0开始，bil从1开始，需减1）
    2. geo像素中"非地理参考"的波段（前3个和后5个）不全为0的像素才需要替换（输出保持0）
    3. 输出尺寸为geo图像的尺寸（geo_metadata['lines'], geo_metadata['samples']）
    4. 支持可选分块以降低峰值内存

    参数:
    -----------
    original_data : np.ndarray
        原始高光谱数据 (orig_lines, orig_samples, bands)
    geo_data : np.ndarray
        地理校正数据 (pixels, 11) - geo图像中所有像素的序列
    geo_metadata : dict
        地理校正数据的元数据
    output_shape : tuple, optional
        输出图像的形状 (lines, samples)，如果不指定则尝试从geo_metadata推断
    chunk_size : int, optional
        分块处理时的块大小，默认一次性处理所有像素

    返回:
    -----------
    transformed_data : np.ndarray
        变换后的高光谱数据，尺寸为geo图像的尺寸
    """
    try:
        # 原始BIL尺寸
        orig_lines, orig_samples, bands = original_data.shape

        # 输出尺寸：使用geo尺寸
        if output_shape is None:
            if 'lines' in geo_metadata and 'samples' in geo_metadata:
                lines_out, samples_out = int(geo_metadata['lines']), int(geo_metadata['samples'])
            else:
                # 兜底：按geo展平像素数推断一个尽量方的尺寸
                total = len(geo_data)
                lines_out = int(np.sqrt(total))
                samples_out = (total + lines_out - 1) // lines_out
        else:
            lines_out, samples_out = output_shape

        # 验证输出图像尺寸是否与geo_data像素数量匹配
        expected_pixels = lines_out * samples_out
        if expected_pixels != len(geo_data):
            print(f"警告: 输出图像尺寸({lines_out}x{samples_out}={expected_pixels})与geo数据像素数({len(geo_data)})不匹配")
            print("将调整输出尺寸以匹配geo数据像素数")
            lines_out = len(geo_data) // samples_out
            if lines_out * samples_out < len(geo_data):
                lines_out += 1

        # 预分配输出（忽略值=0）
        out = np.zeros((lines_out, samples_out, bands), dtype=original_data.dtype)

        print(f"开始地理变换: 原始bil尺寸 {orig_lines}x{orig_samples}x{bands}")
        print(f"输出geo图像尺寸: {lines_out}x{samples_out}x{bands}")
        print(f"处理 {len(geo_data)} 个geo像素")

        # 获取坐标索引（从metadata中读取，默认为3、4、5）
        col_idx = geo_metadata.get('col_idx', 3)
        row_idx = geo_metadata.get('row_idx', 4)
        
        # 有效掩码：
        # 1) geo像素的"非地理参考"波段（前col_idx个和后面的）不全为0
        #    对于11波段，检查波段0-2和6-10是否不全为0
        non_geo_bands = np.concatenate([np.arange(col_idx), np.arange(col_idx+3, geo_data.shape[1])])
        non_zero_mask = ~(np.all(geo_data[:, non_geo_bands] == 0, axis=1))
        
        # 2) 索引合法（geo从0，BIL从1，因此索引时要减1）
        src_cols = geo_data[:, col_idx].astype(np.int64) - 1
        src_rows = geo_data[:, row_idx].astype(np.int64) - 1
        in_bounds = (src_rows >= 0) & (src_rows < orig_lines) & (src_cols >= 0) & (src_cols < orig_samples)

        valid = non_zero_mask & in_bounds
        if not np.any(valid):
            print("地理变换完成: 没有有效像素需要处理")
            return out

        # 有效条目
        valid_idx = np.flatnonzero(valid)

        # 计算原始BIL扁平索引，并批量取光谱
        src_rows_v = src_rows[valid]
        src_cols_v = src_cols[valid]
        src_lin = src_rows_v * orig_samples + src_cols_v  # (N_valid,)

        orig_flat = original_data.reshape(-1, bands)
        if chunk_size is None or len(valid_idx) <= chunk_size:
            # 一次性
            spectra = orig_flat[src_lin]  # (N_valid, bands)
            # 计算输出位置（geo是按行优先展平）
            out_rows = valid_idx // samples_out
            out_cols = valid_idx % samples_out
            out[out_rows, out_cols, :] = spectra
        else:
            # 分块，降低峰值内存
            for s in range(0, len(valid_idx), chunk_size):
                e = min(s + chunk_size, len(valid_idx))
                src_lin_chunk = src_lin[s:e]
                spectra = orig_flat[src_lin_chunk]
                idx_chunk = valid_idx[s:e]
                out_rows = idx_chunk // samples_out
                out_cols = idx_chunk % samples_out
                out[out_rows, out_cols, :] = spectra

        valid_count = len(valid_idx)
        skipped_count = len(geo_data) - valid_count
        print(f"地理变换完成: 成功处理 {valid_count} 个像素，跳过 {skipped_count} 个像素（无效或全0）")

        return out

    except Exception as e:
        raise RuntimeError(f"地理变换失败: {e}")


def fill_nan_with_nearest(data: np.ndarray) -> np.ndarray:
    """
    用最近邻值填充NaN值

    参数:
    -----------
    data : np.ndarray
        包含NaN的数组

    返回:
    -----------
    filled_data : np.ndarray
        填充后的数组
    """
    # 简单实现：使用前向填充
    filled_data = data.copy()

    # 对于每个波段
    for band in range(data.shape[2]):
        band_data = data[:, :, band]

        # 找到非NaN值的掩码
        valid_mask = ~np.isnan(band_data)

        if np.any(valid_mask):
            # 使用最近邻插值（这里使用简单的行方向填充）
            for i in range(band_data.shape[0]):
                row_data = band_data[i, :]
                valid_indices = np.where(~np.isnan(row_data))[0]

                if len(valid_indices) > 0:
                    # 对每一行，用有效值填充
                    for j in range(len(row_data)):
                        if np.isnan(row_data[j]):
                            # 找到最近的有效值
                            distances = np.abs(valid_indices - j)
                            nearest_idx = valid_indices[np.argmin(distances)]
                            row_data[j] = row_data[nearest_idx]

            filled_data[:, :, band] = band_data

    return filled_data


def save_transformed_data(data: np.ndarray, output_file: str, wavelengths: Optional[np.ndarray] = None,
                         geo_info: Optional[dict] = None):
    """
    保存变换后的高光谱数据为ENVI BIL格式

    参数:
    -----------
    data : np.ndarray
        要保存的数据 (lines, samples, bands)
    output_file : str
        输出文件路径 (.bil)
    wavelengths : np.ndarray, optional
        波长信息
    """
    lines, samples, bands = data.shape

    # 确保输出目录存在
    output_path = Path(output_file)
    output_path.parent.mkdir(parents=True, exist_ok=True)

    # 输出文件路径
    bil_file = str(output_path.with_suffix('.dat'))
    hdr_file = str(output_path.with_suffix('.hdr'))

    try:
        if GDAL_AVAILABLE:
            # 使用GDAL保存ENVI格式文件
            save_with_gdal_envi(data, bil_file, wavelengths, geo_info)
        else:
            # 回退到numpy保存
            save_with_numpy_envi(data, bil_file, hdr_file, wavelengths, geo_info)

        print(f"✅ 成功保存地理变换结果:")
        print(f"   数据文件: {bil_file}")
        print(f"   头文件: {hdr_file}")
        print(f"   数据尺寸: {lines} x {samples} x {bands}")
        print(f"   保存方式: {'GDAL' if GDAL_AVAILABLE else 'NumPy'}")

    except Exception as e:
        raise RuntimeError(f"保存文件失败: {output_file}, 错误: {e}")


def save_with_gdal_envi(data: np.ndarray, bil_file: str, wavelengths: Optional[np.ndarray] = None,
                        geo_info: Optional[dict] = None):
    """
    使用GDAL保存ENVI BIL格式文件
    """
    lines, samples, bands = data.shape
    hdr_file = bil_file.replace('.dat', '.hdr')

    # 创建GDAL ENVI驱动
    driver = gdal.GetDriverByName('ENVI')

    # 创建数据集，GDAL ENVI默认使用BSQ格式，data type = 12 (uint16)
    dataset = driver.Create(bil_file, samples, lines, bands, gdal.GDT_UInt16,
                           options=['INTERLEAVE=BSQ'])

    if dataset is None:
        raise RuntimeError(f"无法创建ENVI数据集: {bil_file}")

    try:
        # 设置元数据
        metadata = dataset.GetMetadata()
        metadata['DESCRIPTION'] = 'Geometrically transformed hyperspectral data'
        metadata['SENSOR_TYPE'] = 'Hyperspectral'
        metadata['DATA_UNITS'] = 'Reflectance'
        metadata['PROCESSING_ALGORITHM'] = 'Geometric Transformation'
        metadata['CREATION_DATE'] = str(np.datetime64('now'))

        # 添加波长信息到元数据
        if wavelengths is not None and len(wavelengths) == bands:
            metadata['wavelength_units'] = 'nm'
            for i, wl in enumerate(wavelengths):
                metadata[f'wavelength_{i+1}'] = str(wl)

        dataset.SetMetadata(metadata)

        # 写入数据
        for band_idx in range(bands):
            band = dataset.GetRasterBand(band_idx + 1)
            band_data = data[:, :, band_idx].astype(np.float32)
            band.WriteArray(band_data)
            band.SetNoDataValue(0.0)  # 设置NoData值

            # 设置波段描述
            if wavelengths is not None and band_idx < len(wavelengths):
                band.SetDescription(f'{wavelengths[band_idx]:.1f} nm')
            else:
                band.SetDescription(f'Band {band_idx + 1}')

    finally:
        # 关闭数据集
        dataset = None

    # 在数据集完全关闭后，覆盖GDAL自动创建的HDR文件
    import time
    time.sleep(0.1)  # 短暂等待确保GDAL完成写入
    create_envi_header(hdr_file, lines, samples, bands, wavelengths, geo_info)


def save_with_numpy_envi(data: np.ndarray, bil_file: str, hdr_file: str,
                        wavelengths: Optional[np.ndarray] = None, geo_info: Optional[dict] = None):
    """
    使用numpy保存ENVI BSQ格式文件（GDAL不可用时的回退方案）
    """
    lines, samples, bands = data.shape

    # 保存二进制数据 - BSQ格式：按波段顺序存储，data type = 12 (uint16)
    with open(bil_file, 'wb') as f:
        # BSQ格式：对于每个波段，存储所有像素
        for band_idx in range(bands):
            # 转换为uint16，裁剪到有效范围
            band_data = np.clip(data[:, :, band_idx], 0, 65535).astype(np.uint16)
            band_data.tofile(f)

    # 创建HDR头文件
    create_envi_header(hdr_file, lines, samples, bands, wavelengths, geo_info)


def create_envi_header(hdr_file: str, lines: int, samples: int, bands: int,
                      wavelengths: Optional[np.ndarray] = None, geo_info: Optional[dict] = None):
    """
    创建ENVI格式的HDR头文件
    """
    with open(hdr_file, 'w', encoding='utf-8') as f:
        f.write("ENVI\n")
        f.write("description = {\n")
        f.write("  Geometrically transformed hyperspectral data\n")
        f.write("  Processed with Python geometric transformation}\n")
        f.write(f"samples = {samples}\n")
        f.write(f"lines = {lines}\n")
        f.write(f"bands = {bands}\n")
        f.write("header offset = 0\n")
        f.write("file type = ENVI Standard\n")
        f.write("data type = 12\n")  # uint16
        f.write("interleave = bsq\n")
        f.write("sensor type = Hyperspectral\n")
        f.write("byte order = 0\n")  # little-endian
        f.write("data ignore value = 0\n")

        # 添加地理参考信息（直接使用从原始HDR复制的格式）
        if geo_info:
            if geo_info.get('map_info'):
                f.write(f"map info = {geo_info['map_info']}\n")
            if geo_info.get('coordinate_system_string'):
                f.write(f"coordinate system string = {geo_info['coordinate_system_string']}\n")
            if geo_info.get('projection_info'):
                f.write(f"projection info = {geo_info['projection_info']}\n")

        # 添加波长信息
        if wavelengths is not None and len(wavelengths) == bands:
            f.write("wavelength units = nm\n")
            f.write("wavelength = { ")
            for i, wl in enumerate(wavelengths):
                f.write(f"{wl}")
                if i < len(wavelengths) - 1:
                    f.write(",")
            f.write(" }\n")




def process_file_pair(geo_dat_file: str, bil_file: str, output_dir: str) -> bool:
    """
    处理一对匹配的文件

    参数:
    -----------
    geo_dat_file : str
        地理校正dat文件路径
    bil_file : str
        原始bil文件路径
    output_dir : str
        输出目录

    返回:
    -----------
    success : bool
        处理是否成功
    """
    try:
        # 读取地理校正数据
        geo_data, geo_metadata = load_geo_corrected_dat(geo_dat_file)

        # 读取原始高光谱数据
        original_data, orig_metadata = load_original_bil(bil_file)

        # 执行地理变换
        transformed_data = perform_geometric_transform(original_data, geo_data, geo_metadata)

        # 生成输出文件名
        bil_name = Path(bil_file).stem
        output_file = Path(output_dir) / f"{bil_name}_geo_corrected.dat"

        # 保存结果
        wavelengths = orig_metadata.get('wavelengths')
        geo_info = geo_metadata.get('geo_info')
        save_transformed_data(transformed_data, str(output_file), wavelengths, geo_info)

        return True

    except Exception as e:
        print(f"处理失败: {e}")
        return False


def find_matching_files(geo_dir: str, bil_dir: str) -> List[Tuple[str, str]]:
    """
    查找匹配的文件对

    参数:
    -----------
    geo_dir : str
        地理校正文件目录
    bil_dir : str
        原始bil文件目录

    返回:
    -----------
    file_pairs : List[Tuple[str, str]]
        匹配的文件对列表 [(geo_file, bil_file), ...]
    """
    geo_files = {}
    bil_files = {}

    # 收集地理校正文件
    for file_path in Path(geo_dir).glob('*_rad_rgbxyz_geo_angles_registered.bip'):
        key = extract_file_key(file_path.name)
        geo_files[key] = str(file_path)

    # 收集bil文件
    for file_path in Path(bil_dir).glob('*_rad.bil'):
        key = extract_file_key(file_path.name)
        bil_files[key] = str(file_path)

    # 找到匹配的对
    matching_pairs = []
    for key in geo_files.keys():
        if key in bil_files:
            matching_pairs.append((geo_files[key], bil_files[key]))

    return matching_pairs


def batch_process(geo_dir: str, bil_dir: str, output_dir: str) -> dict:
    """
    批量处理所有匹配的文件对

    参数:
    -----------
    geo_dir : str
        地理校正文件目录
    bil_dir : str
        原始bil文件目录
    output_dir : str
        输出目录

    返回:
    -----------
    results : dict
        处理结果统计
    """
    # 确保输出目录存在
    Path(output_dir).mkdir(parents=True, exist_ok=True)

    # 查找匹配的文件对
    file_pairs = find_matching_files(geo_dir, bil_dir)

    if not file_pairs:
        return {'total': 0, 'success': 0, 'failed': 0}

    # 处理每一对文件
    results = {'total': len(file_pairs), 'success': 0, 'failed': 0}

    for geo_file, bil_file in file_pairs:
        success = process_file_pair(geo_file, bil_file, output_dir)
        if success:
            results['success'] += 1
        else:
            results['failed'] += 1

    return results


def main():
    """
    主函数 - 示例用法
    """
    # 示例路径（需要根据实际情况修改）
    geo_corrected_dir = r"D:\BaiduNetdiskDownload\20250902\_3_52_52\316\jiaozhen"  # 地理校正dat文件目录
    original_bil_dir = r"D:\BaiduNetdiskDownload\20250902\_3_52_52\Geoout\Radout"       # 原始bil文件目录
    output_dir = r"D:\BaiduNetdiskDownload\20250902\_3_52_52\316\cube"              # 输出目录

    # 检查依赖
    if not SPECTRAL_AVAILABLE:
        print("错误: 需要安装spectral库")
        return

    # 批量处理
    results = batch_process(geo_corrected_dir, original_bil_dir, output_dir)

    if results['success'] > 0:
        print(f"处理完成！成功处理了 {results['success']} 对文件")
    else:
        print("未成功处理任何文件，请检查文件路径和格式")


if __name__ == "__main__":
    main()