import {
    type CreateDevice,
    type Device,
    type DeviceStatusValue,
    type UpdateDevice,
} from "@pkg/logic/domains/device/data";
import {
    listDevicesSQ,
    createDeviceSC,
    deleteDeviceSC,
    setDeviceStatusSC,
    updateDeviceSC,
} from "./device.remote";
import { toast } from "svelte-sonner";

class DeviceViewModel {
    devices = $state<Device[]>([]);
    loading = $state(false);
    creating = $state(false);
    updating = $state(false);
    deletingId = $state<number | null>(null);
    showCreateDialog = $state(false);
    editingId = $state<number | null>(null);

    async fetchDevices() {
        this.loading = true;
        try {
            const result = await listDevicesSQ();
            if (result?.error || !result?.data) {
                toast.error(
                    result?.error?.message || "Failed to fetch devices",
                    {
                        description:
                            result?.error?.description || "Please try again",
                    },
                );
                return;
            }
            this.devices = result.data as Device[];
        } catch (error) {
            toast.error("Failed to fetch devices", {
                description:
                    error instanceof Error
                        ? error.message
                        : "Please try again",
            });
        } finally {
            this.loading = false;
        }
    }

    async createDevice(data: CreateDevice): Promise<boolean> {
        this.creating = true;
        try {
            const result = await createDeviceSC(data);
            if (result?.error) {
                toast.error(
                    result.error.message || "Failed to create device",
                    {
                        description:
                            result.error.description || "Please try again",
                    },
                );
                return false;
            }
            toast.success("Device created");
            this.showCreateDialog = false;
            if (result.data) {
                this.devices = [...this.devices, result.data as Device];
            }
            return true;
        } catch (error) {
            toast.error("Failed to create device", {
                description:
                    error instanceof Error
                        ? error.message
                        : "Please try again",
            });
            return false;
        } finally {
            this.creating = false;
        }
    }

    async deleteDevice(id: number) {
        this.deletingId = id;
        try {
            const result = await deleteDeviceSC({ id });
            if (result?.error) {
                toast.error(
                    result.error.message || "Failed to delete device",
                    {
                        description:
                            result.error.description || "Please try again",
                    },
                );
                return;
            }
            toast.success("Device deleted");
            this.devices = this.devices.filter((d) => d.id !== id);
        } catch (error) {
            toast.error("Failed to delete device", {
                description:
                    error instanceof Error
                        ? error.message
                        : "Please try again",
            });
        } finally {
            this.deletingId = null;
        }
    }

    async updateDevice(id: number, data: UpdateDevice): Promise<boolean> {
        this.updating = true;
        this.editingId = id;
        try {
            const result = await updateDeviceSC({ id, data });
            if (result?.error) {
                toast.error(
                    result.error.message || "Failed to update device",
                    {
                        description:
                            result.error.description || "Please try again",
                    },
                );
                return false;
            }
            toast.success("Device updated");
            if (result.data) {
                const updated = result.data as Device;
                this.devices = this.devices.map((device) =>
                    device.id === id ? updated : device,
                );
            }
            return true;
        } catch (error) {
            toast.error("Failed to update device", {
                description:
                    error instanceof Error
                        ? error.message
                        : "Please try again",
            });
            return false;
        } finally {
            this.updating = false;
            this.editingId = null;
        }
    }

    async setStatus(id: number, status: DeviceStatusValue) {
        try {
            const result = await setDeviceStatusSC({
                id,
                status,
            });
            if (result?.error) {
                toast.error(
                    result.error.message || "Failed to update status",
                    {
                        description:
                            result.error.description || "Please try again",
                    },
                );
                return;
            }
            await this.fetchDevices();
        } catch (error) {
            toast.error("Failed to update status", {
                description:
                    error instanceof Error
                        ? error.message
                        : "Please try again",
            });
        }
    }
}

export const deviceVM = new DeviceViewModel();
