import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
import { groupService } from '@/services/groupService';
import type { GroupPublic as Group, GroupCreate, GroupUpdate } from '@/types/group';
import type { UserPublic } from '@/types/user';
import { useSocket } from '@/composables/useSocket';
import { useNotificationStore } from '@/stores/notifications';

export const useGroupStore = defineStore('group', () => {
    // ---- State ----
    const groups = ref<Group[]>([]);
    const isLoading = ref(false);
    const currentGroupId = ref<number | null>(null);
    const error = ref<string | null>(null);

    // Real-time state
    const { isConnected, on, off, emit } = useSocket();
    const membersByGroup = ref<Record<number, UserPublic[]>>({});
    const notificationStore = useNotificationStore();

    // ---- Getters ----
    const currentGroup = computed(() => {
        if (!currentGroupId.value) return null;
        return groups.value.find(g => g.id === currentGroupId.value);
    });

    const groupCount = computed(() => groups.value.length);
    const firstGroupId = computed(() => groups.value[0]?.id ?? null);

    const currentGroupMembers = computed(() => {
        if (!currentGroupId.value) return [];
        return membersByGroup.value[currentGroupId.value] || [];
    });

    const isGroupAdmin = computed(() => {
        // Would need to check user role in current group
        return currentGroup.value?.created_by_id === 1; // Placeholder
    });

    // ---- Real-time Event Handlers ----
    function setupWebSocketListeners() {
        on('group:created', handleGroupCreated);
        on('group:member_joined', handleMemberJoined);
        on('group:member_left', handleMemberLeft);
        on('group:updated', handleGroupUpdated);
        on('group:deleted', handleGroupDeleted);
        on('group:invite_created', handleInviteCreated);
        on('group:invite_used', handleInviteUsed);
    }

    function cleanupWebSocketListeners() {
        off('group:created', handleGroupCreated);
        off('group:member_joined', handleMemberJoined);
        off('group:member_left', handleMemberLeft);
        off('group:updated', handleGroupUpdated);
        off('group:deleted', handleGroupDeleted);
        off('group:invite_created', handleInviteCreated);
        off('group:invite_used', handleInviteUsed);
    }

    function handleGroupCreated(payload: { group: Group }) {
        const { group } = payload;
        // Only add if it's not already in the list (to prevent duplicates)
        if (!groups.value.find(g => g.id === group.id)) {
            groups.value.push(group);
        }
    }

    function handleMemberJoined(payload: { groupId: number, member: UserPublic }) {
        const { groupId, member } = payload;
        if (!membersByGroup.value[groupId]) {
            membersByGroup.value[groupId] = [];
        }
        membersByGroup.value[groupId].push(member);

        // Show notification for new member
        const group = groups.value.find(g => g.id === groupId);
        if (group) {
            notificationStore.addNotification({
                message: `${member.name} joined ${group.name}!`,
                type: 'success'
            });
        }
    }

    function handleMemberLeft(payload: { groupId: number, userId: number }) {
        const { groupId, userId } = payload;
        if (membersByGroup.value[groupId]) {
            const member = membersByGroup.value[groupId].find(m => m.id === userId);
            membersByGroup.value[groupId] = membersByGroup.value[groupId]
                .filter(m => m.id !== userId);

            // Show notification for member leaving
            const group = groups.value.find(g => g.id === groupId);
            if (group && member) {
                notificationStore.addNotification({
                    message: `${member.name} left ${group.name}`,
                    type: 'info'
                });
            }
        }
    }

    function handleGroupUpdated(payload: { group: Group }) {
        const { group } = payload;
        const index = groups.value.findIndex(g => g.id === group.id);
        if (index >= 0) {
            groups.value[index] = group;
        }
    }

    function handleGroupDeleted(payload: { groupId: number }) {
        const { groupId } = payload;
        // Remove the group from the list
        groups.value = groups.value.filter(g => g.id !== groupId);
        // Clean up member data
        delete membersByGroup.value[groupId];
        // If this was the current group, switch to another one
        if (currentGroupId.value === groupId) {
            currentGroupId.value = groups.value[0]?.id || null;
        }
    }

    function handleInviteCreated(payload: { groupId: number, invite: any }) {
        // Could track pending invites for UI display
        console.log('New invite created for group', payload.groupId);
    }

    function handleInviteUsed(payload: { groupId: number, inviteId: number, member: UserPublic }) {
        // When an invite is used, a new member joins - this usually triggers handleMemberJoined too
        console.log('Invite used for group', payload.groupId, 'by', payload.member.name);
    }

    // ---- Actions ----
    async function fetchUserGroups() {
        isLoading.value = true;
        error.value = null;
        try {
            groups.value = await groupService.getUserGroups();
            // Set the first group as current by default if not already set
            if (!currentGroupId.value && groups.value.length > 0) {
                currentGroupId.value = groups.value[0].id;
            }

            // Fetch members for each group
            for (const group of groups.value) {
                await fetchGroupMembers(group.id);
            }
        } catch (err: any) {
            error.value = err?.message || 'Failed to fetch groups';
            console.error('Failed to fetch groups:', err);
        } finally {
            isLoading.value = false;
        }
    };

    async function fetchGroupMembers(groupId: number) {
        try {
            const members = await groupService.getGroupMembers(groupId);
            membersByGroup.value[groupId] = members;
        } catch (err: any) {
            console.error(`Failed to fetch members for group ${groupId}:`, err);
        }
    }

    async function createGroup(groupData: GroupCreate) {
        isLoading.value = true;
        error.value = null;
        try {
            const newGroup = await groupService.createGroup(groupData);
            // Convert to GroupPublic format for consistency
            const groupPublic: Group = {
                ...newGroup,
                members: []
            };
            groups.value.push(groupPublic);

            // Auto-select new group
            currentGroupId.value = newGroup.id;

            // Emit real-time event
            emit('group:created', { group: groupPublic });

            return groupPublic;
        } catch (err: any) {
            error.value = err?.message || 'Failed to create group';
            throw err;
        } finally {
            isLoading.value = false;
        }
    }

    async function updateGroup(groupId: number, updates: Partial<Group>) {
        const originalGroup = groups.value.find(g => g.id === groupId);
        if (!originalGroup) return;

        // Optimistic update
        const index = groups.value.findIndex(g => g.id === groupId);
        if (index >= 0) {
            groups.value[index] = { ...originalGroup, ...updates };
        }

        try {
            // Convert updates to proper format
            const updateData: GroupUpdate = {
                name: updates.name,
                description: updates.description === null ? undefined : updates.description
            };

            const updatedGroup = await groupService.updateGroup(groupId, updateData);
            const groupPublic: Group = {
                ...updatedGroup,
                members: originalGroup.members
            };
            groups.value[index] = groupPublic;

            // Emit real-time event
            emit('group:updated', { group: groupPublic });

            return groupPublic;
        } catch (err: any) {
            // Rollback
            if (index >= 0) {
                groups.value[index] = originalGroup;
            }
            error.value = err?.message || 'Failed to update group';
            throw err;
        }
    }

    // Simplified functions without unsupported API calls
    function leaveGroup(groupId: number) {
        const groupIndex = groups.value.findIndex(g => g.id === groupId);
        if (groupIndex === -1) return;

        // Remove from local state
        groups.value.splice(groupIndex, 1);
        delete membersByGroup.value[groupId];

        // Switch to another group if this was current
        if (currentGroupId.value === groupId) {
            currentGroupId.value = groups.value[0]?.id || null;
        }

        // Emit real-time event
        emit('group:member_left', { groupId, userId: 1 }); // Would use actual user ID
    }

    function inviteMember(groupId: number, email: string) {
        // For now, just emit the event - actual API call would be added later
        const invite = { id: Date.now(), email, groupId };
        emit('group:invite_created', { groupId, invite });
        return Promise.resolve(invite);
    }

    function setCurrentGroupId(id: number) {
        const group = groups.value.find(g => g.id === id);
        if (group) {
            currentGroupId.value = id;

            // Fetch members if not already loaded
            if (!membersByGroup.value[id]) {
                fetchGroupMembers(id);
            }
        }
    };

    function setError(message: string) {
        error.value = message;
    }

    function clearError() {
        error.value = null;
    }

    // Initialize WebSocket listeners
    setupWebSocketListeners();

    // Alias for backward compatibility
    const fetchGroups = fetchUserGroups;

    return {
        // State
        groups,
        isLoading,
        currentGroupId,
        error,
        membersByGroup,

        // Getters
        currentGroup,
        currentGroupMembers,
        isGroupAdmin,
        groupCount,
        firstGroupId,

        // Actions
        fetchUserGroups,
        fetchGroups,
        fetchGroupMembers,
        createGroup,
        updateGroup,
        leaveGroup,
        inviteMember,
        setCurrentGroupId,
        setError,
        clearError,

        // Real-time
        isConnected,
        setupWebSocketListeners,
        cleanupWebSocketListeners,
    };
}); 