import AsyncStorage from "@react-native-async-storage/async-storage";
import { create } from "zustand";
import { createJSONStorage, persist } from "zustand/middleware";

export type ValidationStatus = "idle" | "pending" | "passed" | "failed";

export type AppState = {
	serverIp: string;
	serverPort: string;
	scannerId?: string;
	stageId?: string;
	deviceName?: string;

	setupCompleted: boolean;
	isRegistered: boolean;

	lastValidationStatus: ValidationStatus;
	lastValidationAt?: string;

	appVersion?: string;

	hasHydrated: boolean;
};

type AppActions = {
	setServerIp: (value: string) => void;
	setServerPort: (value: string) => void;
	setScannerId: (value?: string) => void;
	setStageId: (value?: string) => void;
	setDeviceName: (value?: string) => void;
	setSetupCompleted: (value: boolean) => void;
	setIsRegistered: (value: boolean) => void;
	setValidationStatus: (status: ValidationStatus, validatedAt?: string) => void;
	setAppVersion: (value?: string) => void;
	setHasHydrated: (value: boolean) => void;
	updateAppState: (updates: Partial<AppState>) => void;
	resetApp: () => void;
	hasValidSetup: () => boolean;
	canEnterApp: () => boolean;
	getServerUrl: () => string;
};

export type AppStore = AppState & AppActions;

const defaultAppState: AppState = {
	serverIp: "",
	serverPort: "",
	scannerId: "0001",
	stageId: undefined,
	deviceName: undefined,
	setupCompleted: false,
	isRegistered: false,
	lastValidationStatus: "idle",
	lastValidationAt: undefined,
	appVersion: undefined,
	hasHydrated: false,
};

export const useAppStore = create<AppStore>()(
	persist(
		(set, get) => ({
			...defaultAppState,

			setServerIp: (value) => set({ serverIp: value }),
			setServerPort: (value) => set({ serverPort: value }),
			setScannerId: (value) => set({ scannerId: value }),
			setStageId: (value) => set({ stageId: value }),
			setDeviceName: (value) => set({ deviceName: value }),
			setSetupCompleted: (value) => set({ setupCompleted: value }),
			setIsRegistered: (value) => set({ isRegistered: value }),
			setValidationStatus: (status, validatedAt) =>
				set({
					lastValidationStatus: status,
					lastValidationAt: validatedAt,
				}),
			setAppVersion: (value) => set({ appVersion: value }),
			setHasHydrated: (value) => set({ hasHydrated: value }),
			updateAppState: (updates) =>
				set((state) => ({
					...state,
					...updates,
				})),
			resetApp: () =>
				set({
					...defaultAppState,
					hasHydrated: true,
				}),
			hasValidSetup: () => {
				const state = get();
				return Boolean(
					state.serverIp?.trim() &&
						state.serverPort?.trim() &&
						state.setupCompleted,
				);
			},
			canEnterApp: () => {
				const state = get();
				return Boolean(
					state.serverIp?.trim() &&
						state.serverPort?.trim() &&
						state.setupCompleted &&
						state.isRegistered,
				);
			},

			getServerUrl: () => {
				const { serverIp, serverPort } = get();

				if (!serverIp?.trim() || !serverPort?.trim()) return "";
				return `http://${serverIp.trim()}:${serverPort.trim()}`;
			},
		}),
		{
			name: "lst_mobile_app_store",
			storage: createJSONStorage(() => AsyncStorage),

			onRehydrateStorage: () => (state, error) => {
				if (error) {
					console.log("Failed to hydrate app state", error);
				}

				state?.setHasHydrated(true);
			},

			partialize: (state) => ({
				serverIp: state.serverIp,
				serverPort: state.serverPort,
				scannerId: state.scannerId,
				stageId: state.stageId,
				deviceName: state.deviceName,
				setupCompleted: state.setupCompleted,
				isRegistered: state.isRegistered,
				lastValidationStatus: state.lastValidationStatus,
				lastValidationAt: state.lastValidationAt,
				appVersion: state.appVersion,
			}),
		},
	),
);
