<script setup lang="ts">
import { computed, watch, ref } from 'vue'
import { Button } from '@/components/ui/button'
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog'
import { Megaphone, RefreshCw, AlertCircle } from 'lucide-vue-next'
import { useFeed } from '../composables/useFeed'
import { useProfiles } from '../composables/useProfiles'
import { useReactions } from '../composables/useReactions'
import { useScheduledEvents } from '../composables/useScheduledEvents'
import ThreadedPost from './ThreadedPost.vue'
import ScheduledEventCard from './ScheduledEventCard.vue'
import appConfig from '@/app.config'
import type { ContentFilter, FeedPost } from '../services/FeedService'
import type { ScheduledEvent } from '../services/ScheduledEventService'
import { injectService, SERVICE_TOKENS } from '@/core/di-container'
import type { AuthService } from '@/modules/base/auth/auth-service'
import type { RelayHub } from '@/modules/base/nostr/relay-hub'
import { finalizeEvent } from 'nostr-tools'
import { useToast } from '@/core/composables/useToast'

interface Emits {
  (e: 'reply-to-note', note: { id: string; content: string; pubkey: string }): void
}

const props = defineProps<{
  relays?: string[]
  feedType?: 'all' | 'announcements' | 'rideshare' | 'custom'
  contentFilters?: ContentFilter[]
  adminPubkeys?: string[]
  compactMode?: boolean
}>()

const emit = defineEmits<Emits>()

// Inject services
const authService = injectService<AuthService>(SERVICE_TOKENS.AUTH_SERVICE)
const relayHub = injectService<RelayHub>(SERVICE_TOKENS.RELAY_HUB)
const toast = useToast()

// Get admin/moderator pubkeys from props or app config
const adminPubkeys = props.adminPubkeys || appConfig.modules['nostr-feed']?.config?.adminPubkeys || []

// Get current user's pubkey
const currentUserPubkey = computed(() => authService?.user.value?.pubkey || null)

// Use centralized feed service - this handles all subscription management and deduplication
const { posts: notes, threadedPosts, isLoading, error, refreshFeed } = useFeed({
  feedType: props.feedType || 'all',
  maxPosts: 100,
  adminPubkeys,
  contentFilters: props.contentFilters
})

// Centralized collapse state management
const collapsedPosts = ref(new Set<string>())

// Track which posts should show limited replies (not collapsed, just limited)
const limitedReplyPosts = ref(new Set<string>())

// Delete confirmation dialog state
const showDeleteDialog = ref(false)
const postToDelete = ref<FeedPost | null>(null)

// Initialize posts that should show limited replies (>2 children)
watch(threadedPosts, (newPosts) => {
  if (newPosts.length > 0) {
    const newLimited = new Set<string>()

    // Find posts with more than 2 direct replies - these should show limited replies by default
    const findLimitedPosts = (posts: any[]) => {
      posts.forEach(post => {
        if ((post.replies?.length || 0) > 2) {
          // Mark this post as having limited replies shown
          newLimited.add(post.id)
        }
        // Recursively check nested replies
        if (post.replies?.length > 0) {
          findLimitedPosts(post.replies)
        }
      })
    }

    findLimitedPosts(newPosts)
    limitedReplyPosts.value = newLimited
  }
}, { immediate: true })

// Use profiles service for display names
const { getDisplayName, fetchProfiles } = useProfiles()

// Use reactions service for likes/hearts
const { getEventReactions, subscribeToReactions, toggleLike } = useReactions()

// Use scheduled events service
const { getTodaysEvents, getCompletion, toggleComplete } = useScheduledEvents()

// Get today's scheduled events (reactive)
const todaysScheduledEvents = computed(() => getTodaysEvents())

// Watch for new posts and fetch their profiles and reactions
watch(notes, async (newNotes) => {
  if (newNotes.length > 0) {
    const pubkeys = [...new Set(newNotes.map(note => note.pubkey))]
    const eventIds = newNotes.map(note => note.id)

    // Fetch profiles and subscribe to reactions in parallel
    await Promise.all([
      fetchProfiles(pubkeys),
      subscribeToReactions(eventIds)
    ])
  }
}, { immediate: true })

// Check if we have admin pubkeys configured
const hasAdminPubkeys = computed(() => adminPubkeys.length > 0)

// Get feed title and description based on type
const feedTitle = computed(() => {
  switch (props.feedType) {
    case 'announcements':
      return 'Announcements'
    case 'rideshare':
      return 'Rideshare'
    case 'all':
    default:
      return 'All Content'
  }
})

const feedDescription = computed(() => {
  switch (props.feedType) {
    case 'announcements':
      return 'Important announcements from community administrators'
    case 'rideshare':
      return 'Rideshare requests and offers'
    case 'all':
    default:
      return 'All community posts and updates'
  }
})




// Handle reply to note
function onReplyToNote(note: any) {
  emit('reply-to-note', {
    id: note.id,
    content: note.content,
    pubkey: note.pubkey
  })
}

// Handle like/heart reaction toggle
async function onToggleLike(note: FeedPost) {
  try {
    await toggleLike(note.id, note.pubkey, note.kind)
  } catch (error) {
    console.error('Failed to toggle like:', error)
  }
}

// Handle scheduled event completion toggle
async function onToggleComplete(event: ScheduledEvent) {
  console.log('🎯 NostrFeed: onToggleComplete called for event:', event.title)
  try {
    await toggleComplete(event)
    console.log('✅ NostrFeed: toggleComplete succeeded')
  } catch (error) {
    console.error('❌ NostrFeed: Failed to toggle event completion:', error)
  }
}

// Handle collapse toggle with cascading behavior
function onToggleCollapse(postId: string) {
  const newCollapsed = new Set(collapsedPosts.value)

  if (newCollapsed.has(postId)) {
    // Expand this post (remove from collapsed set)
    newCollapsed.delete(postId)
  } else {
    // Collapse this post (add to collapsed set)
    newCollapsed.add(postId)

    // Find all descendant posts and collapse them too (cascading collapse)
    const collapseDescendants = (posts: any[], targetId: string) => {
      posts.forEach(post => {
        if (post.id === targetId && post.replies) {
          // Found the target post, collapse all its descendants
          const addAllDescendants = (replies: any[]) => {
            replies.forEach(reply => {
              newCollapsed.add(reply.id)
              if (reply.replies?.length > 0) {
                addAllDescendants(reply.replies)
              }
            })
          }
          addAllDescendants(post.replies)
        } else if (post.replies?.length > 0) {
          // Keep searching in nested replies
          collapseDescendants(post.replies, targetId)
        }
      })
    }

    collapseDescendants(threadedPosts.value, postId)
  }

  collapsedPosts.value = newCollapsed
}

// Handle toggle limited replies (show/hide extra replies beyond first 2)
function onToggleLimited(postId: string) {
  const newLimited = new Set(limitedReplyPosts.value)

  if (newLimited.has(postId)) {
    // Show all replies
    newLimited.delete(postId)
  } else {
    // Limit to first 2 replies
    newLimited.add(postId)
  }

  limitedReplyPosts.value = newLimited
}

// Helper function to convert hex string to Uint8Array
const hexToUint8Array = (hex: string): Uint8Array => {
  const bytes = new Uint8Array(hex.length / 2)
  for (let i = 0; i < hex.length; i += 2) {
    bytes[i / 2] = parseInt(hex.substr(i, 2), 16)
  }
  return bytes
}

// Handle delete post button click - show confirmation dialog
function onDeletePost(note: FeedPost) {
  if (!authService?.isAuthenticated.value || !authService?.user.value) {
    toast.error("Please sign in to delete posts")
    return
  }

  // Verify user owns the post
  if (note.pubkey !== currentUserPubkey.value) {
    toast.error("You can only delete your own posts")
    return
  }

  // Show confirmation dialog
  postToDelete.value = note
  showDeleteDialog.value = true
}

// Confirm and execute post deletion (NIP-09: Event Deletion Request)
async function confirmDeletePost() {
  const note = postToDelete.value
  if (!note) return

  if (!relayHub?.isConnected.value) {
    toast.error("Not connected to Nostr relays")
    showDeleteDialog.value = false
    postToDelete.value = null
    return
  }

  const userPrivkey = authService?.user.value?.prvkey
  if (!userPrivkey) {
    toast.error("User private key not available")
    showDeleteDialog.value = false
    postToDelete.value = null
    return
  }

  try {
    // Create deletion event (NIP-09)
    const deletionEvent = {
      kind: 5, // Event Deletion Request
      content: 'Deleted by author',
      tags: [
        ['e', note.id], // Reference to event being deleted
        ['k', String(note.kind)] // Kind of event being deleted
      ],
      created_at: Math.floor(Date.now() / 1000)
    }

    // Sign the deletion event
    const privkeyBytes = hexToUint8Array(userPrivkey)
    const signedEvent = finalizeEvent(deletionEvent, privkeyBytes)

    // Publish the deletion request
    const result = await relayHub.publishEvent(signedEvent)

    if (result.success > 0) {
      toast.success(`Deletion request sent to ${result.success}/${result.total} relays`)
      // The post will be removed automatically via websocket when relays broadcast the deletion event
    } else {
      toast.error("Failed to send deletion request to any relay")
    }
  } catch (error) {
    console.error('Failed to delete post:', error)
    toast.error(error instanceof Error ? error.message : "Failed to delete post")
  } finally {
    // Close dialog and clear state
    showDeleteDialog.value = false
    postToDelete.value = null
  }
}

// Cancel delete action
function cancelDelete() {
  showDeleteDialog.value = false
  postToDelete.value = null
}
</script>

<template>
  <div class="flex flex-col">
    <!-- Compact Header (only in non-compact mode) -->
    <div v-if="!compactMode" class="flex items-center justify-between p-4 md:p-6 border-b md:bg-card/50 md:backdrop-blur-sm">
      <div class="w-full max-w-3xl mx-auto flex items-center justify-between">
        <div class="flex items-center gap-3">
          <Megaphone class="h-5 w-5 md:h-6 md:w-6 text-primary" />
          <div>
            <h2 class="text-lg md:text-xl font-bold">{{ feedTitle }}</h2>
            <p class="text-xs md:text-sm text-muted-foreground">{{ feedDescription }}</p>
          </div>
        </div>
        <Button
          variant="outline"
          size="sm"
          @click="refreshFeed"
          :disabled="isLoading"
          class="gap-2 md:h-10 md:px-4 hover:bg-accent transition-colors"
        >
          <RefreshCw :class="{ 'animate-spin': isLoading }" class="h-4 w-4" />
          <span class="hidden md:inline">Refresh</span>
        </Button>
      </div>
    </div>

    <!-- Feed Content Container -->
    <div class="w-full max-w-3xl mx-auto px-0 md:px-4">
      <!-- Loading State -->
      <div v-if="isLoading" class="flex items-center justify-center py-12">
        <div class="flex items-center gap-2">
          <RefreshCw class="h-4 w-4 animate-spin" />
          <span class="text-muted-foreground">Loading feed...</span>
        </div>
      </div>

      <!-- Error State -->
      <div v-else-if="error" class="text-center py-8 px-4">
        <div class="flex items-center justify-center gap-2 text-destructive mb-4">
          <AlertCircle class="h-5 w-5" />
          <span>Failed to load feed</span>
        </div>
        <p class="text-sm text-muted-foreground mb-4">{{ error }}</p>
        <Button @click="refreshFeed" variant="outline">Try Again</Button>
      </div>

      <!-- No Admin Pubkeys Warning -->
      <div v-else-if="!hasAdminPubkeys && props.feedType === 'announcements'" class="text-center py-8 px-4">
        <div class="flex items-center justify-center gap-2 text-muted-foreground mb-4">
          <Megaphone class="h-5 w-5" />
          <span>No admin pubkeys configured</span>
        </div>
        <p class="text-sm text-muted-foreground">
          Community announcements will appear here once admin pubkeys are configured.
        </p>
      </div>

      <!-- No Posts -->
      <div v-else-if="threadedPosts.length === 0" class="text-center py-8 px-4">
        <div class="flex items-center justify-center gap-2 text-muted-foreground mb-4">
          <Megaphone class="h-5 w-5" />
          <span>No posts yet</span>
        </div>
        <p class="text-sm text-muted-foreground">
          Check back later for community updates.
        </p>
      </div>

      <!-- Posts List - Natural flow without internal scrolling -->
      <div v-else>
        <!-- Today's Scheduled Events Section -->
        <div v-if="todaysScheduledEvents.length > 0" class="mb-6 md:mb-8">
          <h3 class="text-sm font-semibold text-muted-foreground uppercase tracking-wide px-4 md:px-0 mb-3">
            📅 Today's Events
          </h3>
          <div class="md:space-y-3">
            <ScheduledEventCard
              v-for="event in todaysScheduledEvents"
              :key="`${event.pubkey}:${event.dTag}`"
              :event="event"
              :get-display-name="getDisplayName"
              :get-completion="getCompletion"
              :admin-pubkeys="adminPubkeys"
              @toggle-complete="onToggleComplete"
            />
          </div>
        </div>

        <!-- Posts Section -->
        <div v-if="threadedPosts.length > 0" class="md:space-y-4 md:py-4">
          <h3 v-if="todaysScheduledEvents.length > 0" class="text-sm font-semibold text-muted-foreground uppercase tracking-wide px-4 md:px-0 mb-3 mt-6">
            💬 Posts
          </h3>
          <ThreadedPost
            v-for="post in threadedPosts"
            :key="post.id"
            :post="post"
            :admin-pubkeys="adminPubkeys"
            :current-user-pubkey="currentUserPubkey"
            :get-display-name="getDisplayName"
            :get-event-reactions="getEventReactions"
            :depth="0"
            :parent-collapsed="false"
            :collapsed-posts="collapsedPosts"
            :limited-reply-posts="limitedReplyPosts"
            @reply-to-note="onReplyToNote"
            @toggle-like="onToggleLike"
            @toggle-collapse="onToggleCollapse"
            @toggle-limited="onToggleLimited"
            @delete-post="onDeletePost"
          />
        </div>

        <!-- End of feed message -->
        <div class="text-center py-6 text-md text-muted-foreground">
          <p>🐢</p>
        </div>
      </div>
    </div>

    <!-- Delete Confirmation Dialog -->
    <Dialog :open="showDeleteDialog" @update:open="(val: boolean) => showDeleteDialog = val">
      <DialogContent>
        <DialogHeader>
          <DialogTitle>Delete Post?</DialogTitle>
          <DialogDescription>
            Are you sure you want to delete this post? This action cannot be undone. The deletion request will be sent to all relays.
          </DialogDescription>
        </DialogHeader>
        <DialogFooter>
          <Button variant="outline" @click="cancelDelete">Cancel</Button>
          <Button variant="destructive" @click="confirmDeletePost">Delete</Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  </div>
</template>
