import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import type { GroupPublic as Household, GroupUpdate } from '@/types/group'
import type { UserPublic } from '@/types/user'
import { groupService } from '@/services/groupService'
import { useSocket } from '@/composables/useSocket'
import { useOptimisticUpdates } from '@/composables/useOptimisticUpdates'

export const useHouseholdStore = defineStore('household', () => {
    // ---- State ----
    const household = ref<Household | null>(null)
    const isLoading = ref(false)
    const error = ref<string | null>(null)

    // Real-time member activity tracking
    const memberActivity = ref<Record<number, { lastSeen: Date, isActive: boolean }>>({})
    const inviteCodes = ref<string[]>([])
    const pendingInvites = ref<{ code: string, expiresAt: Date, usageCount: number }[]>([])

    // Real-time socket
    const { on, off, emit } = useSocket()

    // Optimistic updates
    const { mutate, rollback } = useOptimisticUpdates<Household>([])

    // ---- Enhanced Getters ----
    const householdName = computed(() => household.value?.name || '')
    const members = computed(() => household.value?.members || [])
    const memberCount = computed(() => members.value.length)
    const isMember = computed(() => household.value?.is_member ?? false)

    // Activity-based member insights
    const activeMembers = computed(() =>
        members.value.filter(member => memberActivity.value[member.id]?.isActive)
    )

    const inactiveMembers = computed(() =>
        members.value.filter(member => !memberActivity.value[member.id]?.isActive)
    )

    // Household health metrics
    const householdHealth = computed(() => {
        const totalMembers = memberCount.value
        const activeCount = activeMembers.value.length
        const healthScore = totalMembers > 0 ? (activeCount / totalMembers) * 100 : 0

        return {
            score: Math.round(healthScore),
            status: healthScore > 75 ? 'excellent' : healthScore > 50 ? 'good' : 'needs-attention',
            activeMembers: activeCount,
            totalMembers
        }
    })

    // ---- Enhanced Socket Handlers ----
    function handleUpdated(payload: { household: Household }) {
        if (household.value && payload.household.id === household.value.id) {
            // Direct update for socket events
            household.value = payload.household
        }
    }

    function handleMemberJoined(payload: { householdId: number; member: UserPublic }) {
        if (household.value && payload.householdId === household.value.id) {
            household.value.members.push(payload.member)
            // Track new member activity
            memberActivity.value[payload.member.id] = {
                lastSeen: new Date(),
                isActive: true
            }
        }
    }

    function handleMemberLeft(payload: { householdId: number; userId: number }) {
        if (household.value && payload.householdId === household.value.id) {
            household.value.members = household.value.members.filter(m => m.id !== payload.userId)
            delete memberActivity.value[payload.userId]
        }
    }

    function handleMemberActivity(payload: { userId: number; lastSeen: string; isActive: boolean }) {
        memberActivity.value[payload.userId] = {
            lastSeen: new Date(payload.lastSeen),
            isActive: payload.isActive
        }
    }

    function handleInviteCreated(payload: { code: string; expiresAt: string }) {
        pendingInvites.value.push({
            code: payload.code,
            expiresAt: new Date(payload.expiresAt),
            usageCount: 0
        })
    }

    function setupSocket() {
        on('household:updated', handleUpdated)
        on('household:member_joined', handleMemberJoined)
        on('household:member_left', handleMemberLeft)
        on('household:member_activity', handleMemberActivity)
        on('household:invite_created', handleInviteCreated)
    }

    function cleanupSocket() {
        off('household:updated', handleUpdated)
        off('household:member_joined', handleMemberJoined)
        off('household:member_left', handleMemberLeft)
        off('household:member_activity', handleMemberActivity)
        off('household:invite_created', handleInviteCreated)
    }

    // ---- Enhanced Actions ----
    async function fetchHousehold(id: number) {
        isLoading.value = true
        error.value = null

        try {
            const data = await groupService.getGroupDetails(id)
            // Convert Group to GroupPublic format
            household.value = {
                ...data,
                members: (data.members || []).filter(m => m !== null).map(m => ({
                    id: m!.id as number,
                    name: m!.name,
                    full_name: m!.name,
                    email: m!.email
                })),
                is_member: true
            } as Household

            // Initialize member activity tracking
            household.value.members.forEach((member: UserPublic) => {
                memberActivity.value[member.id] = {
                    lastSeen: new Date(),
                    isActive: true // Default to active for newly loaded members
                }
            })

            setupSocket()
        } catch (err: any) {
            error.value = err.message || 'Failed to fetch household'
            throw err
        } finally {
            isLoading.value = false
        }
    }

    async function updateHousehold(updates: Partial<GroupUpdate>) {
        if (!household.value) return

        const original = { ...household.value }

        // Optimistic update
        household.value = { ...household.value, ...updates }

        try {
            const updated = await groupService.updateGroup(household.value.id, updates)
            // Convert Group to GroupPublic format
            household.value = {
                ...updated,
                members: household.value.members, // Keep existing members
                is_member: true
            } as Household

            // Emit real-time update to other members
            emit('household:updated', { household: household.value })

            return household.value
        } catch (err: any) {
            // Rollback on error
            household.value = original
            error.value = err.message || 'Failed to update household'
            throw err
        }
    }

    async function generateInviteCode() {
        if (!household.value) return null

        try {
            // TODO: Implement when backend API is available
            // const response = await groupService.createInvite(household.value.id)
            // const newCode = response.code

            const newCode = `inv_${Math.random().toString(36).substring(2, 15)}`

            inviteCodes.value.push(newCode)
            emit('household:invite_created', {
                code: newCode,
                expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString() // 7 days
            })

            return newCode
        } catch (err: any) {
            error.value = err.message || 'Failed to generate invite code'
            throw err
        }
    }

    // Member management
    async function removeMember(userId: number) {
        if (!household.value) return

        const original = [...household.value.members]

        // Optimistic update
        household.value.members = household.value.members.filter(m => m.id !== userId)
        delete memberActivity.value[userId]

        try {
            // TODO: Implement when backend API is available
            // await groupService.removeMember(household.value.id, userId)
            emit('household:member_left', { householdId: household.value.id, userId })
        } catch (err: any) {
            // Rollback on error
            household.value.members = original
            error.value = err.message || 'Failed to remove member'
            throw err
        }
    }

    // Cross-feature integration helpers
    function getMemberById(id: number) {
        return members.value.find(m => m.id === id)
    }

    function updateMemberActivity(userId: number, isActive: boolean = true) {
        if (memberActivity.value[userId]) {
            memberActivity.value[userId] = {
                lastSeen: new Date(),
                isActive
            }

            // Emit activity update to other members
            emit('household:member_activity', {
                userId,
                lastSeen: new Date().toISOString(),
                isActive
            })
        }
    }

    // Cleanup on unmount
    function cleanup() {
        cleanupSocket()
    }

    return {
        // State
        household,
        isLoading,
        error,
        memberActivity,
        inviteCodes,
        pendingInvites,

        // Getters
        householdName,
        members,
        memberCount,
        isMember,
        activeMembers,
        inactiveMembers,
        householdHealth,

        // Actions
        fetchHousehold,
        updateHousehold,
        generateInviteCode,
        removeMember,
        getMemberById,
        updateMemberActivity,
        setupSocket,
        cleanup
    }
}) 