import {
	PatchUserRequest,
	UserDocumentTypes,
	UserDocuments,
	UserDocumentsUrl,
	UserSettingsFieldStatus,
	UserSettingsField,
} from "@root/model/user"
import { produce } from "immer"
import { create } from "zustand"
import { createJSONStorage, devtools, persist } from "zustand/middleware"
import { StringSchema, string } from "yup"
import { patchUser } from "@root/api/user"
import { UserAccountSettingsFieldStatus, VerificationStatus } from "@root/model/account"
import { patchCurrency, deleteCart, patchCart } from "@root/api/cart"
import { User, UserAccount, UserName, getInitials, patchUserAccount } from "@frontend/kitui"
import { setNotEnoughMoneyAmount } from "./cart";

interface UserStore {
  userId: string | null;
  user: User | null;
  userAccount: UserAccount | null;
  settingsFields: UserSettingsFieldStatus & UserAccountSettingsFieldStatus & { hasError: boolean };
  verificationStatus: VerificationStatus;
  verificationType: "juridical" | "nko";
  isDocumentsDialogOpen: boolean;
  dialogType: "juridical" | "nko" | "";
  documents: UserDocuments;
  documentsUrl: UserDocumentsUrl;
  comment: string;
  initials: string;
}

const defaultFieldValues = {
	value: "",
	error: null,
	touched: false,
}

const defaultFields: UserStore["settingsFields"] = {
	firstname: { ...defaultFieldValues },
	secondname: { ...defaultFieldValues },
	middlename: { ...defaultFieldValues },
	orgname: { ...defaultFieldValues },
	email: { ...defaultFieldValues },
	phoneNumber: { ...defaultFieldValues },
	password: { ...defaultFieldValues },
	hasError: false,
}

export const defaultDocument = {
	file: null,
	uploadedFileName: null,
	imageSrc: null,
}

const initialState: UserStore = {
	userId: null,
	user: null,
	userAccount: null,
	settingsFields: { ...defaultFields },
	verificationStatus: VerificationStatus.NOT_VERIFICATED,
	verificationType: "juridical",
	isDocumentsDialogOpen: false,
	dialogType: "",
	comment: "",
	documents: {
		ИНН: { ...defaultDocument },
		Устав: { ...defaultDocument },
		"Свидетельство о регистрации НКО": { ...defaultDocument },
	},
	documentsUrl: {
		ИНН: "",
		Устав: "",
		"Свидетельство о регистрации НКО": "",
	},
	initials: "AA",
}

export const useUserStore = create<UserStore>()(
	persist(
		devtools((set, get) => initialState, {
			name: "User",
			enabled: process.env.NODE_ENV === "development",
			trace: true,
		}),
		{
			version: 2,
			name: "user",
			storage: createJSONStorage(() => localStorage),
			partialize: (state) => ({ // список полей для хранения в ЛС
				userId: state.userId,
				user: state.user,
			}),
			migrate: (persistedState, version) => ({
				...(persistedState as UserStore),
				user: null,
			}),
		}
	)
)

export const setVerificationStatus = (verificationStatus: VerificationStatus) =>
	useUserStore.setState({ verificationStatus })

export const setVerificationType = (verificationType: "nko" | "org") =>
	useUserStore.setState({
		verificationType: verificationType === "org" ? "juridical" : "nko",
	})

export const setUserId = (userId: string | null) => useUserStore.setState({ userId })
export const setUser = (user: User) =>
	useUserStore.setState(
		produce<UserStore>((state) => {
			state.user = user

			state.settingsFields.email.value = user?.email ?? ""
			state.settingsFields.phoneNumber.value = user?.phoneNumber ?? ""
			state.settingsFields.password.value = ""
		})
	)

export const setUserAccount = (user: UserAccount) =>
	useUserStore.setState(
		produce<UserStore>((state) => {
			state.userAccount = user

			state.settingsFields.firstname.value = user?.name.firstname ?? ""
			state.settingsFields.secondname.value = user?.name.secondname ?? ""
			state.settingsFields.middlename.value = user?.name.middlename ?? ""
			state.settingsFields.orgname.value = user?.name.orgname ?? ""

			state.initials = getInitials(state.settingsFields.firstname.value, state.settingsFields.secondname.value)
		}),
		false,
		{
			type: "setUserAccount",
			payload: user,
		}
	)

export const setCart = (cart: string[]) =>
	useUserStore.setState(
		produce<UserStore>((state) => {
			if (state.userAccount) state.userAccount.cart = cart
		})
	)

export const setComment = (comment: string) => useUserStore.setState({ comment })

export const clearUserData = () => useUserStore.setState({ ...initialState })

export const openDocumentsDialog = (type: UserStore["dialogType"]) =>
	useUserStore.setState(
		produce<UserStore>((state) => {
			state.isDocumentsDialogOpen = true
			state.dialogType = type
		})
	)

export const closeDocumentsDialog = () =>
	useUserStore.setState(
		produce<UserStore>((state) => {
			state.isDocumentsDialogOpen = false
			state.dialogType = ""
		})
	)

export const setDocument = (type: UserDocumentTypes, file: File | null) =>
	useUserStore.setState(
		produce<UserStore>((state) => {
			if (!file) {
				state.documents[type] = { ...defaultDocument }
				return
			}

			let imageSrc: string | null = null

			try {
				const src = state.documents[type].imageSrc
				if (src) URL.revokeObjectURL(src)

				imageSrc = URL.createObjectURL(file)
			} catch (error) {
				console.log("Error creating object url", error)
			}

			state.documents[type] = {
				file,
				uploadedFileName: null,
				imageSrc,
			}
		})
	)

export const setDocumentUrl = (type: UserDocumentTypes, url: string) =>
	useUserStore.setState(
		produce<UserStore>((state) => {
			if (!url) {
				state.documentsUrl[type] = ""
				return
			}

			state.documentsUrl[type] = url
		})
	)

export const setUploadedDocument = (type: UserDocumentTypes, fileName: string, url: string) =>
	useUserStore.setState(
		produce<UserStore>((state) => {
			state.documents[type] = {
				file: null,
				uploadedFileName: fileName,
				imageSrc: url,
			}
		})
	)

export const setSettingsField = (fieldName: UserSettingsField | keyof UserName, value: string) => 
	useUserStore.setState(
		produce<UserStore>((state) => {
			if (!state.settingsFields) return

			let errorMessage: string | null = null

			try {
				if (value) validators[fieldName].validateSync(value)
			} catch (error: any) {
				errorMessage = error.message
			}

			state.settingsFields[fieldName].value = value || ""
			state.settingsFields[fieldName].touched = true
			state.settingsFields[fieldName].error = errorMessage

			state.settingsFields.hasError = Object.values(state.settingsFields).reduce((acc: boolean, field) => {
				if (typeof field === "boolean") return acc

				if (field.error !== null) return true
				return acc
			}, false)
		})
	)

export const sendUserData = async () => {
	const state = useUserStore.getState()
	if (!state.settingsFields) return

	const isPatchingUser =
    state.settingsFields.email.touched ||
    state.settingsFields.password.touched ||
    state.settingsFields.phoneNumber.touched

	const isPatchingUserAccount =
    state.settingsFields.firstname.touched ||
    state.settingsFields.secondname.touched ||
    state.settingsFields.middlename.touched ||
    state.settingsFields.orgname.touched

	const userPayload: PatchUserRequest = {}

	if (state.settingsFields.email.value.length !== 0) userPayload.email = state.settingsFields.email.value
	if (state.settingsFields.password.value.length !== 0) userPayload.password = state.settingsFields.password.value
	if (state.settingsFields.phoneNumber.value.length !== 0)
		userPayload.phoneNumber = state.settingsFields.phoneNumber.value

	const userAccountPayload: UserName = {
		firstname: state.settingsFields.firstname.value,
		secondname: state.settingsFields.secondname.value,
		middlename: state.settingsFields.middlename.value,
		orgname: state.settingsFields.orgname.value,
	}

	await Promise.all([
		isPatchingUser && patchUser(userPayload).then(([user]) => user && setUser(user)),
		isPatchingUserAccount && patchUserAccount(userAccountPayload).then(setUserAccount),
	])
}

export const addTariffToCart = async (tariffId: string) => {
	const [patchCartResponse, patchCartError] = await patchCart(tariffId)

	if (patchCartError === undefined) {
		setCart(patchCartResponse)
	}
	return({patchCartResponse, patchCartError})
}

export const removeTariffFromCart = async (tariffId: string) => {
    setNotEnoughMoneyAmount(0);
	const [deleteCartResponse, deleteCartError] = await deleteCart(tariffId)

	if (!deleteCartError) {
		setCart(deleteCartResponse)
	}
}

export const changeUserCurrency = async (currency: string) => {
	const [patchCurrencyResponse, patchCurrencyError] = await patchCurrency(currency)

	if (!patchCurrencyError && patchCurrencyResponse) {
		setUserAccount(patchCurrencyResponse)
	}
}

const validators: Record<UserSettingsField | keyof UserName, StringSchema> = {
	email: string().email("Неверный email"),
	phoneNumber: string()
		.matches(/^[+\d|\d]*$/, "Неверный номер телефона")
		.min(6, "Номер телефона должен содержать минимум 6 символов"),
	password: string()
		.min(8, "Минимум 8 символов")
		.matches(/^[.,:;-_+\d\w]+$/, "Некорректные символы в пароле")
		.optional(),
	firstname: string(),
	secondname: string(),
	middlename: string(),
	orgname: string(),
}
