<template>
    <v-card>
        <v-card-title class="d-flex align-center ga-3 flex-wrap">
            <span>Organization Timeline</span>
            <v-spacer />
            <div class="filters-row">
                <v-select
                    v-model="reportType"
                    :items="reportTypeOptions"
                    item-title="label"
                    item-value="value"
                    label="Report"
                    density="compact"
                    variant="outlined"
                    hide-details
                    class="filter-report"
                />
                <v-autocomplete
                    v-model="selectedUserId"
                    v-model:search="memberSearch"
                    :items="memberOptions"
                    item-title="label"
                    item-value="id"
                    label="Member"
                    density="compact"
                    variant="outlined"
                    hide-details
                    clearable
                    class="filter-member"
                    :loading="membersLoading"
                    :disabled="!organization"
                    no-filter
                />
                <v-menu
                    v-if="reportType === 'daily'"
                    v-model="dailyMenu"
                    :close-on-content-click="false"
                    transition="scale-transition"
                    offset-y
                >
                    <template #activator="{ props }">
                        <v-text-field
                            v-bind="props"
                            :model-value="formattedSelectedDate"
                            label="Date"
                            readonly
                            density="compact"
                            variant="outlined"
                            hide-details
                            class="filter-date"
                        />
                    </template>
                    <v-date-picker
                        v-model="selectedDate"
                        show-adjacent-months
                        first-day-of-week="1"
                        @update:modelValue="dailyMenu = false"
                    />
                </v-menu>
                <v-menu
                    v-else
                    v-model="menu"
                    :close-on-content-click="false"
                    transition="scale-transition"
                    offset-y
                >
                    <template #activator="{ props }">
                        <v-text-field
                            v-bind="props"
                            :model-value="formattedWeek"
                            label="Week"
                            readonly
                            density="compact"
                            variant="outlined"
                            hide-details
                            class="filter-week"
                        />
                    </template>

                    <v-date-picker
                        v-model="selectedWeekDate"
                        show-adjacent-months
                        first-day-of-week="1"
                        @update:modelValue="handleWeekSelect"
                    >
                        <template #day="{ item, props }">
                            <div
                                v-bind="props"
                                class="custom-day"
                                :class="getDayClass(item.date)"
                            >
                                {{ formatDay(item.date) }}
                            </div>
                        </template>
                    </v-date-picker>
                </v-menu>
            </div>
        </v-card-title>
        <v-data-table-server
            :headers="computedHeaders"
            :items="normalizedItems"
            :items-per-page-options="[10, 20, 50]"
            :items-length="totalItems"
            :items-per-page="perPage"
            v-model:page="page"
            v-model:items-per-page="perPage"
            :loading="loading"
            item-value="userId"
            density="comfortable"
        >
            <template #item.totalTrackedSeconds="{ item }">{{ formatDuration(item.totalTrackedSeconds) }}</template>
            <template #item.startTime="{ item }">{{ formatTime(item.startTime) }}</template>
            <template #item.endTime="{ item }">{{ formatTime(item.endTime) }}</template>

            <template
                v-for="day in days"
                :key="`col-${day.date}`"
                #[`item.day_${day.date}`]="{ item }"
            >
                <div class="day-cell">
                    <v-tooltip location="top">
                        <template #activator="{ props }">
                            <div
                                v-bind="props"
                                class="bar"
                                @click="openUserDayActivities(item.userId, day.date)"
                            >
                                <div
                                    class="bar-active"
                                    :style="{ width: getActivePercent(item, day.date) + '%' }"
                                />
                                <div
                                    class="bar-idle"
                                    :style="{ width: getIdlePercent(item, day.date) + '%' }"
                                />
                            </div>
                        </template>
                        <div class="bar-tooltip">
                            <div><strong>Active:</strong> {{ formatDuration(getDay(item, day.date).active) }}</div>
                            <div><strong>Idle:</strong> {{ formatDuration(getDay(item, day.date).idle) }}</div>
                        </div>
                    </v-tooltip>
                    <div class="total">
                        {{ formatDuration(getDay(item, day.date).tracked) }}
                    </div>
                </div>
            </template>
        </v-data-table-server>
    </v-card>
</template>

<script setup>
import axios from "axios"
import { computed, onMounted, ref, watch } from "vue"
import { apiEndpoints } from "../apiEndpoints"
import { useRoute, useRouter } from "vue-router"
import { useStore } from "vuex"

const selectedWeekDate = ref(null)

const store = useStore()
const route = useRoute()
const router = useRouter()

const organization = computed(() => store.getters["auth/organization"])

const page = ref(1)
const perPage = ref(10)
const totalItems = ref(0)
const weekRange = ref([])
const menu = ref(false)
const dailyMenu = ref(false)

const selectedUserId = ref(route.query.user ? Number(route.query.user) : null)
const memberSearch = ref("")
const memberOptions = ref([])
const membersLoading = ref(false)
const selectedDate = ref(route.query.date || formatAsYmd(new Date()))
const reportType = ref(route.query.type || "weekly")
const reportTypeOptions = [
    { label: "Daily", value: "daily" },
    { label: "Weekly", value: "weekly" }
]

const timelineData = ref({
    data: [],
    meta: {},
    reportType: "daily",
    week: { days: [] }
})
const loading = ref(false)

const days = computed(() => normalizedItems.value[0]?.days || [])

const formattedWeek = computed(() => {
    if (!weekRange.value || weekRange.value.length < 2) return ""

    const start = weekRange.value[0]
    const end = weekRange.value[1]

    return `${formatDate(start)} - ${formatDate(end)}`
})

const formattedSelectedDate = computed(() => selectedDate.value ? formatDate(selectedDate.value) : "")

function parseDateInput(date) {
    if (!date) return null

    if (date instanceof Date) {
        return isNaN(date.getTime()) ? null : new Date(date.getFullYear(), date.getMonth(), date.getDate())
    }

    if (typeof date === "string" && /^\d{4}-\d{2}-\d{2}$/.test(date)) {
        const [year, month, day] = date.split("-").map(Number)
        const parsed = new Date(year, month - 1, day)
        return isNaN(parsed.getTime()) ? null : parsed
    }

    const parsed = new Date(date)
    return isNaN(parsed.getTime()) ? null : new Date(parsed.getFullYear(), parsed.getMonth(), parsed.getDate())
}

function formatAsYmd(date) {
    const year = date.getFullYear()
    const month = `${date.getMonth() + 1}`.padStart(2, "0")
    const day = `${date.getDate()}`.padStart(2, "0")
    return `${year}-${month}-${day}`
}

function formatDay(date) {
    const parsed = parseDateInput(date)
    return parsed ? parsed.getDate() : ""
}

function formatDate(date) {
    const parsed = parseDateInput(date)
    if (!parsed) return ""

    return parsed.toLocaleDateString("en-IN", {
        day: "2-digit",
        month: "short"
    })
}

function handleWeekSelect(val) {
    if (!val) return

    const range = getWeekRange(val)
    weekRange.value = [range.start, range.end]
    selectedWeekDate.value = range.start
    selectedDate.value = range.start

    menu.value = false
    page.value = 1

    fetchTimeline()
}

function formatISO(date) {
    const parsed = parseDateInput(date)
    return parsed ? formatAsYmd(parsed) : null
}

function getDayClass(date) {
    if (!weekRange.value || weekRange.value.length < 2) return ""

    const current = formatISO(date)
    if (!current) return ""

    const start = weekRange.value[0]
    const end = weekRange.value[1]

    if (current === start || current === end) {
        return "day-boundary"
    }

    if (current > start && current < end) {
        return "day-in-range"
    }

    return ""
}

function getActivePercent(item, date) {
    const d = getDay(item, date)
    if (!d.tracked) return 0
    return (d.active / d.tracked) * 100
}

function getIdlePercent(item, date) {
    const d = getDay(item, date)
    if (!d.tracked || d.idle <= 0) return 0

    return (d.idle / d.tracked) * 100
}

function getDay(item, date) {
    return item.days.find(d => d.date === date) || {
        tracked: 0,
        active: 0,
        idle: 0
    }
}

const computedHeaders = computed(() => {
    const items = timelineData.value?.data || []
    if (!items.length) {
        return [{ title: "User", key: "displayName" }]
    }

    const firstItem = items[0]
    const dayCount = firstItem.days.length

    return [
        { title: "User", key: "displayName", width: "200px" },
        ...firstItem.days.map((d) => ({
            title: d.label,
            key: `day_${d.date}`,
            sortable: false,
            width: `calc((100% - 200px) / ${dayCount})`
        }))
    ]
})

const normalizedItems = computed(() => timelineData.value?.data || [])

watch(
    [organization, selectedDate, reportType, selectedUserId],
    async () => {
        const normalizedDate = formatAsYmd(parseDateInput(selectedDate.value) ?? new Date())
        if (selectedDate.value !== normalizedDate) {
            selectedDate.value = normalizedDate
            return
        }

        if (reportType.value === "weekly") {
            const baseDate = selectedDate.value || (typeof route.query.date === "string" ? route.query.date : formatAsYmd(new Date()))
            const range = getWeekRange(baseDate)
            weekRange.value = [range.start, range.end]
            selectedWeekDate.value = range.start
            if (selectedDate.value !== range.start) {
                selectedDate.value = range.start
                return
            }
        }

        router.replace({
            query: {
                org: organization.value.id,
                date: reportType.value === "daily"
                    ? normalizedDate
                    : weekRange.value[0],
                type: reportType.value,
                user: selectedUserId.value || undefined
            }
        })

        page.value = 1
        await fetchTimeline()
    }
)

watch([page, perPage], async () => {
    await fetchTimeline()
})

function getWeekRange(date) {
    const d = parseDateInput(date)
    if (!d) {
        const today = new Date()
        return { start: formatAsYmd(today), end: formatAsYmd(today) }
    }

    const day = d.getDay() || 7
    const start = new Date(d.getFullYear(), d.getMonth(), d.getDate())
    start.setDate(start.getDate() - day + 1)

    const end = new Date(start)
    end.setDate(start.getDate() + 6)

    return {
        start: formatAsYmd(start),
        end: formatAsYmd(end)
    }
}

async function fetchMembers(search = "") {
    membersLoading.value = true
    try {
        const { data } = await axios.get(apiEndpoints.organizations.members(organization.value.id), {
            params: {
                page: 1,
                perPage: 20,
                search: search || undefined
            }
        })

        const items = data?.data || []
        memberOptions.value = items.map((member) => ({
            id: Number(member.id),
            label: member.displayName || member.email || `User ${member.id}`
        }))

        if (selectedUserId.value && !memberOptions.value.some((member) => member.id === Number(selectedUserId.value))) {
            const matched = items.find((member) => Number(member.id) === Number(selectedUserId.value))
            if (matched) {
                memberOptions.value.unshift({
                    id: Number(matched.id),
                    label: matched.displayName || matched.email || `User ${matched.id}`
                })
            }
        }
    } finally {
        membersLoading.value = false
    }
}

async function fetchTimeline() {
    if (reportType.value === "daily" && !selectedDate.value) return
    if (reportType.value === "weekly" && (!weekRange.value || weekRange.value.length < 2)) return

    loading.value = true
    try {
        const { data } = await axios.get(apiEndpoints.organizations.timeline(organization.value.id), {
            params: {
                date: reportType.value === "daily" ? selectedDate.value : weekRange.value[0],
                reportType: reportType.value,
                userId: selectedUserId.value || undefined,
                page: page.value,
                perPage: perPage.value
            }
        })
        timelineData.value = data || { data: [], meta: {} }
        totalItems.value = data?.meta?.pagination?.totalItems || 0
    } finally {
        loading.value = false
    }
}

function openUserDayActivities(userId, date) {
    if (!userId || !date) return

    router.push({
        name: "activities",
        query: {
            user: String(userId),
            date
        }
    })
}

function formatDuration(seconds) {
    const totalSeconds = Math.max(0, Number(seconds) || 0)
    const hours = Math.floor(totalSeconds / 3600)
    const minutes = Math.floor((totalSeconds % 3600) / 60)
    return `${hours}h ${minutes}m`
}

function formatTime(value) {
    if (!value) return "-"
    return new Intl.DateTimeFormat(undefined, { timeStyle: "short" }).format(new Date(value))
}

onMounted(async () => {
    await fetchMembers(memberSearch.value)

    if (reportType.value === "weekly") {
        const initialDate = typeof route.query.date === "string" ? route.query.date : formatAsYmd(new Date())
        const range = getWeekRange(initialDate)
        weekRange.value = [range.start, range.end]
        selectedWeekDate.value = range.start
    }

    await fetchTimeline()
})

watch(memberSearch, async (value) => {
    await fetchMembers(typeof value === "string" ? value.trim() : "")
})
</script>

<style scoped>
.filters-row {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
}

.filter-report {
    width: 150px;
}

.filter-member {
    min-width: 220px;
    width: 260px;
}

.filter-date,
.filter-week {
    width: 220px;
}

.bar {
    display: flex;
    width: 100%;
    height: 12px;
    background: #eee;
    border-radius: 8px;
    overflow: hidden;
    margin-bottom: 8px;
    cursor: pointer;
}

.bar-active {
    background: #4caf50;
    height: 100%;
}

.bar-idle {
    background: #ffc107;
}

.v-data-table table {
    table-layout: fixed;
    width: 100%;
}

.day-cell {
    display: flex;
    flex-direction: column;
    font-size: 12px;
    overflow: hidden;
    padding: 8px 6px;
}

.day-cell .total {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    font-weight: 600;
}

.bar-tooltip {
    font-size: 12px;
    line-height: 1.4;
}

.custom-day {
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
}

.day-boundary {
    background: #1976d2;
    color: white;
}

.day-in-range {
    background: rgba(25, 118, 210, 0.2);
    border-radius: 0;
}
</style>
