import UIButton from '@/components/ui/ui-button';
import { Colors } from '@/constants/theme';
import api from '@/utils/api';
import { openSystemSettings } from '@/utils/os';
import { ActionSheet, ActivityIndicator, Icon, Modal, Toast } from '@ant-design/react-native';
import { Ionicons } from '@expo/vector-icons';
import clsx from 'clsx';
import { DocumentPickerAsset, getDocumentAsync } from 'expo-document-picker';
import { File } from 'expo-file-system';
import {
    ImagePickerAsset,
    launchCameraAsync,
    launchImageLibraryAsync,
    requestCameraPermissionsAsync,
    requestMediaLibraryPermissionsAsync,
} from 'expo-image-picker';
import { Link } from 'expo-router';
import { useCallback, useEffect, useState } from 'react';
import { Platform, Pressable, Text, View } from 'react-native';

type Asset = ImagePickerAsset | DocumentPickerAsset;
type UploadHandler = (assets: Asset[]) => void;

type UploadState = 0 | 1 | 2; // 0: 待选择 / 1: 上传中 / 2: 已提交

type Attachment = { url: string; fullurl: string; attid: unknown };

const DOCUMENT_MIME_TYPES = [
    'application/pdf',
    'application/msword',
    'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    'application/vnd.ms-excel',
    'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    'application/wps-office.doc',
    'application/wps-office.docx',
    'application/wps-office.xls',
    'application/wps-office.xlsx',
    'application/wps-office.et',
    'application/wps-office.wps',
    'text/plain',
    'text/html',
    'image/*',
];

function alertPermissionDenied() {
    Modal.alert(
        '请允许相册权限',
        '如果点击"确认"按钮后没有跳转，请自己前往系统设置开启相关权限',
        [{ text: '确认', onPress: openSystemSettings }]
    );
}

const takePhoto = async (upload: UploadHandler) => {
    const permission = await requestCameraPermissionsAsync();
    if (!permission.granted) {
        alertPermissionDenied();
        return;
    }
    const toastKey = Toast.loading('正在打开相机...');
    try {
        const result = await launchCameraAsync({ allowsEditing: false, quality: 0.9 });
        if (!result.canceled) upload(result.assets);
    } catch (err) {
        console.warn(err);
        Toast.fail('打开相机失败，请重试');
    } finally {
        Toast.remove(toastKey);
    }
};

const pickImage = async (upload: UploadHandler) => {
    const permission = await requestMediaLibraryPermissionsAsync();
    if (!permission.granted) {
        alertPermissionDenied();
        return;
    }
    const toastKey = Toast.loading('正在打开相册...');
    try {
        const result = await launchImageLibraryAsync({
            mediaTypes: ['images'],
            allowsEditing: false,
            quality: 0.9,
        });
        if (!result.canceled) upload(result.assets);
    } catch (err) {
        console.warn(err);
        Toast.fail('打开相册失败，请重试');
    } finally {
        Toast.remove(toastKey);
    }
};

const pickDocument = async (upload: UploadHandler) => {
    const toastKey = Toast.loading('正在打开文件选择器...');
    try {
        const result = await getDocumentAsync({
            type: DOCUMENT_MIME_TYPES,
            copyToCacheDirectory: true,
        });
        if (!result.canceled) upload(result.assets);
    } catch (err) {
        console.warn(err);
        Toast.fail('打开文件失败，请重试');
    } finally {
        Toast.remove(toastKey);
    }
};

async function uploadAndCreateCredit(assets: Asset[]) {
    const file = new File(assets[0].uri);
    const formData = new FormData();
    formData.append('file', file);
    const attachment = await api.uploadFile<Attachment>('common/upload', { body: formData });
    await api.post('/credit/create', { att: JSON.stringify(attachment) });
}

export function UploadScreen({
    visible,
    onClose,
}: {
    visible: boolean;
    onClose: (isCancel: boolean) => void;
}) {
    const [state, setState] = useState<UploadState>(0);

    useEffect(() => {
        if (!visible) setState(0);
    }, [visible]);

    const upload = useCallback<UploadHandler>(async (assets) => {
        setState(1);
        try {
            await uploadAndCreateCredit(assets);
            setState(2);
        } catch (err) {
            console.warn(err);
            setState(0);
            Toast.fail('上传失败，请重试');
        }
    }, []);

    return (
        <Modal visible={visible} transparent animationType="slide">
            <View className="flex-row items-center">
                <Ionicons name="cloud-upload" size={48} color={Colors.tint} />
                <Text className="ml-4 text-3xl font-bold">征信分析</Text>
            </View>
            {state === 0 && (
                <View className="w-72 h-auto px-6">
                    <Text className="mt-2 text-2xl">请选择征信上传方式</Text>
                    <UIButton title="从本机文件" icon="folder" onPress={() => pickDocument(upload)} className="mt-8" />
                    {Platform.OS === 'ios' && (
                        <UIButton title="从手机相册" icon="picture" onPress={() => pickImage(upload)} className="mt-4" />
                    )}
                    <UIButton title="拍照上传" icon="camera" onPress={() => takePhoto(upload)} className="mt-4" />
                </View>
            )}
            {state === 1 && (
                <View className="w-72 h-auto p-8">
                    <ActivityIndicator size="large" color={Colors.tint} text="正在上传，请稍候..." />
                </View>
            )}
            {state === 2 && (
                <>
                    <View className="w-72 h-auto p-8 flex-row">
                        <Ionicons name="time-outline" size={48} color={Colors.tint} />
                        <Text className="mt-4 ml-4 text-2xl">AI 正在分析</Text>
                    </View>
                    <Text className="mt-4 ml-4 text-2xl">
                        <Link asChild href="/(tabs)/analytics" onPress={() => onClose(false)}>
                            <Text className="text-primary">分析页</Text>
                        </Link>
                        查看状态和结果
                    </Text>
                </>
            )}
            <View className="h-8" />
            {state !== 1 && (
                <Pressable
                    hitSlop={8}
                    className="absolute top-0 right-4"
                    onPress={() => onClose(state !== 2)}
                >
                    <Icon name="close" size={32} />
                </Pressable>
            )}
        </Modal>
    );
}

export function UploadComponent({ onComplete }: { onComplete: () => void }) {
    const [state, setState] = useState<UploadState>(0);

    const upload = useCallback<UploadHandler>(
        async (assets) => {
            setState(1);
            try {
                await uploadAndCreateCredit(assets);
                setState(0);
                onComplete?.();
            } catch (err) {
                console.warn(err);
                setState(0);
                Toast.fail('上传失败，请重试');
            }
        },
        [onComplete]
    );

    const handleSelect = useCallback(
        (index: number) => {
            if (Platform.OS === 'ios') {
                if (index === 0) pickDocument(upload);
                else if (index === 1) pickImage(upload);
                else if (index === 2) takePhoto(upload);
                return;
            }
            if (index === 0) pickDocument(upload);
            else if (index === 1) takePhoto(upload);
        },
        [upload]
    );

    const selectFile = useCallback(() => {
        ActionSheet.showActionSheetWithOptions(
            {
                title: '请选择征信上传方式',
                cancelButtonIndex: Platform.OS === 'ios' ? 3 : 2,
                options:
                    Platform.OS === 'ios'
                        ? ['从本机文件', '从手机相册', '拍照上传', '取消']
                        : ['从本机文件', '拍照上传', '取消'],
            },
            handleSelect
        );
    }, [handleSelect]);

    const isUploading = state === 1;
    return (
        <View className="mb-3 rounded-2xl border border-outline-variant bg-surface-container-lowest p-4">
            <Text className="mb-3 text-xs font-bold uppercase tracking-widest text-outline">
                上传征信文件
            </Text>
            <Pressable
                onPress={selectFile}
                disabled={isUploading}
                className="items-center rounded-2xl border-2 border-dashed border-outline-variant/40 bg-surface-container-low/50 px-6 py-8 disabled:opacity-50"
            >
                <View className="mb-3 h-14 w-14 items-center justify-center rounded-full bg-primary-fixed">
                    <Ionicons name="cloud-upload-outline" size={30} color="#004ac6" />
                </View>
                {isUploading ? (
                    <ActivityIndicator text="正在上传文档" size="small" />
                ) : (
                    <Text className="text-base font-bold text-on-surface">点击上传征信报告</Text>
                )}
                <Text
                    className={clsx('mt-1 text-sm leading-6 text-on-surface-variant', {
                        'opacity-50': isUploading,
                    })}
                >
                    支持 PDF、图片格式，最大 20MB
                </Text>
            </Pressable>
        </View>
    );
}
