import { fetchApi } from '@/lib/server-api-util';
import { ConfirmUpload, defaultExifData, ExifData, FileStatus, ImagesPickerProps, UploadResult, UploadUrlResponse } from '@/types/upload';
import * as ImageManipulator from 'expo-image-manipulator';
import * as ImagePicker from 'expo-image-picker';
import * as Location from 'expo-location';
import * as MediaLibrary from 'expo-media-library';
import React, { useEffect, useState } from 'react';
import { Alert, Button, Platform, TouchableOpacity, View } from 'react-native';
import * as Progress from 'react-native-progress';

export const ImagesPicker: React.FC<ImagesPickerProps> = ({
    children,
    style,
    onPickImage,
    compressQuality = 0.8,
    maxWidth = 2048,
    maxHeight = 2048,
    preserveExif = true,
    onUploadComplete,
    onProgress,
}) => {
    const [isLoading, setIsLoading] = useState(false);

    // 请求权限
    const requestPermissions = async () => {
        if (Platform.OS !== 'web') {

            const { status: mediaStatus } = await ImagePicker.requestMediaLibraryPermissionsAsync();
            if (mediaStatus !== 'granted') {
                Alert.alert('需要媒体库权限', '请允许访问媒体库以选择图片');
                return false;
            }

            const { status: locationStatus } = await Location.requestForegroundPermissionsAsync();;
            if (locationStatus !== 'granted') {
                Alert.alert('需要位置权限', '需要位置权限才能获取图片位置信息');
            }
        }
        return true;
    };

    // 获取上传URL
    const getUploadUrl = async (file: File, metadata: Record<string, any> = {}): Promise<UploadUrlResponse> => {
        const body = {
            filename: file.name,
            content_type: file.type,
            file_size: file.size,
            metadata: {
                ...metadata,
                originalName: file.name,
                fileType: 'image',
                isCompressed: metadata.isCompressed || 'false',
            },
        };
        return await fetchApi<UploadUrlResponse>("/file/generate-upload-url", {
            method: 'POST',
            body: JSON.stringify(body)
        });
    };

    // 向服务端confirm上传
    const confirmUpload = async (file_id: string): Promise<ConfirmUpload> => await fetchApi<ConfirmUpload>('/file/confirm-upload', {
        method: 'POST',
        body: JSON.stringify({
            file_id
        })
    });

    // 新增素材
    const addMaterial = async (file: string, compressFile: string) => {
        await fetchApi('/material', {
            method: 'POST',
            body: JSON.stringify([{
                "file_id": file,
                "preview_file_id": compressFile
            }])
        }).catch((error) => {
            // console.log(error);
        })
    }
    // 上传文件到URL
    const uploadFileToUrl = async (file: File, uploadUrl: string, onProgress: (progress: number) => void): Promise<void> => {
        return new Promise((resolve, reject) => {
            const xhr = new XMLHttpRequest();

            xhr.open('PUT', uploadUrl);
            xhr.setRequestHeader('Content-Type', file.type);

            // 进度监听
            xhr.upload.onprogress = (event) => {
                if (event.lengthComputable) {
                    const progress = Math.round((event.loaded / event.total) * 100);
                    onProgress(progress);
                }
            };

            xhr.onload = () => {
                if (xhr.status >= 200 && xhr.status < 300) {
                    resolve();
                } else {
                    reject(new Error(`Upload failed with status ${xhr.status}`));
                }
            };

            xhr.onerror = () => {
                reject(new Error('Network error during upload'));
            };

            xhr.send(file);
        });
    };
    // 上传进度
    const [currentFileStatus, setCurrentFileStatus] = useState<FileStatus>({
        file: null as unknown as File,
        status: 'pending',
        progress: 0
    });

    // 使用函数更新文件状态，确保每次更新都是原子的
    const updateFileStatus = (updates: Partial<FileStatus>) => {
        setCurrentFileStatus((original) => ({ ...original, ...updates }))
    };
    // 上传文件
    const uploadFile = async (file: File, metadata: Record<string, any> = {}): Promise<ConfirmUpload> => {

        try {
            // 初始化上传状态
            updateFileStatus({ status: 'uploading', progress: 1 });

            // 添加小延迟，确保初始状态能被看到
            await new Promise(resolve => setTimeout(resolve, 300));

            // 获取上传URL
            const { upload_url, file_id } = await getUploadUrl(file, metadata);
            // 上传文件到URL
            await uploadFileToUrl(
                file,
                upload_url,
                (progress) => {
                    // 将实际进度映射到 60%-90% 区间
                    const mappedProgress = 60 + (progress * 0.3);
                    updateFileStatus({ progress: Math.round(mappedProgress) });
                }
            );
            // 确认上传到服务器
            const fileData = confirmUpload(file_id)

            // 将fileData, upload_url,file_id 传递出去
            return { ...fileData, upload_url, file_id }
        } catch (error) {
            console.error('上传文件时出错:', error);
            updateFileStatus({
                status: 'error',
                error: error instanceof Error ? error.message : '上传失败'
            });
            throw new Error('文件上传失败');
        }
    };

    // 压缩并处理图片
    const processImage = async (uri: string, fileName: string, mimeType: string) => {
        try {
            // 压缩图片
            const manipResult = await ImageManipulator.manipulateAsync(
                uri,
                [
                    {
                        resize: {
                            width: maxWidth,
                            height: maxHeight,
                        },
                    },
                ],
                {
                    compress: compressQuality,
                    format: ImageManipulator.SaveFormat.JPEG,
                    base64: false,
                }
            );

            // 获取压缩后的图片数据
            const response = await fetch(manipResult.uri);
            const blob = await response.blob();

            // 创建文件对象
            const file = new File([blob], `compressed_${Date.now()}_${fileName}`, {
                type: mimeType,
            });
            console.log("压缩后的文件", file);

            return { file, uri: manipResult.uri };
        } catch (error) {
            console.error('图片压缩失败:', error);
            throw new Error('图片处理失败');
        }
    };

    // 处理图片选择
    const pickImage = async () => {
        try {
            setIsLoading(true);
            const hasPermission = await requestPermissions();
            if (!hasPermission) return;

            const result = await ImagePicker.launchImageLibraryAsync({
                mediaTypes: ImagePicker.MediaTypeOptions.Images,
                allowsMultipleSelection: false,
                quality: 1,
                exif: preserveExif,
            });

            if (result.canceled || !result.assets?.[0]) {
                setIsLoading(false);
                return;
            }

            const asset = result.assets[0];
            try {
                // 获取原图文件
                const originalResponse = await fetch(asset.uri);
                const originalBlob = await originalResponse.blob();
                const originalFile = new File(
                    [originalBlob],
                    `original_${Date.now()}_${asset.fileName || 'photo.jpg'}`,
                    { type: asset.mimeType || 'image/jpeg' }
                ) as File;

                // 压缩并处理图片
                const { file: compressedFile } = await processImage(
                    asset.uri,
                    asset.fileName || 'photo.jpg',
                    asset.mimeType || 'image/jpeg'
                );

                let exifData: ExifData = { ...defaultExifData };

                // 如果保留 EXIF 数据，则获取
                if (preserveExif && asset.exif) {
                    exifData = { ...exifData, ...asset.exif };

                    if (asset.uri && Platform.OS !== 'web') {
                        try {
                            const mediaAsset = await MediaLibrary.getAssetInfoAsync(asset.uri);
                            if (mediaAsset.exif) {
                                exifData = { ...exifData, ...mediaAsset.exif };
                            }
                            if (mediaAsset.location) {
                                exifData.GPSLatitude = mediaAsset.location.latitude;
                                exifData.GPSLongitude = mediaAsset.location.longitude;
                            }
                        } catch (error) {
                            console.warn('从媒体库获取 EXIF 数据失败:', error);
                        }
                    }
                }

                // 调用 onPickImage 回调
                onPickImage?.(compressedFile, exifData);

                // 上传文件
                const uploadResults: UploadResult = {
                    originalUrl: undefined,
                    compressedUrl: '',
                    file: compressedFile,
                    exifData,
                    originalFile: {} as ConfirmUpload,
                    compressedFile: {} as ConfirmUpload,
                };

                try {
                    // 上传压缩后的图片
                    const compressedResult = await uploadFile(compressedFile, {
                        isCompressed: 'true',
                        ...exifData,
                    });
                    uploadResults.originalFile = compressedResult;

                    // 上传原图
                    const originalResult = await uploadFile(originalFile, {
                        isCompressed: 'false',
                        ...exifData,
                    });
                    uploadResults.compressedFile = originalResult;

                    // 添加到素材库
                    await addMaterial(uploadResults.originalFile?.file_id, uploadResults.compressedFile?.file_id);
                    // 等待一些时间再标记为成功
                    await new Promise(resolve => setTimeout(resolve, 300));
                    // 更新状态为成功
                    await updateFileStatus({ status: 'success', progress: 100, id: uploadResults.originalFile?.file_id });
                    // 调用上传完成回调
                    onUploadComplete?.(uploadResults);
                } catch (error) {
                    updateFileStatus({ status: 'error', progress: 0, id: uploadResults.originalFile?.file_id });
                    throw error; // 重新抛出错误，让外层 catch 处理
                }
            } catch (error) {
                Alert.alert('错误', '处理图片时出错');
            }
        } catch (error) {
            Alert.alert('错误', '选择图片时出错，请重试');
        } finally {
            setIsLoading(false);
        }
    };

    useEffect(() => {
        if (onProgress) {
            onProgress(currentFileStatus);
        }
    }, [currentFileStatus.progress]);

    return (
        <View style={[style]}>
            {children ? (
                <TouchableOpacity
                    onPress={pickImage}
                    disabled={isLoading}
                    activeOpacity={0.7}
                >
                    {children}
                </TouchableOpacity>
            ) : (
                <Button
                    title={isLoading ? '处理中...' : '选择图片'}
                    onPress={pickImage}
                    disabled={isLoading}
                />
            )}
            {/* 添加上传进度条 */}
            {currentFileStatus.status === 'uploading' && (
                <Progress.Bar progress={currentFileStatus.progress / 100} width={200} key={currentFileStatus.id} animated={true} />
            )}

        </View>
    );
};

export default ImagesPicker;