<template>
  <main class="container page-padding">
    <div v-if="loading" class="text-center">
      <VSpinner :label="t('groupDetailPage.loadingLabel')" />
    </div>
    <VAlert v-else-if="error" type="error" :message="error" class="mb-3">
      <template #actions>
        <VButton variant="danger" size="sm" @click="fetchGroupDetails">{{ t('groupDetailPage.retryButton') }}</VButton>
      </template>
    </VAlert>
    <div v-else-if="group">
      <div class="flex justify-between items-start mb-4">
        <VHeading :level="1" :text="group.name" class="header-title-text" />
        <div class="member-avatar-list">
          <div ref="avatarsContainerRef" class="member-avatars">
            <div v-for="member in group.members" :key="member.id" class="member-avatar">
              <div @click="toggleMemberMenu(member.id)" class="avatar-circle" :title="member.email">
                {{ member.email.charAt(0).toUpperCase() }}
              </div>
              <div v-show="activeMemberMenu === member.id" ref="memberMenuRef" class="member-menu" @click.stop>
                <div class="popup-header">
                  <span class="font-semibold truncate">{{ member.email }}</span>
                  <VButton variant="neutral" size="sm" :icon-only="true" iconLeft="x" @click="activeMemberMenu = null"
                    aria-label="Close menu" />
                </div>
                <div class="member-menu-content">
                  <VBadge :text="member.role || t('groupDetailPage.members.defaultRole')"
                    :variant="member.role?.toLowerCase() === 'owner' ? 'primary' : 'secondary'" />
                  <VButton v-if="canRemoveMember(member)" variant="danger" size="sm" class="w-full text-left"
                    @click="removeMember(member.id)" :disabled="removingMember === member.id">
                    <VSpinner v-if="removingMember === member.id" size="sm" class="mr-1" />
                    {{ t('groupDetailPage.members.removeButton') }}
                  </VButton>
                </div>
              </div>
            </div>
          </div>
          <button ref="addMemberButtonRef" @click="toggleInviteUI" class="add-member-btn"
            :aria-label="t('groupDetailPage.invites.title')">
            <!-- <VIcon name="plus" size="md" /> -->
            +
          </button>

          <!-- Invite Members Popup -->
          <div v-show="showInviteUI" ref="inviteUIRef" class="invite-popup">
            <div class="popup-header">
              <VHeading :level="3" class="!m-0 !p-0 !border-none">{{ t('groupDetailPage.invites.title') }}
              </VHeading>
              <VButton variant="neutral" size="sm" :icon-only="true" iconLeft="x" @click="showInviteUI = false"
                aria-label="Close invite" />
            </div>
            <p class="text-sm text-gray-500 my-2">Invite new members by generating a shareable code.</p>
            <VButton variant="primary" class="w-full" @click="generateInviteCode" :disabled="generatingInvite">
              <VSpinner v-if="generatingInvite" size="sm" /> {{ inviteCode ?
                t('groupDetailPage.invites.regenerateButton') :
                t('groupDetailPage.invites.generateButton') }}
            </VButton>
            <div v-if="inviteCode" class="neo-invite-code mt-3">
              <VFormField :label="t('groupDetailPage.invites.activeCodeLabel')" :label-sr-only="false">
                <div class="flex items-center gap-2">
                  <VInput id="inviteCodeInput" :model-value="inviteCode" readonly class="flex-grow" />
                  <VButton variant="neutral" :icon-only="true" iconLeft="clipboard" @click="copyInviteCodeHandler"
                    :aria-label="t('groupDetailPage.invites.copyButtonLabel')" />
                </div>
              </VFormField>
              <p v-if="copySuccess" class="text-sm text-green-600 mt-1">{{ t('groupDetailPage.invites.copySuccess') }}
              </p>
            </div>
          </div>
        </div>
      </div>

      <div class="neo-section-container">
        <!-- Lists Section -->
        <div class="neo-section">
          <VHeading :level="3" class="neo-section-header">{{ t('groupDetailPage.lists.title') }}</VHeading>
          <ListsPage :group-id="groupId" />
        </div>

        <!-- Chores Section -->
        <div class="mt-4 neo-section">
          <div class="flex justify-between items-center w-full mb-2">
            <VHeading :level="3" class="neo-section-header">{{ t('groupDetailPage.chores.title') }}</VHeading>

          </div>
          <VList v-if="upcomingChores.length > 0">
            <VListItem v-for="chore in upcomingChores" :key="chore.id" class="flex justify-between items-center">
              <div class="neo-chore-info">
                <span class="neo-chore-name">{{ chore.name }}</span>
                <span class="neo-chore-due">{{ t('groupDetailPage.chores.duePrefix') }} {{
                  formatDate(chore.next_due_date)
                }}</span>
              </div>
              <VBadge :text="formatFrequency(chore.frequency)" :variant="getFrequencyBadgeVariant(chore.frequency)" />
            </VListItem>
          </VList>
          <div v-else class="text-center py-4">
            <VIcon name="cleaning_services" size="lg" class="opacity-50 mb-2" />
            <p>{{ t('groupDetailPage.chores.emptyState') }}</p>
          </div>
        </div>

        <!-- Expenses Section -->
        <div class="mt-4 neo-section">
          <div class="flex justify-between items-center w-full mb-2">
            <VHeading :level="3" class="neo-section-header">{{ t('groupDetailPage.expenses.title') }}</VHeading>

          </div>
          <div v-if="recentExpenses.length > 0" class="neo-expense-list">
            <div v-for="expense in recentExpenses" :key="expense.id" class="neo-expense-item-wrapper">
              <div class="neo-expense-item" @click="toggleExpense(expense.id)"
                :class="{ 'is-expanded': isExpenseExpanded(expense.id) }">
                <div class="expense-main-content">
                  <div class="expense-icon-container">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
                      stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                      <line x1="12" x2="12" y1="2" y2="22"></line>
                      <path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"></path>
                    </svg>
                  </div>
                  <div class="expense-text-content">
                    <div class="neo-expense-header">
                      {{ expense.description }}
                    </div>
                    <div class="neo-expense-details">
                      {{ formatCurrency(expense.total_amount) }} &mdash;
                      {{ t('groupDetailPage.expenses.paidBy') }} <strong>{{ expense.paid_by_user?.name ||
                        expense.paid_by_user?.email }}</strong>
                    </div>
                  </div>
                </div>
                <div class="expense-side-content">
                  <span class="neo-expense-status" :class="getStatusClass(expense.overall_settlement_status)">
                    {{ getOverallExpenseStatusText(expense.overall_settlement_status) }}
                  </span>
                  <div class="expense-toggle-icon">
                    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none"
                      stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
                      class="feather feather-chevron-down">
                      <polyline points="6 9 12 15 18 9"></polyline>
                    </svg>
                  </div>
                </div>
              </div>
              <div v-if="isExpenseExpanded(expense.id)" class="neo-splits-container">
                <div class="neo-splits-list">
                  <div v-for="split in expense.splits" :key="split.id" class="neo-split-item">
                    <div class="split-col split-user">
                      <strong>{{ split.user?.name || split.user?.email || `User ID: ${split.user_id}` }}</strong>
                    </div>
                    <div class="split-col split-owes">
                      {{ t('groupDetailPage.expenses.owes') }} <strong>{{
                        formatCurrency(split.owed_amount) }}</strong>
                    </div>
                    <div class="split-col split-status">
                      <span class="neo-expense-status" :class="getStatusClass(split.status)">
                        {{ getSplitStatusText(split.status) }}
                      </span>
                    </div>
                    <div class="split-col split-paid-info">
                      <div v-if="split.paid_at" class="paid-details">
                        {{ t('groupDetailPage.expenses.paidAmount') }} {{ getPaidAmountForSplitDisplay(split) }}
                        <span v-if="split.paid_at"> {{ t('groupDetailPage.expenses.onDate') }} {{ new
                          Date(split.paid_at).toLocaleDateString() }}</span>
                      </div>
                    </div>
                    <div class="split-col split-action">
                      <button
                        v-if="split.user_id === authStore.user?.id && split.status !== ExpenseSplitStatusEnum.PAID"
                        class="btn btn-sm btn-primary" @click="openSettleShareModal(expense, split)"
                        :disabled="isSettlementLoading">
                        {{ t('groupDetailPage.expenses.settleShareButton') }}
                      </button>
                    </div>
                    <ul v-if="split.settlement_activities && split.settlement_activities.length > 0"
                      class="neo-settlement-activities">
                      <li v-for="activity in split.settlement_activities" :key="activity.id">
                        {{ t('groupDetailPage.expenses.activityLabel') }} {{
                          formatCurrency(activity.amount_paid) }}
                        {{
                          t('groupDetailPage.expenses.byUser') }} {{ activity.payer?.name || `User
                        ${activity.paid_by_user_id}` }} {{ t('groupDetailPage.expenses.onDate') }} {{ new
                          Date(activity.paid_at).toLocaleDateString() }}
                      </li>
                    </ul>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <div v-else class="text-center py-4">
            <VIcon name="payments" size="lg" class="opacity-50 mb-2" />
            <p>{{ t('groupDetailPage.expenses.emptyState') }}</p>
          </div>
        </div>
      </div>
    </div>

    <VAlert v-else type="info" :message="t('groupDetailPage.groupNotFound')" />

    <!-- Settle Share Modal -->
    <VModal v-model="showSettleModal" :title="t('groupDetailPage.settleShareModal.title')"
      @update:modelValue="!$event && closeSettleShareModal()" size="md">
      <template #default>
        <div v-if="isSettlementLoading" class="text-center">
          <VSpinner :label="t('groupDetailPage.loading.settlement')" />
        </div>
        <VAlert v-else-if="settleAmountError" type="error" :message="settleAmountError" />
        <div v-else>
          <p>{{ t('groupDetailPage.settleShareModal.settleAmountFor', {
            userName: selectedSplitForSettlement?.user?.name
              || selectedSplitForSettlement?.user?.email || `User ID: ${selectedSplitForSettlement?.user_id}`
          }) }}</p>
          <VFormField :label="t('groupDetailPage.settleShareModal.amountLabel')"
            :error-message="settleAmountError || undefined">
            <VInput type="number" v-model="settleAmount" id="settleAmount" required />
          </VFormField>
        </div>
      </template>
      <template #footer>
        <VButton variant="neutral" @click="closeSettleShareModal">{{
          t('groupDetailPage.settleShareModal.cancelButton')
          }}</VButton>
        <VButton variant="primary" @click="handleConfirmSettle" :disabled="isSettlementLoading">{{
          t('groupDetailPage.settleShareModal.confirmButton')
          }}</VButton>
      </template>
    </VModal>
  </main>
</template>

<script setup lang="ts">
import { ref, onMounted, computed } from 'vue';
import { useI18n } from 'vue-i18n';
// import { useRoute } from 'vue-router';
import { apiClient, API_ENDPOINTS } from '@/config/api'; // Assuming path
import { useClipboard, useStorage } from '@vueuse/core';
import ListsPage from './ListsPage.vue'; // Import ListsPage
import { useNotificationStore } from '@/stores/notifications';
import { choreService } from '../services/choreService'
import type { Chore, ChoreFrequency } from '../types/chore'
import { format } from 'date-fns'
import type { Expense, ExpenseSplit, SettlementActivityCreate } from '@/types/expense';
import { ExpenseOverallStatusEnum, ExpenseSplitStatusEnum } from '@/types/expense';
import { useAuthStore } from '@/stores/auth';
import { Decimal } from 'decimal.js';
import type { BadgeVariant } from '@/components/valerie/VBadge.vue';
import VHeading from '@/components/valerie/VHeading.vue';
import VSpinner from '@/components/valerie/VSpinner.vue';
import VAlert from '@/components/valerie/VAlert.vue';
import VCard from '@/components/valerie/VCard.vue';
import VList from '@/components/valerie/VList.vue';
import VListItem from '@/components/valerie/VListItem.vue';
import VButton from '@/components/valerie/VButton.vue';
import VBadge from '@/components/valerie/VBadge.vue';
import VInput from '@/components/valerie/VInput.vue';
import VFormField from '@/components/valerie/VFormField.vue';
import VIcon from '@/components/valerie/VIcon.vue';
import VModal from '@/components/valerie/VModal.vue';
import { onClickOutside } from '@vueuse/core'

const { t } = useI18n();

// Caching setup
const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes

interface CachedGroup { group: Group; timestamp: number; }
const cachedGroups = useStorage<Record<string, CachedGroup>>('cached-groups-v1', {});

interface CachedChores { chores: Chore[]; timestamp: number; }
const cachedUpcomingChores = useStorage<Record<string, CachedChores>>('cached-group-chores-v1', {});

// interface CachedExpenses { expenses: Expense[]; timestamp: number; }
// const cachedRecentExpenses = useStorage<Record<string, CachedExpenses>>('cached-group-expenses-v1', {});

interface Group {
  id: string | number;
  name: string;
  members?: GroupMember[];
}

interface GroupMember {
  id: number;
  email: string;
  role?: string;
}

const props = defineProps<{
  id: string;
}>();

// const route = useRoute();
// const $q = useQuasar(); // Not used anymore

const notificationStore = useNotificationStore();
const group = ref<Group | null>(null);
const loading = ref(true);
const error = ref<string | null>(null);
const inviteCode = ref<string | null>(null);
const inviteExpiresAt = ref<string | null>(null);
const generatingInvite = ref(false);
const copySuccess = ref(false);
const removingMember = ref<number | null>(null);
const showInviteUI = ref(false);
const activeMemberMenu = ref<number | null>(null);

const memberMenuRef = ref(null)
const inviteUIRef = ref(null)
const addMemberButtonRef = ref(null)
const avatarsContainerRef = ref(null)

onClickOutside(memberMenuRef, () => {
  activeMemberMenu.value = null
}, { ignore: [avatarsContainerRef] })

onClickOutside(inviteUIRef, () => {
  showInviteUI.value = false
}, { ignore: [addMemberButtonRef] })

// groupId is directly from props.id now, which comes from the route path param
const groupId = computed(() => props.id);

const { copy, copied, isSupported: clipboardIsSupported } = useClipboard({
  source: computed(() => inviteCode.value || '')
});

// Chores state
const upcomingChores = ref<Chore[]>([])

// Add new state for expenses
const recentExpenses = ref<Expense[]>([])
const expandedExpenses = ref<Set<number>>(new Set());
const authStore = useAuthStore();

// Settle Share Modal State
const showSettleModal = ref(false);
const selectedSplitForSettlement = ref<ExpenseSplit | null>(null);
const settleAmount = ref<string>('');
const settleAmountError = ref<string | null>(null);
const isSettlementLoading = ref(false);

const getApiErrorMessage = (err: unknown, fallbackMessageKey: string): string => {
  if (err && typeof err === 'object') {
    if ('response' in err && err.response && typeof err.response === 'object' && 'data' in err.response && err.response.data) {
      const errorData = err.response.data as any;
      if (typeof errorData.detail === 'string') {
        return errorData.detail;
      }
      if (typeof errorData.message === 'string') {
        return errorData.message;
      }
      if (Array.isArray(errorData.detail) && errorData.detail.length > 0) {
        const firstError = errorData.detail[0];
        if (typeof firstError.msg === 'string' && typeof firstError.type === 'string') {
          return firstError.msg;
        }
      }
      if (typeof errorData === 'string') {
        return errorData;
      }
    }
    if (err instanceof Error && err.message) {
      return err.message;
    }
  }
  return t(fallbackMessageKey);
};

const fetchActiveInviteCode = async () => {
  if (!groupId.value) return;
  // Consider adding a loading state for this fetch if needed, e.g., initialInviteCodeLoading
  try {
    const response = await apiClient.get(API_ENDPOINTS.GROUPS.GET_ACTIVE_INVITE(String(groupId.value)));
    if (response.data && response.data.code) {
      inviteCode.value = response.data.code;
      inviteExpiresAt.value = response.data.expires_at; // Store expiry
    } else {
      inviteCode.value = null; // No active code found
      inviteExpiresAt.value = null;
    }
  } catch (err: any) {
    if (err.response && err.response.status === 404) {
      inviteCode.value = null; // Explicitly set to null on 404
      inviteExpiresAt.value = null;
      // Optional: notify user or set a flag to show "generate one" message more prominently
      console.info('No active invite code found for this group.');
    } else {
      const message = err instanceof Error ? err.message : 'Failed to fetch active invite code.';
      // error.value = message; // This would display a large error banner, might be too much
      console.error('Error fetching active invite code:', err);
      notificationStore.addNotification({ message, type: 'error' });
    }
  }
};

const fetchGroupDetails = async () => {
  if (!groupId.value) return;
  const groupIdStr = String(groupId.value);
  const cached = cachedGroups.value[groupIdStr];

  // If we have any cached data (even stale), show it first to avoid loading spinner.
  if (cached) {
    group.value = cached.group;
    loading.value = false;
  } else {
    // Only show loading spinner if there is no cached data at all.
    loading.value = true;
  }

  // Reset error state for the new fetch attempt
  error.value = null;
  try {
    const response = await apiClient.get(API_ENDPOINTS.GROUPS.BY_ID(groupIdStr));
    group.value = response.data;
    // Update cache on successful fetch
    cachedGroups.value[groupIdStr] = {
      group: response.data,
      timestamp: Date.now(),
    };
  } catch (err: unknown) {
    const message = err instanceof Error ? err.message : 'Failed to fetch group details.';
    // Only show the main error banner if we have no data at all to show
    if (!group.value) {
      error.value = message;
    }
    console.error('Error fetching group details:', err);
    // Always show a notification for failures, even background ones
    notificationStore.addNotification({ message, type: 'error' });
  } finally {
    // If we were showing the loader, hide it.
    if (loading.value) {
      loading.value = false;
    }
  }
  // Fetch active invite code after group details are loaded or retrieved from cache
  await fetchActiveInviteCode();
};

const generateInviteCode = async () => {
  if (!groupId.value) return;
  generatingInvite.value = true;
  copySuccess.value = false;
  try {
    const response = await apiClient.post(API_ENDPOINTS.GROUPS.CREATE_INVITE(String(groupId.value)));
    if (response.data && response.data.code) {
      inviteCode.value = response.data.code;
      inviteExpiresAt.value = response.data.expires_at; // Update with new expiry
      notificationStore.addNotification({ message: t('groupDetailPage.notifications.generateInviteSuccess'), type: 'success' });
    } else {
      // Should not happen if POST is successful and returns the code
      throw new Error(t('groupDetailPage.invites.errors.newDataInvalid'));
    }
  } catch (err: unknown) {
    const message = err instanceof Error ? err.message : t('groupDetailPage.notifications.generateInviteError');
    console.error('Error generating invite code:', err);
    notificationStore.addNotification({ message, type: 'error' });
  } finally {
    generatingInvite.value = false;
  }
};

const copyInviteCodeHandler = async () => {
  if (!clipboardIsSupported.value || !inviteCode.value) {
    notificationStore.addNotification({ message: t('groupDetailPage.notifications.clipboardNotSupported'), type: 'warning' });
    return;
  }
  await copy(inviteCode.value);
  if (copied.value) {
    copySuccess.value = true;
    setTimeout(() => (copySuccess.value = false), 2000);
    // Optionally, notify success via store if preferred over inline message
    // notificationStore.addNotification({ message: 'Invite code copied!', type: 'info' });
  } else {
    notificationStore.addNotification({ message: t('groupDetailPage.notifications.copyInviteFailed'), type: 'error' });
  }
};

const canRemoveMember = (member: GroupMember): boolean => {
  // Simplification: For now, assume a user with role 'owner' can remove anyone but another owner.
  // A real implementation would check the current user's ID against the member to prevent self-removal.
  const isOwner = group.value?.members?.find(m => m.id === member.id)?.role === 'owner';
  return !isOwner;
};

const removeMember = async (memberId: number) => {
  if (!groupId.value) return;

  removingMember.value = memberId;
  try {
    await apiClient.delete(API_ENDPOINTS.GROUPS.MEMBER(String(groupId.value), String(memberId)));
    // Refresh group details to update the members list
    await fetchGroupDetails();
    notificationStore.addNotification({
      message: t('groupDetailPage.notifications.removeMemberSuccess'),
      type: 'success'
    });
  } catch (err: unknown) {
    const message = err instanceof Error ? err.message : t('groupDetailPage.notifications.removeMemberFailed');
    console.error('Error removing member:', err);
    notificationStore.addNotification({ message, type: 'error' });
  } finally {
    removingMember.value = null;
  }
};

// Chores methods
const loadUpcomingChores = async () => {
  if (!groupId.value) return
  const groupIdStr = String(groupId.value);
  const cached = cachedUpcomingChores.value[groupIdStr];

  if (cached) {
    upcomingChores.value = cached.chores;
  }

  try {
    const chores = await choreService.getChores(Number(groupId.value))
    const sortedChores = chores
      .sort((a, b) => new Date(a.next_due_date).getTime() - new Date(b.next_due_date).getTime())
      .slice(0, 5)
    upcomingChores.value = sortedChores;
    cachedUpcomingChores.value[groupIdStr] = {
      chores: sortedChores,
      timestamp: Date.now()
    };
  } catch (error) {
    console.error('Error loading upcoming chores:', error)
  }
}

const formatDate = (date: string) => {
  return format(new Date(date), 'MMM d, yyyy')
}

const formatFrequency = (frequency: ChoreFrequency) => {
  const options: Record<ChoreFrequency, string> = {
    one_time: t('choresPage.frequencyOptions.oneTime'), // Reusing existing keys
    daily: t('choresPage.frequencyOptions.daily'),
    weekly: t('choresPage.frequencyOptions.weekly'),
    monthly: t('choresPage.frequencyOptions.monthly'),
    custom: t('choresPage.frequencyOptions.custom')
  };
  return options[frequency] || frequency;
};

const getFrequencyBadgeVariant = (frequency: ChoreFrequency): BadgeVariant => {
  const colorMap: Record<ChoreFrequency, BadgeVariant> = {
    one_time: 'neutral',
    daily: 'info',
    weekly: 'success',
    monthly: 'accent', // Using accent for purple as an example
    custom: 'warning'
  };
  return colorMap[frequency] || 'secondary';
};

// Add new methods for expenses
const loadRecentExpenses = async () => {
  if (!groupId.value) return
  try {
    const response = await apiClient.get(
      `${API_ENDPOINTS.FINANCIALS.EXPENSES}?group_id=${groupId.value}&limit=5&detailed=true`
    )
    recentExpenses.value = response.data
  } catch (error) {
    console.error('Error loading recent expenses:', error)
    notificationStore.addNotification({ message: t('groupDetailPage.notifications.loadExpensesFailed'), type: 'error' });
  }
}

const formatAmount = (amount: string) => {
  return parseFloat(amount).toFixed(2)
}

const formatSplitType = (type: string) => {
  // Assuming 'type' is like 'exact_amounts' or 'item_based'
  const key = `groupDetailPage.expenses.splitTypes.${type.toLowerCase().replace(/_([a-z])/g, g => g[1].toUpperCase())}`;
  // This creates keys like 'groupDetailPage.expenses.splitTypes.exactAmounts'
  // Check if translation exists, otherwise fallback to a simple formatted string
  // For simplicity in this subtask, we'll assume keys will be added.
  // A more robust solution would check i18n.global.te(key) or have a fallback.
  return t(key);
};

const getSplitTypeBadgeVariant = (type: string): BadgeVariant => {
  const colorMap: Record<string, BadgeVariant> = {
    equal: 'info',
    exact_amounts: 'success',
    percentage: 'accent', // Using accent for purple
    shares: 'warning',
    item_based: 'secondary', // Using secondary for teal as an example
  };
  return colorMap[type] || 'neutral';
};

const formatCurrency = (value: string | number | undefined | null): string => {
  if (value === undefined || value === null) return '$0.00';
  if (typeof value === 'string' && !value.trim()) return '$0.00';
  const numValue = typeof value === 'string' ? parseFloat(value) : value;
  return isNaN(numValue) ? '$0.00' : `$${numValue.toFixed(2)}`;
};

const getPaidAmountForSplit = (split: ExpenseSplit): Decimal => {
  if (!split.settlement_activities) return new Decimal(0);
  return split.settlement_activities.reduce((sum, activity) => {
    return sum.plus(new Decimal(activity.amount_paid));
  }, new Decimal(0));
}

const getPaidAmountForSplitDisplay = (split: ExpenseSplit): string => {
  const amount = getPaidAmountForSplit(split);
  return formatCurrency(amount.toString());
};

const getSplitStatusText = (status: ExpenseSplitStatusEnum): string => {
  switch (status) {
    case ExpenseSplitStatusEnum.PAID: return t('groupDetailPage.status.paid');
    case ExpenseSplitStatusEnum.PARTIALLY_PAID: return t('groupDetailPage.status.partiallyPaid');
    case ExpenseSplitStatusEnum.UNPAID: return t('groupDetailPage.status.unpaid');
    default: return t('groupDetailPage.status.unknown');
  }
};

const getOverallExpenseStatusText = (status: ExpenseOverallStatusEnum): string => {
  switch (status) {
    case ExpenseOverallStatusEnum.PAID: return t('groupDetailPage.status.settled');
    case ExpenseOverallStatusEnum.PARTIALLY_PAID: return t('groupDetailPage.status.partiallySettled');
    case ExpenseOverallStatusEnum.UNPAID: return t('groupDetailPage.status.unsettled');
    default: return t('groupDetailPage.status.unknown');
  }
};

const getStatusClass = (status: ExpenseSplitStatusEnum | ExpenseOverallStatusEnum): string => {
  if (status === ExpenseSplitStatusEnum.PAID || status === ExpenseOverallStatusEnum.PAID) return 'status-paid';
  if (status === ExpenseSplitStatusEnum.PARTIALLY_PAID || status === ExpenseOverallStatusEnum.PARTIALLY_PAID) return 'status-partially_paid';
  if (status === ExpenseSplitStatusEnum.UNPAID || status === ExpenseOverallStatusEnum.UNPAID) return 'status-unpaid';
  return '';
};

const toggleExpense = (expenseId: number) => {
  const newSet = new Set(expandedExpenses.value);
  if (newSet.has(expenseId)) {
    newSet.delete(expenseId);
  } else {
    newSet.add(expenseId);
  }
  expandedExpenses.value = newSet;
};

const isExpenseExpanded = (expenseId: number) => {
  return expandedExpenses.value.has(expenseId);
};

const openSettleShareModal = (expense: Expense, split: ExpenseSplit) => {
  if (split.user_id !== authStore.user?.id) {
    notificationStore.addNotification({ message: t('groupDetailPage.notifications.cannotSettleOthersShares'), type: 'warning' });
    return;
  }
  selectedSplitForSettlement.value = split;
  const alreadyPaid = getPaidAmountForSplit(split);
  const owed = new Decimal(split.owed_amount);
  const remaining = owed.minus(alreadyPaid);
  settleAmount.value = remaining.toFixed(2);
  settleAmountError.value = null;
  showSettleModal.value = true;
};

const closeSettleShareModal = () => {
  showSettleModal.value = false;
  selectedSplitForSettlement.value = null;
  settleAmount.value = '';
  settleAmountError.value = null;
};

const validateSettleAmount = (): boolean => {
  settleAmountError.value = null;
  if (!settleAmount.value.trim()) {
    settleAmountError.value = t('groupDetailPage.settleShareModal.errors.enterAmount');
    return false;
  }
  const amount = new Decimal(settleAmount.value);
  if (amount.isNaN() || amount.isNegative() || amount.isZero()) {
    settleAmountError.value = t('groupDetailPage.settleShareModal.errors.positiveAmount');
    return false;
  }
  if (selectedSplitForSettlement.value) {
    const alreadyPaid = getPaidAmountForSplit(selectedSplitForSettlement.value);
    const owed = new Decimal(selectedSplitForSettlement.value.owed_amount);
    const remaining = owed.minus(alreadyPaid);
    if (amount.greaterThan(remaining.plus(new Decimal('0.001')))) {
      settleAmountError.value = t('groupDetailPage.settleShareModal.errors.exceedsRemaining', { amount: formatCurrency(remaining.toFixed(2)) });
      return false;
    }
  } else {
    settleAmountError.value = t('groupDetailPage.settleShareModal.errors.noSplitSelected');
    return false;
  }
  return true;
};

const handleConfirmSettle = async () => {
  if (!validateSettleAmount()) return;
  if (!selectedSplitForSettlement.value || !authStore.user?.id) {
    notificationStore.addNotification({ message: t('groupDetailPage.notifications.settlementDataMissing'), type: 'error' });
    return;
  }

  isSettlementLoading.value = true;
  try {
    const activityData: SettlementActivityCreate = {
      expense_split_id: selectedSplitForSettlement.value.id,
      paid_by_user_id: Number(authStore.user.id),
      amount_paid: new Decimal(settleAmount.value).toString(),
      paid_at: new Date().toISOString(),
    };

    await apiClient.post(API_ENDPOINTS.FINANCIALS.SETTLEMENTS, activityData);

    notificationStore.addNotification({ message: t('groupDetailPage.notifications.settleShareSuccess'), type: 'success' });
    closeSettleShareModal();
    await loadRecentExpenses();
  } catch (err) {
    const message = getApiErrorMessage(err, 'groupDetailPage.notifications.settleShareFailed');
    notificationStore.addNotification({ message, type: 'error' });
  } finally {
    isSettlementLoading.value = false;
  }
};

const toggleMemberMenu = (memberId: number) => {
  if (activeMemberMenu.value === memberId) {
    activeMemberMenu.value = null;
  } else {
    activeMemberMenu.value = memberId;
    // Close invite UI if it's open
    showInviteUI.value = false;
  }
};

const toggleInviteUI = () => {
  showInviteUI.value = !showInviteUI.value;
  if (showInviteUI.value) {
    activeMemberMenu.value = null; // Close any open member menu
  }
};

onMounted(() => {
  fetchGroupDetails();
  loadUpcomingChores();
  loadRecentExpenses();
});
</script>

<style scoped>
.page-padding {
  padding: 1rem;
  padding-block-end: 3rem;
  max-width: 1200px;
  margin: 0 auto;
}

.mt-1 {
  margin-top: 0.5rem;
}

.mt-2 {
  margin-top: 1rem;
}

.mt-3 {
  margin-top: 1.5rem;
}

.mt-4 {
  margin-top: 2rem;
}

.mb-3 {
  margin-bottom: 1.5rem;
}

.ml-1 {
  margin-left: 0.25rem;
}

.w-full {
  width: 100%;
}

.neo-section-container {
  border: 3px solid #111;
  border-radius: 18px;
  background: rgb(255, 248, 240);
  box-shadow: 6px 6px 0 #111;
  overflow: hidden;
}

.neo-section {
  padding: 1.5rem;
  border-bottom: 1px solid #eee;
}

.neo-section:last-child {
  border-bottom: none;
}

.neo-section-header {
  font-weight: 900;
  font-size: 1.25rem;
  margin: 0;
  margin-bottom: 1rem;
  letter-spacing: 0.5px;
}

.neo-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 0;
  border-bottom: 1px solid #eee;
}

.neo-grid .neo-section {
  border-bottom: none;
}

.neo-grid .neo-section:first-child {
  border-right: 1px solid #eee;
}

@media (max-width: 620px) {
  .neo-grid {
    grid-template-columns: 1fr;
  }

  .neo-grid .neo-section:first-child {
    border-right: none;
    border-bottom: 1px solid #eee;
  }
}

.member-avatar-list {
  display: flex;
  align-items: flex-end;
}

.member-avatars {
  display: flex;
  padding-left: 12px;
}

.member-avatar {
  position: relative;
  margin-left: -12px;
}

.avatar-circle {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background-color: var(--primary);
  color: var(--dark);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 900;
  border: 2px solid var(--light);
  cursor: pointer;
  transition: transform 0.2s ease;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
}

.avatar-circle:hover {
  transform: scale(1.1);
  z-index: 10;
}

.member-menu {
  position: absolute;
  top: 110%;
  right: -10px;
  background: white;
  border-radius: 8px;
  border: 2px solid var(--dark);
  box-shadow: var(--shadow-md);
  width: 220px;
  z-index: 100;
  overflow: hidden;
  /* padding: 0.5rem; */
}

.popup-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.5rem 0.5rem 0.5rem 1rem;
  border-bottom: 2px solid #eee;
}

.member-menu-content {
  padding: 0.75rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.add-member-btn {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--light);
  border: 2px dashed var(--dark);
  color: var(--dark);
  font-size: 1.5rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s ease;
  margin-left: -8px;
  z-index: 1;
}

.add-member-btn:hover {
  background: var(--secondary);
  transform: scale(1.1);
  border-style: solid;
}

.header-title-text {
  margin: 0;
}

.invite-popup {
  position: absolute;
  top: calc(16%);
  right: 10%;
  width: 27%;
  background: white;
  border-radius: 12px;
  border: 2px solid var(--dark);
  box-shadow: var(--shadow-md);
  z-index: 100;
  padding: 0.75rem;
}

/* Members List Styles */
.neo-members-list {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.neo-member-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem;
  border-radius: 12px;
  background: #fafafa;
  border: 2px solid #111;
  transition: transform 0.1s ease-in-out;
}

.neo-member-item:hover {
  transform: translateY(-2px);
}

.neo-member-info {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.neo-member-name {
  font-weight: 600;
  font-size: 1.1rem;
}

.neo-member-role {
  font-size: 0.875rem;
  padding: 0.25rem 0.75rem;
  border-radius: 1rem;
  background: #e0e0e0;
  font-weight: 600;
}

.neo-member-role.owner {
  background: #111;
  color: white;
}

/* Invite Code Styles */
.neo-invite-code {
  background: #fafafa;
  padding: 1rem;
  border-radius: 12px;
  border: 2px solid #111;
}

.neo-label {
  display: block;
  font-weight: 600;
  margin-bottom: 0.5rem;
}

.neo-input-group {
  display: flex;
  gap: 0.5rem;
}

.neo-input {
  flex: 1;
  padding: 0.75rem;
  border: 2px solid #111;
  border-radius: 8px;
  font-family: monospace;
  font-size: 1rem;
  background: white;
}

.neo-success-text {
  color: var(--success);
  font-size: 0.9rem;
  font-weight: 600;
  margin-top: 0.5rem;
}

/* Empty State Styles */
.neo-empty-state {
  text-align: center;
  padding: 2rem;
  color: #666;
}

.neo-empty-state .icon {
  width: 3rem;
  height: 3rem;
  margin-bottom: 1rem;
  opacity: 0.5;
}

/* Responsive Adjustments */
@media (max-width: 900px) {
  .neo-grid {
    /* The gap is removed to allow for border-based separators */
  }
}

@media (max-width: 600px) {
  .page-padding {
    padding: 0.5rem;
  }

  .neo-member-item {
    flex-direction: column;
    gap: 0.75rem;
    align-items: flex-start;
  }

  .neo-member-info {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.5rem;
  }
}

/* Chores List Styles */
.neo-chores-list {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.neo-chore-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem;
  border-radius: 12px;
  background: #fafafa;
  border: 2px solid #111;
  transition: transform 0.1s ease-in-out;
}

.neo-chore-item:hover {
  transform: translateY(-2px);
}

.neo-chore-info {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.neo-chore-name {
  font-weight: 600;
  font-size: 1.1rem;
}

.neo-chore-due {
  font-size: 0.875rem;
  color: #666;
}

/* Expenses List Styles */
.neo-expenses-list {
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.neo-expense-item {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem;
  border-radius: 12px;
  background: #fafafa;
  border: 2px solid #111;
  transition: transform 0.1s ease-in-out;
}

.neo-expense-info {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.neo-expense-name {
  font-weight: 600;
  font-size: 1.1rem;
}

.neo-expense-date {
  font-size: 0.875rem;
  color: #666;
}

.neo-expense-details {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.neo-expense-amount {
  font-weight: 600;
  font-size: 1.1rem;
}

.neo-chip {
  padding: 0.25rem 0.75rem;
  border-radius: 1rem;
  font-size: 0.875rem;
  font-weight: 600;
  background: #e0e0e0;
}

.neo-chip.blue {
  background: #e3f2fd;
  color: #1976d2;
}

.neo-chip.green {
  background: #e8f5e9;
  color: #2e7d32;
}

.neo-chip.purple {
  background: #f3e5f5;
  color: #7b1fa2;
}

.neo-chip.orange {
  background: #fff3e0;
  color: #f57c00;
}

.neo-chip.teal {
  background: #e0f2f1;
  color: #00796b;
}

.neo-chip.grey {
  background: #f5f5f5;
  color: #616161;
}

.neo-expense-list {
  background-color: rgb(255, 248, 240);
  /* Container for expense items */
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid #f0e5d8;
}

.neo-expense-item-wrapper {
  border-bottom: 1px solid #f0e5d8;
  margin-bottom: 0.5rem;
}

.neo-expense-item-wrapper:last-child {
  border-bottom: none;
}

.neo-expense-item {
  padding: 1rem 1.2rem;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  transition: background-color 0.2s ease;
}

.neo-expense-item:hover {
  background-color: rgba(0, 0, 0, 0.02);
}

.neo-expense-item.is-expanded .expense-toggle-icon {
  transform: rotate(180deg);
}

.expense-main-content {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.expense-icon-container {
  color: #d99a53;
}

.expense-text-content {
  display: flex;
  flex-direction: column;
}

.expense-side-content {
  display: flex;
  align-items: center;
  gap: 1rem;
}

.expense-toggle-icon {
  color: #888;
  transition: transform 0.3s ease;
}

.neo-expense-header {
  font-size: 1.1rem;
  font-weight: 600;
  margin-bottom: 0.1rem;
}

.neo-expense-details,
.neo-split-details {
  font-size: 0.9rem;
  color: #555;
  margin-bottom: 0.3rem;
}

.neo-expense-details strong,
.neo-split-details strong {
  color: #111;
}

.neo-expense-status {
  display: inline-block;
  padding: 0.25em 0.6em;
  font-size: 0.85em;
  font-weight: 700;
  line-height: 1;
  text-align: center;
  white-space: nowrap;
  vertical-align: baseline;
  border-radius: 0.375rem;
  margin-left: 0.5rem;
  color: #22c55e;
}

.status-unpaid {
  background-color: #fee2e2;
  color: #dc2626;
}

.status-partially_paid {
  background-color: #ffedd5;
  color: #f97316;
}

.status-paid {
  background-color: #dcfce7;
  color: #22c55e;
}

.neo-splits-container {
  padding: 0.5rem 1.2rem 1.2rem;
  background-color: rgba(255, 255, 255, 0.5);
}

.neo-splits-list {
  margin-top: 0rem;
  padding-left: 0;
  border-left: none;
}

.neo-split-item {
  padding: 0.75rem 0;
  border-bottom: 1px dashed #f0e5d8;
  display: grid;
  grid-template-areas:
    "user owes status paid action"
    "activities activities activities activities activities";
  grid-template-columns: 1.5fr 1fr 1fr 1.5fr auto;
  gap: 0.5rem 1rem;
  align-items: center;
}

.neo-split-item:last-child {
  border-bottom: none;
}

.split-col.split-user {
  grid-area: user;
}

.split-col.split-owes {
  grid-area: owes;
}

.split-col.split-status {
  grid-area: status;
}

.split-col.split-paid-info {
  grid-area: paid;
}

.split-col.split-action {
  grid-area: action;
  justify-self: end;
}

.split-col.neo-settlement-activities {
  grid-area: activities;
  font-size: 0.8em;
  color: #555;
  padding-left: 1em;
  list-style-type: disc;
  margin-top: 0.5em;
}

.neo-settlement-activities {
  font-size: 0.8em;
  color: #555;
  padding-left: 1em;
  list-style-type: disc;
  margin-top: 0.5em;
}

.neo-settlement-activities li {
  margin-top: 0.2em;
}
</style>
