import axios, {isAxiosError} from 'axios';
import { Alert } from 'react-native';
import * as SecureStore from 'expo-secure-store';
import { forgetPasswordFormData } from '../types/signup';
import { CustomerData } from '../types/signUpFormData';
import * as FileSystem from 'expo-file-system';
import {apiClient} from './requets'
class AuthenticationService {

    async emailLogin(username: string, password: string, isBinding?: boolean) {
        try {
            const response = await apiClient.instance.post('/public/client/customer/sign-in',
                {
                    email: username,
                    password: password,
                    isBinding: isBinding,
                },
                {
                    customConfig: {needAuth: false}
                },
            );
            if (response.status === 201) {
                const token = response.data.accessToken;
                await SecureStore.setItemAsync('accessToken', token);
                return true;
            } else {
                return false;
            }
        } catch (error) {
            if (isAxiosError(error)) {
                console.error('Login error:', error.response?.data?.message || error.message);
            } else {
                console.error('An unexpected error occurred:', error);
            }

            return false;
        }
    }

    async phoneLogin(username: string | null | undefined, password: string, isBinding?: boolean) {
        const response = await apiClient.instance.post(
            `/public/client/customer/phone/sign-in`,
            {
                phone: username,
                password: password,
                isBinding: isBinding,
            },
            {
                customConfig: {needAuth: false}
            }
        );
        if (response.status === 201) {
            const token = response.data.accessToken;
            await SecureStore.setItemAsync('accessToken', token);
            return true;
        } else {
            return false
        }
    }

    async logout() {
        await SecureStore.deleteItemAsync('accessToken');
        console.log('log out successfully, accessToken deleted');
    }

    async sendOtpToSignUpEmail(email: string) {
        try {
            const response = await apiClient.instance.post(
                `/public/client/customer/otp`,
                { email: email },
            );
            if (response.status === 200 || response.status === 201) {
                return true;
            } else {
                console.error('Failed to send OTP:', response.status);
                return false;
            }
        } catch (error) {
            if (isAxiosError(error)) {
                console.error('Error sending OTP:', error.response?.data?.message || error.message);
            } else {
                console.error('An unexpected error occurred while sending OTP:', error);
            }
            return false;
        }
    }

    async uploadUberImage(imageUri: string, customFileName: string) {
        try {
            const fileInfo = await FileSystem.getInfoAsync(imageUri);
            if (!fileInfo.exists) {
                throw new Error('File does not exist');
            }
            const fileExtension = imageUri ? imageUri.split('.').pop()?.toLowerCase() : undefined;
            
            const allowedExtensions = ['jpg', 'jpeg', 'png'];

            if (fileExtension && !allowedExtensions.includes(fileExtension)) {
                throw new Error('只接受jpg,jpeg,png格式的圖片');
            }

            const formData = new FormData();

            const fileName = customFileName || imageUri.split('/').pop();

            formData.append('file', {
                uri: imageUri,
                name: fileName,
                type: `image/${fileExtension}`
            } as any);

            const response = await apiClient.instance.post(`/clients/customer/image?type=uber`, formData, {
                headers: {
                    accept: '*/*',
                    'Content-Type': 'multipart/form-data',
                }
            });
            console.log('Upload response:', response.data);
            return response.data;
        } catch (error) {
            console.error('Error uploading image:', error);
            throw error;
        }
    }

    async verifySignUpOtp(
        email: string,
        code: string,
        setScreen: React.Dispatch<React.SetStateAction<number>>,
        setError: React.Dispatch<React.SetStateAction<string>>
    ) {
        try {
            const response = await apiClient.instance.put(
                `/public/client/customer/otp`,
                { email, code },
            );

            if (response.status === 200) {
                console.log('OTP verified successfully');
                setScreen((currentScreenNumber: number) => currentScreenNumber + 1);
                return true;
            } else {
                console.error('OTP verification failed:', response.status);
                setError('OTP驗證碼錯誤');
                return false;
            }
        } catch (error) {
            if (isAxiosError(error)) {
                console.error('Error verifying OTP:', error.response?.data?.message || error.message);
                setError('發生意外錯誤，請確保您輸入的電子郵件正確，並再次確認您的OTP驗證碼是否正確。');
            } else {
                console.error('An unexpected error occurred while verifying OTP:', error);
                setError('發生意外錯誤，請稍後再試');
            }
            return false;
        }
    }

    async signUp(data: CustomerData) {
        try {
            const response = await apiClient.instance.post(`/public/client/customer`, data);
            if (response.status === 200 || response.status === 201) {
                return true;
            } else {
                console.error('Signup failed:', response.status);
                return false;
            }
        } catch (error) {
            if (isAxiosError(error)) {
                console.error('Error signing up:', error.response?.data?.message || error.message);
            } else {
                console.error('An unexpected error occurred while signing up:', error);
            }
            return false;
        }
    }

    async sendForgetPasswordOtp(email: string) {
        try {
            const response = await apiClient.instance.post(
                `/public/client/customer/pw/otp`,
                { email },
            );
            console.log('Forget password OTP response:', response);
            if (response.status === 200 || response.status === 201) {
                console.log('Forget password OTP sent successfully');
                return true;
            } else {
                console.error('Failed to send forget password OTP:', response.status);
                return false;
            }
        } catch (error) {
            if (isAxiosError(error)) {
                console.error('Error sending forget password OTP:', error.response?.data?.message || error.message);
            } else {
                console.error('An unexpected error occurred while sending forget password OTP:', error);
            }
            return false;
        }
    }

    async getVersion() {
        try {
            const response = await apiClient.instance.get(`/public/client/app/version`);
            return response.data.data;
        } catch (error) {
            console.error('Error getting version:', error);
            return null;
        }
    }

    async verifyingOtpForgetPassword(
        email: string,
        otp: string,
        setForgetPasswordFormData: React.Dispatch<React.SetStateAction<forgetPasswordFormData>>,
        setData: React.Dispatch<React.SetStateAction<string>>
    ) {
        try {
            const res = await apiClient.instance.put(`/public/client/customer/pw/otp`, {
                email: email,
                code: otp
            });
            const data = res.data;
            setData(data.msg);
            console.log(data.msg);
            setForgetPasswordFormData((prevFormData) => ({
                ...prevFormData,
                otpAuthCompleted: true
            }));
            return true;
        } catch (error) {
            console.error('Error', error);
            return false;
        }
    }

    async changePassword(confirmedNewPassword: string, token: string | null) {
        try {
            const res = await apiClient.instance.put(
                `/clients/customer/pw/forget`,
                { newPassword: confirmedNewPassword },
                {
                    customConfig: { token }
                }
            );
            return true;
        } catch (error) {
            if (isAxiosError(error)) {
                console.error('Error changing password:', error.response?.data?.message || error.message);
            } else {
                console.error('An unexpected error occurred:', error);
            }
        }
    }

    async changeEmail(email: string | null, token: string | null): Promise<boolean> {
        try {
            const res = await apiClient.instance.put(
                `/clients/customer`,
                { email: email },
                {
                
                    customConfig: { token }
                }
            );
            console.log('Change Name Successfully!');
            return true;
        } catch (error) {
            if (isAxiosError(error)) {
                console.error('Error changing name:', error.response?.data?.message);
            } else {
                console.error('An unexpected error occurred:', error);
            }
            return false;
        }
    }
    //BELOW CODES RELATE TO "changing account info (such as gender, name)"
    async changeName(name: string | null, token: string | null): Promise<boolean> {
        try {
            const res = await apiClient.instance.put(
                `/clients/customer`,
                { nickname: name },
                {
                    customConfig: { token }
                }
            );
            console.log('Change Name Successfully!');
            return true;
        } catch (error) {
            if (isAxiosError(error)) {
                console.error('Error changing name:', error.response?.data?.message);
            } else {
                console.error('An unexpected error occurred:', error);
            }
            return false;
        }
    }
    async changeNotifySessionID(notifySessionID: string | null): Promise<boolean> {
        try {
            const res = await apiClient.instance.put(
                `/clients/customer`,
                { notify_session_id: notifySessionID }
            );
            if (res.data.status == 200) {
                console.log('Change notifySessionID Successfully!');
                return true;
            } else {
                console.log('Change notifySessionID Failed!');
                return false;
            }
        } catch (error) {
            if (isAxiosError(error)) {
                console.error('Error changing name:', error.response?.data?.message);
            } else {
                console.error('An unexpected error occurred:', error);
            }
            return false;
        }
    }

    async changePhone(phone: string | null, token: string | null): Promise<boolean> {
        try {
            const convertPhoneStringToNumber = Number(phone);
            const res = await apiClient.instance.put(
                `/clients/customer`,
                { phone: convertPhoneStringToNumber },
                {
                    customConfig: { token }
                }
            );
            return true;
        } catch (error) {
            if (isAxiosError(error)) {
                console.error('Error changing phone:', error.response?.data?.message);
            } else {
                console.error('An unexpected error occurred:', error);
            }
            return false;
        }
    }

    async changeGender(gender: string | null, token: string | null): Promise<boolean> {
        try {
            const res = await apiClient.instance.put(
                `/clients/customer`,
                { gender: gender },
                {
                    customConfig: { token }
                }
            );
            console.log('Change gender Successfully!');
            return true;
        } catch (error) {
            if (isAxiosError(error)) {
                console.error('Error changing gender:', error.response?.data?.message);
            } else {
                console.error('An unexpected error occurred:', error);
            }
            return false;
        }
    }
    async getUserInfo() {
        try {
            const response = await apiClient.instance.get(`/clients/customer`);
            if (response.status === 200 || response.status === 201) {
                return response;
            } else {
                console.log('invalid response');
            }
        } catch (error) {
            console.log(error);
        }
    }
    async deleteAccount(): Promise<boolean> {
        try {
            const response = await apiClient.instance.delete(`/clients/customer`);

            if (response.status === 200 || response.status === 201) {
                console.log('Account deleted successfully');

                return true;
            } else {
                console.error('Failed to delete account:', response.status);
                return false;
            }
        } catch (error) {
            if (isAxiosError(error)) {
                console.error('Error deleting account:', error.response?.data?.message || error.message);
            } else {
                console.error('An unexpected error occurred while deleting account:', error);
            }
            return false;
        }
    }

    async checkPhoneSame(phoneNumber: string) {
        try {
            console.log('being checkPhoneSame');
            const response = await apiClient.instance.post(
                `/clients/customer/binding/sms`,
                {
                    phone: phoneNumber,
                    type: 3
                }
            );
            const token = await SecureStore.getItemAsync('accessToken');
            console.log('accessToken', token);
            console.log('checkPhoneSame response', response.data);
            return response.data;
        } catch (error) {
            console.log(error);
        }
    }

    async confirmBindingPhone(phoneNumber: string, otp: string, notify_session_id: string) {
        try {
            const response = await apiClient.instance.put(
                `/public/client/customer/phone/otp`,
                {
                    phone: phoneNumber,
                    code: otp,
                    notify_session_id: notify_session_id,
                    type: 3
                },
            );
            console.log('confirmBindingPhone response', response.data);
            return response.data;
        } catch (error) {
            console.log(error);
        }
    }

    async verifyPhoneOtp(phoneNumber: string, otp: string, notify_session_id: string) {
        try {
            const response = await apiClient.instance.put(
                `/public/client/customer/phone/otp`,
                {
                    phone: phoneNumber,
                    code: otp,
                    notify_session_id: notify_session_id
                },
            );
            return response.data;
        } catch (error) {
            if (isAxiosError(error)) {
                console.error('Error verifying phone OTP:', error.response?.data || error.message);
                throw error;
            } else {
                console.error('Unexpected error:', error);
                throw new Error('Failed to verify phone OTP');
            }
        }
    }
    async sendOtpToSignUpPhone(phone: string) {
        try {
            const response = await apiClient.instance.post(`/public/client/customer/phone/sms`, {
                phone: phone,
                type: 1
            });
            if (response.status === 200 || response.status === 201) {
                return true;
            } else {
                return false;
            }
        } catch (error) {
            console.log(error);
        }
    }
}
export const authenticationService = new AuthenticationService();
