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

    type Timesheets = {
        id: number;
        entered_by: string;
        work_description: string;
        type_of_work: "Running" | "Periodic" | "Irregular";
        category_of_work:
            | "Cleaning"
            | "Gardening/Pool"
            | "Maintenance"
            | "Supervision"
            | "Guest Service"
            | "Administration"
            | "Non Billable";
        villa_id: string;
        datetime_in: string;
        datetime_out: string;
        total_work_hour: number;
        remarks: string;
        approval: boolean;
        created_at?: Date;
    };

    type TimesheetDisplay = {
        id: number;
        name: string;
        staff_id: string;
        date_in: Date;
        date_out: Date;
        type_of_work: "Running" | "Periodic" | "Irregular";
        category_of_work:
            | "Cleaning"
            | "Gardening/Pool"
            | "Maintenance"
            | "Supervision"
            | "Guest Service"
            | "Administration"
            | "Non Billable";
        villa_name?: string;
        approval: string;
        approved_by?: string;
        approved_date?: Date;
        total_hours_work: number;
        remarks: string;
        created_at?: Date;
    };

    type TimesheetsInsert = {
        entered_by: string;
        work_description: string;
        type_of_work: "Running" | "Periodic" | "Irregular";
        category_of_work:
            | "Cleaning"
            | "Gardening/Pool"
            | "Maintenance"
            | "Supervision"
            | "Guest Service"
            | "Administration"
            | "Non Billable";
        villa_id: string;
        datetime_in: string;
        datetime_out: string;
        total_work_hour: number;
        remarks: string;
        approval: boolean | null; // Allow null for new entries
    };

    const categoryOfWork = [
        { label: "Cleaning", value: "Cleaning" },
        { label: "Gardening/Pool", value: "Gardening/Pool" },
        { label: "Maintenance", value: "Maintenance" },
        { label: "Security", value: "Security" },
        { label: "Other", value: "Other" },
    ];

    const typeOfWork = [
        { label: "Running", value: "Running" },
        { label: "Periodic", value: "Periodic" },
        { label: "Irregular", value: "Irregular" },
    ];

    const reportedBy = [
        { label: "Admin", value: "Admin" },
        { label: "Staff", value: "Staff" },
        { label: "Manager", value: "Manager" },
        { label: "Guest", value: "Guest" },
    ];

    let currentUserId: string | null = null;

    onMount(async () => {
        const {
            data: { user },
        } = await supabase.auth.getUser();

        currentUserId = user?.id ?? null;
    });

    type Villa = {
        id: string;
        villa_name: string;
    };

    let dataVilla: Villa[] = [];

    onMount(async () => {
        const { data, error } = await supabase
            .from("vb_villas")
            .select("id, villa_name");

        if (error) {
            console.error("Error fetching villas:", error);
        } else if (data) {
            dataVilla = data;
        }
    });

    let allRows: TimesheetDisplay[] = [];

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

    const columns: columns[] = [
        { key: "name", title: "Name" },
        { key: "staff_id", title: "Staff Report" },
        { key: "date_in", title: "Date In" },
        { key: "date_out", title: "Date Out" },
        { key: "type_of_work", title: "Type of Work" },
        { key: "category_of_work", title: "Category of Work" },
        { key: "approval", title: "Approval" },
        { key: "villa_name", title: "Villa Name" },
        { key: "approved_by", title: "Approved By" },
        { key: "approved_date", title: "Approved Date" },
        { key: "total_hours_work", title: "Total Hours Work" },
        { key: "remarks", title: "Remarks" },
        { key: "vacant", title: "Vacant" },
        { key: "created_at", title: "Created At" },
        { key: "actions", title: "Actions" },
    ];

    async function fetchTimeSheets(
        filter: string | null = null,
        searchTerm: string | null = null,
        sortColumn: string | null = "created_at",
        sortOrder: "asc" | "desc" = "desc",
        offset: number = 0,
        limit: number = 10,
    ) {
        let query = supabase
            .from("vb_timesheet")
            .select("*", { count: "exact" })
            .order(sortColumn || "created_at", {
                ascending: sortOrder === "asc",
            });
        if (filter) {
            query = query.eq("category_of_work", filter);
        }
        if (searchTerm) {
            query = query.ilike("work_description", `%${searchTerm}%`);
        }
        if (offset) {
            query = query.range(offset, offset + limit - 1);
        }
        if (limit) {
            query = query.limit(limit);
        }
        const { data: timesheet, error } = await query;
        if (error) {
            console.error("Error fetching timesheets:", error);
            return;
        }

        // Ambil semua villa_id unik dari issues
        const villaIds = [
            ...new Set(timesheet.map((i: Timesheets) => i.villa_id)),
        ];

        const { data: villas, error: villaError } = await supabase
            .from("vb_villas")
            .select("*")
            .in("id", villaIds);

        if (villaError) {
            console.error("Error fetching villas:", villaError);
            return;
        }

        let reportedBy: { label: string; value: string }[] = [];
        const { data: staffData, error: staffError } = await supabase
            .from("vb_employee")
            .select("id, employee_name");
        if (staffError) {
            console.error("Error fetching staff:", staffError);
        } else if (staffData) {
            reportedBy = staffData.map((s) => ({
                label: s.employee_name,
                value: s.id,
            }));
        }

        // Gabungkan data villa ke dalam setiap issue
        allRows = timesheet.map((issue: Timesheets) => {
            const villa = villas.find((v) => v.id === issue.villa_id);
            // Map entered_by to staff_id
            const staff = reportedBy.find((s) => s.value === issue.entered_by);

            return {
                id: issue.id,
                name: issue.work_description, // Map work_description to name
                staff_id: staff?.label, // Map entered_by to staff_id
                date_in: new Date(issue.datetime_in),
                date_out: new Date(issue.datetime_out),
                type_of_work: issue.type_of_work,
                category_of_work: issue.category_of_work,
                villa_name: villa ? villa.villa_name : "Unknown Villa",
                approval:
                    issue.approval == null
                        ? "PENDING"
                        : issue.approval
                          ? "APPROVED"
                          : "REJECTED", // or map as needed
                total_hours_work:
                    Math.abs(
                        new Date(issue.datetime_out).getTime() -
                            new Date(issue.datetime_in).getTime(),
                    ) /
                    (1000 * 60 * 60), // Convert milliseconds to hours
                remarks: issue.remarks,
                created_at: issue.created_at
                    ? new Date(issue.created_at)
                    : undefined,
            } as TimesheetDisplay;
        });
        // Sort the rows based on the sortColumn and sortOrder
    }
    let currentPage = 1;
    let rowsPerPage = 5;
    $: totalPages = Math.ceil(allRows.length / rowsPerPage);
    $: paginatedRows = allRows.slice(
        (currentPage - 1) * rowsPerPage,
        currentPage * rowsPerPage,
    );

    function goToPage(page: number) {
        if (page >= 1 && page <= totalPages) currentPage = page;
    }

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

    // Initialize the first page
    $: currentPage = 1;

    let showModal = false;
    let isEditing = false;
    let currentEditingId: string | null = null;
    let newIssue: Record<string, any> = {};
    const excludedKeys = ["id"];
    const formColumns = columns.filter(
        (col) => !excludedKeys.includes(col.key),
    );

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

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

        const formData = new FormData(event.target as HTMLFormElement);

        // Validate form data
        if (!validateForm(formData)) {
            console.error("Form validation failed");
            return;
        }

        if (isEditing && currentEditingId) {
            const { error } = await supabase
                .from("vb_issues")
                .update(newIssue)
                .eq("id", currentEditingId);

            if (error) {
                alert("Error updating issue: " + error.message);
                console.error("Error updating issue:", error);
                return;
            }
        } else {
            const TimesheetsInsert: TimesheetsInsert = {
                entered_by: formData.get("entered_by") as string,
                work_description: formData.get("work_description") as string,
                type_of_work: formData.get("type_of_work") as
                    | "Running"
                    | "Periodic"
                    | "Irregular",
                category_of_work: formData.get("category_of_work") as
                    | "Cleaning"
                    | "Gardening/Pool"
                    | "Maintenance"
                    | "Supervision"
                    | "Guest Service"
                    | "Administration"
                    | "Non Billable",
                villa_id: formData.get("villa_id") as string,
                datetime_in: formData.get("date_in") as string,
                datetime_out: formData.get("date_out") as string,
                total_work_hour: Math.abs(
                    new Date(formData.get("date_out") as string).getTime() -
                        new Date(formData.get("date_in") as string).getTime(),
                ),
                remarks: formData.get("remarks") as string,
                approval: null, // Default null
            };

            const { error } = await supabase
                .from("vb_timesheet")
                .insert([TimesheetsInsert]);
            if (error) {
                console.error("Error adding issue:", error);
                return;
            }
        }
        await fetchTimeSheets();
        showModal = false;
    }

    async function deleteTimesheet(id: string) {
        if (confirm("Are you sure you want to delete this issue?")) {
            const { error } = await supabase
                .from("vb_timesheet")
                .delete()
                .eq("id", id);
            if (error) {
                console.error("Error deleting issue:", error);
                return;
            }
            await fetchTimeSheets();
        }
    }

    export let formErrors = writable<{ [key: string]: string }>({});

    function validateForm(formData: FormData): boolean {
        const errors: { [key: string]: string } = {};
        const requiredFields = [
            "work_description",
            "type_of_work",
            "category_of_work",
            "villa_id",
            "date_in",
            "date_out",
            "remarks",
        ];

        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 updateApprovalStatus(
        id: string,
        status: string,
    ): Promise<void> {
        const approved = status === "true";
        const approved_by = currentUserId;
        const approved_date = new Date().toISOString();
        const { error } = await supabase
            .from("vb_timesheet")
            .update({
                approval: status,
                approved_by,
                approved_date,
            })
            .eq("id", id);

        if (error) {
            console.error("Error updating approval status:", error);
        } else {
            await fetchTimeSheets();
        }
    }
</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-lg font-semibold text-gray-800">
                🕒 Timesheet List
            </h2>
            <p class="text-sm text-gray-600">
                Manage and track timesheets for staff members.
            </p>
        </div>
        <div class="flex flex-col sm:flex-row sm:items-center gap-2">
            <input
                type="text"
                placeholder="🔍 Search by name..."
                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.toLowerCase();
                    fetchTimeSheets(null, searchTerm, "created_at", "desc");
                }}
            />
            <select
                class="border border-gray-300 focus:ring-2 focus:ring-blue-500 focus:outline-none px-4 py-2 rounded-xl text-sm w-48 transition"
                on:change={(e) => {
                    const filter = (e.target as HTMLSelectElement).value;
                    fetchTimeSheets(filter, null, null, "desc");
                }}
            >
                <option value="">All Issues</option>
                <option value="PROJECT">Project Issues</option>
                <option value="PURCHASE_ORDER">Purchase Order Issues</option>
            </select>
            <button
                class="bg-gray-200 text-gray-700 px-4 py-2 rounded-xl hover:bg-gray-300 text-sm transition"
                on:click={() =>
                    fetchTimeSheets(null, null, "created_at", "desc", 0, 10)}
            >
                🔄 Reset
            </button>
            <button
                class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 text-sm"
                on:click={() => openModal()}
            >
                ➕ Add Timesheet
            </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}
                        {#if col.key === "name"}
                            <th
                                class="sticky left-0 px-4 py-3 text-left font-semibold text-gray-700 uppercase tracking-wider whitespace-nowrap"
                                style="background-color: #f0f8ff; z-index: 10;"
                            >
                                {col.title}
                            </th>
                        {:else}
                            <th
                                class="px-4 py-3 text-left font-semibold text-gray-700 uppercase tracking-wider whitespace-nowrap"
                            >
                                {col.title}
                            </th>
                        {/if}
                    {/each}
                </tr>
            </thead>
            <tbody class="divide-y divide-gray-200 bg-white">
                {#each paginatedRows as row}
                    <tr class="hover:bg-gray-50 transition">
                        {#each columns as col}
                            {#if col.key === "name"}
                                <td
                                    class="sticky left-0 px-4 py-2 font-medium text-blue-600"
                                    style="background-color: #f0f8ff; cursor: pointer;"
                                >
                                    {row[col.key]}
                                </td>
                            {:else if col.key === "approval"}
                                <td class="px-4 py-2">
                                    <span
                                        class="inline-flex items-center gap-1 rounded px-2 py-1 text-xs font-medium
                                            {row[col.key] === 'APPROVED'
                                            ? 'bg-green-100 text-green-800'
                                            : 'bg-yellow-100 text-yellow-800'}"
                                    >
                                        {row[col.key]}
                                    </span>
                                    {#if row.approval === "PENDING"}
                                        <button
                                            class="ml-2 inline-flex items-center gap-1 rounded bg-green-600 px-3 py-1.5 text-white text-xs font-medium hover:bg-green-700"
                                            on:click={() =>
                                                updateApprovalStatus(
                                                    String(row.id),
                                                    "true",
                                                )}
                                        >
                                            ✅ Approve
                                        </button>
                                        <button
                                            class="ml-2 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={() =>
                                                updateApprovalStatus(
                                                    String(row.id),
                                                    "false",
                                                )}
                                        >
                                            ❌ Reject
                                        </button>
                                    {/if}
                                </td>
                            {:else if col.key === "approved_by"}
                                <td class="px-4 py-2">
                                    {row[col.key] || "Not Approved"}
                                </td>
                            {:else if col.key === "approved_date"}
                                <td class="px-4 py-2">
                                    {row[col.key] !== undefined
                                        ? new Date(
                                              row[col.key]!,
                                          ).toLocaleDateString()
                                        : "N/A"}
                                </td>
                            {:else if col.key === "total_hours_work"}
                                <td class="px-4 py-2">
                                    {row[col.key].toFixed(2)} hours
                                </td>
                            {:else if col.key === "created_at"}
                                <td class="px-4 py-2">
                                    {row[col.key] !== undefined
                                        ? new Date(
                                              row[col.key]!,
                                          ).toLocaleDateString()
                                        : "N/A"}
                                </td>
                            {:else if col.key === "villa_name"}
                                <td class="px-4 py-2">
                                    {row[col.key] || "Unknown Villa"}
                                </td>
                            {:else if col.key === "staff_id"}
                                <td class="px-4 py-2">
                                    {row[col.key] || "Unknown Staff"}
                                </td>
                            {:else if col.key === "remarks"}
                                <td class="px-4 py-2">
                                    {row[col.key] || "No remarks"}
                                </td>
                            {:else if col.key === "actions"}
                                <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={() =>
                                            deleteTimesheet(String(row.id))}
                                    >
                                        🗑️ Delete
                                    </button>
                                </td>
                            {:else}
                                <td class="px-4 py-2">
                                    {row[col.key as keyof TimesheetDisplay]}
                                </td>
                            {/if}
                        {/each}
                    </tr>
                {/each}
            </tbody>
        </table>
    </div>

    <!-- Pagination controls -->
    <div class="flex justify-between items-center text-sm">
        <div>
            Showing {(currentPage - 1) * rowsPerPage + 1}–
            {Math.min(currentPage * rowsPerPage, allRows.length)} of {allRows.length}
        </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={() => goToPage(currentPage - 1)}
                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={() => goToPage(currentPage + 1)}
                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={saveIssue}
            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 Issue" : "Add New Issue"}
            </h3>
            {#each formColumns as col}
                {#if col.key === "name"}
                    <div>
                        <label class="block text-sm font-medium mb-1">
                            {col.title}
                        </label>
                        <input
                            type="text"
                            name={col.key}
                            bind:value={newIssue[col.key]}
                            class="w-full border p-2 rounded {errorClass(
                                col.key,
                            )}"
                            required
                        />
                        {#if $formErrors[col.key]}
                            <p class="text-red-500 text-xs mt-1">
                                {$formErrors[col.key]}
                            </p>
                        {/if}
                    </div>
                {:else if col.key === "remarks"}
                    <div>
                        <label class="block text-sm font-medium mb-1">
                            {col.title}
                        </label>
                        <textarea
                            name={col.key}
                            bind:value={newIssue[col.key]}
                            class="w-full border p-2 rounded {errorClass(
                                col.key,
                            )}"
                            required
                        ></textarea>
                        {#if $formErrors[col.key]}
                            <p class="text-red-500 text-xs mt-1">
                                {$formErrors[col.key]}
                            </p>
                        {/if}
                    </div>
                {:else if col.key === "type_of_work" || col.key === "category_of_work"}
                    <div>
                        <label class="block text-sm font-medium mb-1">
                            {col.title}
                        </label>
                        <select
                            name={col.key}
                            bind:value={newIssue[col.key]}
                            class="w-full border p-2 rounded {errorClass(
                                col.key,
                            )}"
                            required
                        >
                            {#each col.key === "type_of_work" ? typeOfWork : categoryOfWork as option}
                                <option value={option.value}>
                                    {option.label}
                                </option>
                            {/each}
                        </select>
                        {#if $formErrors[col.key]}
                            <p class="text-red-500 text-xs mt-1">
                                {$formErrors[col.key]}
                            </p>
                        {/if}
                    </div>
                {:else if col.key === "villa_id"}
                    <div>
                        <label class="block text-sm font-medium mb-1">
                            {col.title}
                        </label>
                        <select
                            name={col.key}
                            bind:value={newIssue[col.key]}
                            class="w-full border p-
2 rounded {errorClass(col.key)}"
                            required
                        >
                            <option value="" disabled selected
                                >Select Villa</option
                            >
                            {#each dataVilla as villa}
                                <option value={villa.id}
                                    >{villa.villa_name}</option
                                >
                            {/each}
                        </select>
                        {#if $formErrors[col.key]}
                            <p class="text-red-500 text-xs mt-1">
                                {$formErrors[col.key]}
                            </p>
                        {/if}
                    </div>
                {:else if col.key === "date_in" || col.key === "date_out"}
                    <div>
                        <label class="block text-sm font-medium mb-1">
                            {col.title}
                        </label>
                        <input
                            type="datetime-local"
                            name={col.key}
                            bind:value={newIssue[col.key]}
                            class="w-full border p-2 rounded {errorClass(
                                col.key,
                            )}"
                            required
                        />
                        {#if $formErrors[col.key]}
                            <p class="text-red-500 text-xs mt-1">
                                {$formErrors[col.key]}
                            </p>
                        {/if}
                    </div>
                {:else if col.key === "entered_by"}
                    <div>
                        <label class="block text-sm font-medium mb-1">
                            {col.title}
                        </label>
                        <select
                            name={col.key}
                            bind:value={newIssue[col.key]}
                            class="w-full border p-2 rounded {errorClass(
                                col.key,
                            )}"
                            required
                        >
                            {#each reportedBy as option}
                                <option value={option.value}>
                                    {option.label}
                                </option>
                            {/each}
                        </select>
                        {#if $formErrors[col.key]}
                            <p class="text-red-500 text-xs mt-1">
                                {$formErrors[col.key]}
                            </p>
                        {/if}
                    </div>
                {:else}
                    <!-- Handle other fields if necessary -->
                {/if}
            {/each}
            <div>
                <label class="block text-sm font-medium mb-1">
                    Total Work Hour
                </label>
                <input
                    type="number"
                    name="total_work_hour"
                    bind:value={newIssue.total_work_hour}
                    class="w-full border p-2 rounded {errorClass(
                        'total_work_hour',
                    )}"
                    readonly
                />
                {#if $formErrors.total_work_hour}
                    <p class="text-red-500 text-xs mt-1">
                        {$formErrors.total_work_hour}
                    </p>
                {/if}
            </div>
            <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"
                    on:click={() => (showModal = false)}
                >
                    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}
