<script lang="ts">
    import { supabase } from "$lib/supabaseClient";
    import { onMount } from "svelte";
    import { writable } from "svelte/store";

    const roleUser = [
        { label: "IT", value: "it" },
        { label: "Guest", value: "guest" },
        ,
        { label: "Accounting", value: "accounting" },
        { label: "GA", value: "ga" },
        { label: "HR", value: "hr" },
        { label: "S & M", value: "s&m" },
        { label: "Office", value: "office" },
        { label: "HM", value: "hm" },
        { label: "VM", value: "vm" },
    ];

    type User = {
        id: string;
        email: string;
        password: string; // Note: Passwords should not be stored in plain text
        role: string;
        nip: string;
        full_name: string;
        phone: string;
        address: string;
        profile_picture: string;
        last_login: string;
        is_active: boolean;
        is_verified: boolean;
        is_deleted: boolean;
        last_updated: string;
        last_updated_by: string;
        created_by: string;
        created_at: string;
    };

    let allRows: User[] = [];
    let offset = 0;
    let limit = 10;
    let totalItems = 0;
    export let formErrors = writable<{ [key: string]: string }>({});

    type columns = {
        key: string;
        title: string;
    };

    let columns: columns[] = [
        { key: "no", title: "No. " },
        { key: "email", title: "Email" },
        { key: "password", title: "Password" },
        { key: "role", title: "Role" },
        { key: "nip", title: "NIP" },
        { key: "full_name", title: "Full Name" },
        { key: "phone", title: "Phone" },
        { key: "address", title: "Address" },
        { key: "profile_picture", title: "Profile Picture" },
        { key: "last_login", title: "Last Login" },
        { key: "is_active", title: "Active" },
        { key: "is_verified", title: "Verified" },
        { key: "last_updated", title: "Last Updated" },
        { key: "last_updated_by", title: "Last Updated By" },
        { key: "created_by", title: "Created By" },
        { key: "created_at", title: "Created At" },
    ];

    async function fetchData(
        filter: string = "",
        sortBy: string = "created_at",
        sortOrder: "asc" | "desc" = "desc",
        search: string = "",
        offset: number = 0,
        limit: number = 10,
    ) {
        try {
            const { data, error, count } = await supabase
                .from("vb_users")
                .select("*", { count: "exact" })
                .ilike("email", `%${search}%`)
                .or(`full_name.ilike.%${search}%,nip.ilike.%${search}%`)
                .order(sortBy, { ascending: sortOrder === "asc" })
                .range(offset, offset + limit - 1);

            if (error) {
                throw error;
            }

            allRows = data as User[];
            totalItems = count || 0;
        } catch (error) {
            console.error("Error fetching data:", error);
        }
    }

    onMount(() => {
        fetchData();
    });

    let currentPage = offset + 1;
    let rowsPerPage = 10;
    $: totalPages = Math.ceil(totalItems / rowsPerPage);

    function nextPage() {
        if (currentPage < totalPages) {
            currentPage += 1;
            offset = (currentPage - 1) * rowsPerPage;
            fetchData("", "created_at", "desc", "", offset, rowsPerPage);
        }
    }

    function prevPage() {
        if (currentPage > 1) {
            currentPage -= 1;
            offset = (currentPage - 1) * rowsPerPage;
            fetchData("", "created_at", "desc", "", offset, rowsPerPage);
        }
    }

    function goToPage(page: number) {
        if (page >= 1 && page <= totalPages) {
            currentPage = page;
            offset = (currentPage - 1) * rowsPerPage;
            fetchData("", "created_at", "desc", "", offset, rowsPerPage);
        }
    }

    let showModal = false;
    let isEditing = false;
    let currentEditingId: string | null = null;
    let newUser: Record<string, any> = {};
    const excludedKeys = [
        "id",
        "last_updated",
        "last_updated_by",
        "created_by",
        "created_at",
        "last_login",
        "deleted",
        "no",
    ];

    const formColumns = columns.filter(
        (col) => !excludedKeys.includes(col.key),
    );

    let selectedFile: File | null = null;
    let imagePreviewUrl: string | null = null;

    function handleFileChange(event: Event) {
        const input = event.target as HTMLInputElement;
        if (input.files && input.files.length > 0) {
            selectedFile = input.files[0];
            imagePreviewUrl = URL.createObjectURL(selectedFile);
        }
    }

    // function get public URL for image supabase
    async function getPublicUrl(path: string): Promise<string> {
        const { data } = supabase.storage.from("villabugis").getPublicUrl(path);
        return data.publicUrl;
    }

    function openModal(user?: Record<string, any>) {
        if (user) {
            isEditing = true;
            currentEditingId = user.id;
            newUser = { ...user };
        } else {
            isEditing = false;
            currentEditingId = null;
            newUser = {};
        }
        showModal = true;
    }

    function validateForm(formData: FormData): boolean {
        const errors: { [key: string]: string } = {};
        const requiredFields = [
            "email",
            "role",
            "nip",
            "full_name",
            "phone",
            "address",
        ];

        requiredFields.forEach((field) => {
            if (!formData.get(field) || formData.get(field) === "") {
                errors[field] = `${field.replace(/_/g, " ")} is required.`;
            }
        });

        formErrors.set(errors);
        return Object.keys(errors).length === 0;
    }

    function errorClass(field: string): string {
        return $formErrors[field] ? "border-red-500" : "border";
    }

    async function saveUser(event: Event) {
        event.preventDefault();

        const formData = new FormData(event.target as HTMLFormElement);
        if (!validateForm(formData)) {
            console.error("Form validation failed:", $formErrors);
            return;
        }

        if (selectedFile) {
            // Upload file to Supabase Storage
            const { data, error } = await supabase.storage
                .from("villabugis")
                .upload(`profile_pictures/${selectedFile.name}`, selectedFile);

            if (error) {
                console.error("Error uploading file:", error);
                return;
            }
            newUser.profile_picture = data.path; // Store the path in newUser
        }

        try {
            if (isEditing && currentEditingId) {
                // Update user in 'users' table
                const { error } = await supabase
                    .from("vb_users")
                    .update(newUser)
                    .eq("id", currentEditingId);

                if (error) throw error;
            } else {
                // valid password tidak boleh kosong
                if (!newUser.password || newUser.password.trim() === "") {
                    alert("Password is required for new users.");
                    return;
                }

                // 1. Create user in Supabase Auth
                const { data: authUser, error: authError } =
                    await supabase.auth.signUp({
                        email: newUser.email,
                        password: newUser.password, // Use NIP as password or fallback
                    });

                if (authError) throw authError;

                // 2. Insert user in 'users' table with auth user id
                const { error } = await supabase
                    .from("vb_users")
                    .insert([{ ...newUser, id: authUser.user?.id }]);
                if (error) throw error;
            }
            showModal = false;
            fetchData();
        } catch (error) {
            console.error("Error saving user:", error);
        }
    }

    async function deleteUser(id: string) {
        if (confirm("Are you sure you want to delete this user?")) {
            try {
                const { error } = await supabase
                    .from("vb_users")
                    .delete()
                    .eq("id", id);
                if (error) throw error;
                fetchData();
            } catch (error) {
                console.error("Error deleting user:", error);
            }
        }
    }

    function closeModal() {
        showModal = false;
        isEditing = false;
        currentEditingId = null;
        newUser = {};
        formErrors.set({});
    }

    $: if (showModal) {
        document.body.style.overflow = "hidden";
    } else {
        document.body.style.overflow = "auto";
    }

    $: if (isEditing && currentEditingId) {
        const user = allRows.find((u) => u.id === currentEditingId);
        if (user) {
            newUser = { ...user };
        }
    }

    $: if (!isEditing) {
        newUser = {
            email: "",
            role: "user",
            nip: "",
            full_name: "",
            phone: "",
            address: "",
            profile_picture: "",
            is_active: true,
            is_verified: false,
            is_deleted: false,
        };
    }
</script>

<div>
    <div
        class="p-6 bg-white shadow-md rounded-2xl mb-4 flex flex-col sm:flex-row sm:justify-between sm:items-center gap-4"
    >
        <div>
            <h2 class="text-xl font-semibold text-gray-800">👤 User List</h2>
            <p class="text-sm text-gray-500">
                Manage and view all users in the system.
            </p>
        </div>

        <div class="flex flex-col sm:flex-row sm:items-center gap-2">
            <input
                type="text"
                placeholder="🔍 Search by email, name, or NIP..."
                class="border border-gray-300 focus:ring-2 focus:ring-blue-500 focus:outline-none px-4 py-2 rounded-xl text-sm w-64 transition"
                on:input={(e) => {
                    const searchTerm = (e.target as HTMLInputElement).value;
                    fetchData(
                        "",
                        "created_at",
                        "desc",
                        searchTerm,
                        0,
                        rowsPerPage,
                    );
                }}
            />
            <button
                class="bg-gray-200 text-gray-700 px-4 py-2 rounded-xl hover:bg-gray-300 text-sm transition"
                on:click={() =>
                    fetchData("", "created_at", "desc", "", 0, rowsPerPage)}
            >
                🔄 Reset
            </button>
            <button
                class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 text-sm"
                on:click={() => openModal()}
            >
                ➕ Add User
            </button>
        </div>
    </div>
    <div class="overflow-x-auto rounded-lg shadow mb-4">
        <table class="min-w-[1000px] divide-y divide-gray-200 text-sm w-max">
            <thead class="bg-gray-100">
                <tr>
                    {#each columns as col}
                        <th
                            class="px-4 py-3 text-left font-semibold text-gray-700 uppercase tracking-wider whitespace-nowrap"
                        >
                            {col.title}
                        </th>
                    {/each}
                    <th
                        class="px-4 py-3 text-left font-semibold text-gray-700 uppercase tracking-wider whitespace-nowrap"
                    >
                        Actions
                    </th>
                </tr>
            </thead>
            {#if allRows.length === 0}
                <tbody>
                    <tr>
                        <td
                            colspan={columns.length + 1}
                            class="px-4 py-12 text-center text-gray-400 bg-gray-50"
                        >
                            <div
                                class="flex flex-col items-center justify-center space-y-2"
                            >
                                <svg
                                    xmlns="http://www.w3.org/2000/svg"
                                    class="h-10 w-10 text-gray-300 mb-2"
                                    fill="none"
                                    viewBox="0 0 24 24"
                                    stroke="currentColor"
                                >
                                    <path
                                        stroke-linecap="round"
                                        stroke-linejoin="round"
                                        stroke-width="2"
                                        d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6 6 0 10-12 0v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"
                                    />
                                </svg>
                                <span class="text-lg font-semibold"
                                    >No users found</span
                                >
                                <span class="text-sm text-gray-400"
                                    >Try adjusting your search or add a new
                                    user.</span
                                >
                            </div>
                        </td>
                    </tr>
                </tbody>
            {:else}
                <tbody class="divide-y divide-gray-200 bg-white">
                    {#each allRows as row, i}
                        <tr class="hover:bg-gray-50 transition">
                            {#each columns as col}
                                <td class="px-4 py-2 text-gray-700">
                                    {#if col.key === "no"}
                                        {offset + i + 1}
                                    {:else if col.key === "is_active" || col.key === "is_verified" || col.key === "is_deleted"}
                                        {(row as Record<string, any>)[col.key]
                                            ? "✅"
                                            : "❌"}
                                    {:else if col.key === "profile_picture"}
                                        {#if row.profile_picture}
                                            {#if typeof row[col.key] === "string" && row[col.key]}
                                                {#await getPublicUrl(row[col.key] as string) then publicUrl}
                                                    <a
                                                        href={publicUrl}
                                                        target="_blank"
                                                        class="text-blue-600 hover:underline"
                                                        >View Picture</a
                                                    >
                                                {:catch}
                                                    <span class="text-red-500"
                                                        >Error loading image</span
                                                    >
                                                {/await}
                                            {:else}
                                                No Picture
                                            {/if}
                                        {/if}
                                    {:else}
                                        {(row as Record<string, any>)[col.key]}
                                    {/if}
                                </td>
                            {/each}
                            <td class="px-4 py-2">
                                <button
                                    class="inline-flex items-center gap-1 rounded bg-blue-600 px-3 py-1.5 text-white text-xs font-medium hover:bg-blue-700"
                                    on:click={() => openModal(row)}
                                >
                                    ✏️ Edit
                                </button>
                                <button
                                    class="inline-flex items-center gap-1 rounded bg-red-600 px-3 py-1.5 text-white text-xs font-medium hover:bg-red-700"
                                    on:click={() => deleteUser(row.id)}
                                >
                                    🗑️ Delete
                                </button>
                            </td>
                        </tr>
                    {/each}
                </tbody>
            {/if}
        </table>
    </div>

    <!-- Pagination controls -->
    <div class="flex justify-between items-center text-sm">
        <div>
            Showing {offset + 1}–{Math.min(offset + rowsPerPage, totalItems)} of
            {totalItems}
        </div>
        <div class="space-x-2">
            <button
                class="px-3 py-1 rounded border border-gray-300 bg-white hover:bg-gray-100 disabled:opacity-50"
                on:click={prevPage}
                disabled={currentPage === 1}
            >
                Previous
            </button>
            {#each Array(totalPages)
                .fill(0)
                .map((_, i) => i + 1) as page}
                <button
                    class="px-3 py-1 rounded border text-sm
                        {currentPage === page
                        ? 'bg-blue-600 text-white border-blue-600'
                        : 'bg-white border-gray-300 hover:bg-gray-100'}"
                    on:click={() => goToPage(page)}
                >
                    {page}
                </button>
            {/each}
            <button
                class="px-3 py-1 rounded border border-gray-300 bg-white hover:bg-gray-100 disabled:opacity-50"
                on:click={nextPage}
                disabled={currentPage === totalPages}
            >
                Next
            </button>
        </div>
    </div>
</div>

<!-- Modal -->
{#if showModal}
    <div
        class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"
    >
        <form
            on:submit|preventDefault={saveUser}
            class="bg-white p-6 rounded shadow-lg w-[600px] max-h-[90vh] overflow-y-auto space-y-4"
        >
            <h3 class="text-lg font-semibold">
                {isEditing ? "Edit User" : "Add New User"}
            </h3>
            {#each formColumns as col}
                <div class="space-y-1">
                    <label class="block text-sm font-medium text-gray-700">
                        {col.title}
                    </label>
                    {#if col.key === "role"}
                        <select
                            name="role"
                            class="w-full border px-3 py-2 rounded {errorClass(
                                'role',
                            )}"
                            bind:value={newUser.role}
                        >
                            <option value="" disabled>Select Role</option>
                            {#each roleUser as role}
                                {#if role}
                                    <option value={role.value}
                                        >{role.label}</option
                                    >
                                {/if}
                            {/each}
                        </select>
                        {#if $formErrors.role}
                            <p class="text-red-500 text-xs">
                                {$formErrors.role}
                            </p>
                        {/if}
                    {:else if col.key === "email"}
                        <input
                            name="email"
                            class="w-full border px-3 py-2 rounded {errorClass(
                                'email',
                            )}"
                            type="email"
                            bind:value={newUser.email}
                            placeholder="Email"
                        />
                        {#if $formErrors.email}
                            <p class="text-red-500 text-xs">
                                {$formErrors.email}
                            </p>
                        {/if}
                    {:else if col.key === "password"}
                        <input
                            name="password"
                            class="w-full border px-3 py-2 rounded {errorClass(
                                'password',
                            )}"
                            type="password"
                            bind:value={newUser.password}
                            placeholder="Password"
                        />
                        {#if $formErrors.password}
                            <p class="text-red-500 text-xs">
                                {$formErrors.password}
                            </p>
                        {/if}
                    {:else if col.key === "phone"}
                        <input
                            name="phone"
                            class="w-full border px-3 py-2 rounded {errorClass(
                                'phone',
                            )}"
                            type="tel"
                            bind:value={newUser.phone}
                            placeholder="Phone Number"
                        />
                        {#if $formErrors.phone}
                            <p class="text-red-500 text-xs">
                                {$formErrors.phone}
                            </p>
                        {/if}
                    {:else if col.key === "profile_picture"}
                        <div class="space-y-1">
                            <input
                                type="file"
                                accept="image/*"
                                class="w-full border px-3 py-2 rounded"
                                on:change={handleFileChange}
                            />
                            {#if imagePreviewUrl}
                                <img
                                    src={imagePreviewUrl}
                                    alt="Preview"
                                    class="mt-2 max-h-48 rounded border"
                                />
                                <p class="text-xs text-gray-500">
                                    Preview of selected image
                                </p>
                            {:else if newUser.profile_picture}
                                {#await getPublicUrl(newUser.profile_picture) then publicUrl}
                                    <img
                                        src={publicUrl}
                                        alt="Profile Picture"
                                        class="mt-2 max-h-48 rounded border"
                                    />
                                {:catch}
                                    <span class="text-red-500"
                                        >Error loading image</span
                                    >
                                {/await}
                            {:else}
                                <span class="text-gray-400">No Image</span>
                            {/if}
                        </div>
                    {:else if col.key === "is_active" || col.key === "is_verified" || col.key === "is_deleted"}
                        <select
                            name={col.key}
                            class="w-full border px-3 py-2 rounded"
                            bind:value={newUser[col.key]}
                        >
                            <option value={true}>Yes</option>
                            <option value={false}>No</option>
                        </select>
                    {:else}
                        <input
                            name={col.key}
                            class="w-full border px-3 py-2 rounded {errorClass(
                                col.key,
                            )}"
                            type="text"
                            bind:value={newUser[col.key]}
                            placeholder={col.title}
                        />
                        {#if $formErrors[col.key]}
                            <p class="text-red-500 text-xs">
                                {$formErrors[col.key]}
                            </p>
                        {/if}
                    {/if}
                </div>
            {/each}
            <div class="flex justify-end gap-2 mt-4">
                <button
                    class="px-4 py-2 text-sm rounded bg-gray-200 hover:bg-gray-300"
                    type="button"
                    on:click={closeModal}
                >
                    Cancel
                </button>
                <button
                    class="px-4 py-2 text-sm rounded bg-blue-600 text-white hover:bg-blue-700"
                    type="submit"
                >
                    Save
                </button>
            </div>
        </form>
    </div>
{/if}
