<template>
  <div>
    <v-row>
      <v-col cols="12" md="3">
        <v-card>
          <v-card-text style="border-left: 4px solid rgb(var(--v-theme-primary)); padding-left: 20px">
            <div class="text-h3 font-weight-bold">{{ sourcesStore.sources.length }}</div>
            <div class="text-caption text-medium-emphasis">Total Sources</div>
          </v-card-text>
        </v-card>
      </v-col>

      <v-col cols="12" md="3">
        <v-card>
          <v-card-text style="border-left: 4px solid rgb(var(--v-theme-success)); padding-left: 20px">
            <div class="text-h3 font-weight-bold">{{ stats?.completed || 0 }}</div>
            <div class="text-caption text-medium-emphasis">Completed Downloads</div>
          </v-card-text>
        </v-card>
      </v-col>

      <v-col cols="12" md="3">
        <v-card>
          <v-card-text style="border-left: 4px solid rgb(var(--v-theme-error)); padding-left: 20px">
            <div class="text-h3 font-weight-bold">{{ stats?.active_failed || 0 }}</div>
            <div class="text-caption text-medium-emphasis">Failed Downloads</div>
          </v-card-text>
        </v-card>
      </v-col>

      <v-col cols="12" md="3">
        <v-card>
          <v-card-text style="border-left: 4px solid rgb(var(--v-theme-warning)); padding-left: 20px">
            <div class="text-h3 font-weight-bold">{{ activeDownloadsCount }}</div>
            <div class="text-caption text-medium-emphasis">Active Downloads</div>
            <div class="text-caption text-medium-emphasis" v-if="stats?.queued || stats?.running">
              {{ stats?.queued || 0 }} queued · {{ stats?.running || 0 }} running
            </div>
          </v-card-text>
        </v-card>
      </v-col>
    </v-row>

    <!-- Quick Actions & Status -->
    <v-row class="mt-4">
      <v-col cols="12">
        <v-card>
          <!-- Row 1: Action buttons -->
          <v-card-text class="d-flex align-center ga-3 flex-wrap pb-3">
            <v-btn
              color="primary"
              prepend-icon="mdi-refresh"
              :loading="checkingAll"
              @click="checkAllSources"
            >
              Check All Sources
            </v-btn>
            <v-btn
              color="warning"
              prepend-icon="mdi-replay"
              :loading="retryingAll"
              :disabled="!failedCount"
              @click="retryAllFailed"
            >
              Retry All Failed ({{ failedCount }})
            </v-btn>
            <v-btn
              color="secondary"
              variant="outlined"
              prepend-icon="mdi-broom"
              :loading="resettingOrphaned"
              :disabled="!stuckRunningCount"
              @click="resetOrphanedJobs"
            >
              Reset Stuck ({{ stuckRunningCount }})
            </v-btn>
          </v-card-text>

          <v-divider />

          <!-- Row 2: Status info -->
          <v-card-text class="d-flex align-center ga-2 flex-wrap pt-3">
            <v-icon size="small">mdi-key</v-icon>
            <span class="text-body-2 text-medium-emphasis mr-1">Auth:</span>
            <v-chip
              v-for="platform in supportedPlatforms"
              :key="platform"
              :color="credentialsStore.hasPlatformCredentials(platform) ? 'success' : 'grey'"
              :variant="credentialsStore.hasPlatformCredentials(platform) ? 'tonal' : 'outlined'"
              size="x-small"
              :to="credentialsStore.hasPlatformCredentials(platform) ? undefined : '/credentials'"
            >
              <v-icon start size="x-small">{{ getPlatformIcon(platform) }}</v-icon>
              {{ platform }}
            </v-chip>

            <v-divider vertical class="mx-2" />

            <div class="text-body-2 text-medium-emphasis d-flex align-center">
              <v-icon size="small" class="mr-1">mdi-harddisk</v-icon>
              Storage: {{ storageStats?.total_size_formatted || 'Calculating...' }}
              <span v-if="storageStats?.file_count" class="ml-2">
                ({{ storageStats.file_count.toLocaleString() }} files)
              </span>
              <v-tooltip v-if="storageStats?.calculated_at" location="bottom">
                <template v-slot:activator="{ props }">
                  <v-icon v-bind="props" size="x-small" class="ml-2">mdi-information-outline</v-icon>
                </template>
                <span>Updated: {{ formatDate(storageStats.calculated_at) }}</span>
              </v-tooltip>
              <v-btn
                icon
                size="x-small"
                variant="text"
                class="ml-1"
                :loading="refreshingStorage"
                @click="refreshStorageStats"
                title="Refresh storage stats"
              >
                <v-icon size="small">mdi-refresh</v-icon>
              </v-btn>
            </div>
          </v-card-text>
        </v-card>
      </v-col>
    </v-row>

    <v-row class="mt-4">
      <!-- Active Downloads (queued + running, auto-refresh) -->
      <v-col cols="12" md="4">
        <v-card>
          <v-card-title class="d-flex align-center">
            <v-icon class="mr-2" :class="{ 'mdi-spin': activeDownloads.length }">
              {{ activeDownloads.length ? 'mdi-loading' : 'mdi-download' }}
            </v-icon>
            Active
            <v-chip v-if="activeDownloads.length" size="small" color="info" class="ml-2">
              {{ activeDownloads.length }}
            </v-chip>
            <v-spacer />
            <v-btn
              v-if="activeDownloads.length"
              icon
              size="x-small"
              variant="text"
              @click="refreshActive"
            >
              <v-icon>mdi-refresh</v-icon>
            </v-btn>
          </v-card-title>
          <v-card-text>
            <v-list v-if="activeDownloads.length" density="compact">
              <v-list-item
                v-for="dl in activeDownloads"
                :key="dl.id"
                :class="{ 'download-running': dl.status === 'running' }"
              >
                <template v-slot:prepend>
                  <v-icon :color="dl.status === 'running' ? 'info' : 'warning'" size="small">
                    {{ dl.status === 'running' ? 'mdi-loading mdi-spin' : 'mdi-clock-outline' }}
                  </v-icon>
                </template>
                <v-list-item-title class="text-body-2">
                  {{ getDownloadLabel(dl) }}
                </v-list-item-title>
                <v-list-item-subtitle>
                  <v-chip size="x-small" :color="dl.status === 'running' ? 'info' : 'warning'" variant="tonal">
                    {{ dl.status }}
                  </v-chip>
                </v-list-item-subtitle>
              </v-list-item>
            </v-list>
            <div v-else class="text-center py-8">
              <v-icon size="48" color="secondary" :style="{ opacity: 0.5 }">mdi-check-circle-outline</v-icon>
              <div class="text-body-1 mt-2">No active downloads</div>
              <div class="text-caption text-medium-emphasis mt-1">All sources are idle</div>
            </div>
          </v-card-text>
        </v-card>
      </v-col>

      <!-- Recent Activity -->
      <v-col cols="12" md="8">
        <v-card>
          <v-card-title>
            Recent Activity
            <v-chip v-if="recentActivity.length" size="small" class="ml-2" variant="tonal">
              Last 7 days
            </v-chip>
          </v-card-title>
          <v-card-text>
            <v-list v-if="recentActivity.length">
              <v-list-item
                v-for="download in recentActivity"
                :key="download.id"
              >
                <template v-slot:prepend>
                  <v-icon :color="getStatusColor(download.status)">
                    {{ getStatusIcon(download.status) }}
                  </v-icon>
                </template>
                <v-list-item-title>
                  {{ getDownloadLabel(download) }}
                </v-list-item-title>
                <v-list-item-subtitle>
                  {{ formatRelativeTime(download.created_at) }}
                  <span v-if="download.file_count > 0" class="text-success ml-2">
                    {{ download.file_count }} new file{{ download.file_count !== 1 ? 's' : '' }}
                  </span>
                </v-list-item-subtitle>
                <template v-slot:append>
                  <v-chip
                    :color="getStatusColor(download.status)"
                    size="small"
                    variant="tonal"
                  >
                    {{ download.status === 'completed' ? 'new content' : download.status }}
                  </v-chip>
                </template>
              </v-list-item>
            </v-list>
            <div v-else class="text-center py-8">
              <v-icon size="48" color="secondary" :style="{ opacity: 0.5 }">mdi-history</v-icon>
              <div class="text-body-1 mt-2">No recent activity</div>
              <div class="text-caption text-medium-emphasis mt-1">Failures and new downloads appear here</div>
            </div>
          </v-card-text>
          <v-card-actions>
            <v-btn variant="text" to="/downloads">View All Downloads</v-btn>
          </v-card-actions>
        </v-card>
      </v-col>
    </v-row>

    <v-row class="mt-4">
      <!-- Sources needing attention -->
      <v-col cols="12">
        <v-card>
          <v-card-title>
            Sources Needing Attention
            <v-chip class="ml-2" color="error" size="small" v-if="totalFailingCount">
              {{ totalFailingCount }}
            </v-chip>
          </v-card-title>
          <v-card-text>
            <!-- Platform Health bars -->
            <div class="mb-4">
              <div class="text-caption text-medium-emphasis mb-2">Platform Health</div>
              <div
                v-for="row in platformHealth"
                :key="row.platform"
                class="d-flex align-center mb-2"
              >
                <v-icon :color="getPlatformColor(row.platform)" size="small" class="mr-2">
                  {{ getPlatformIcon(row.platform) }}
                </v-icon>
                <div class="text-body-2 platform-label">{{ row.platform }}</div>
                <v-progress-linear
                  :model-value="row.failing > 0 ? (row.failing / row.total) * 100 : 100"
                  :color="row.failing > 0 ? 'error' : 'success'"
                  height="12"
                  rounded
                  class="mx-3 flex-grow-1"
                />
                <div class="text-caption text-medium-emphasis count-label">
                  {{ row.failing }}/{{ row.total }}
                </div>
              </div>
              <div
                v-if="!platformHealth.length"
                class="text-caption text-medium-emphasis text-center py-2"
              >
                No enabled sources
              </div>
            </div>

            <v-divider class="my-3" />

            <!-- Failing Sources list -->
            <v-table v-if="failingSources.length" density="compact">
              <thead>
                <tr>
                  <th>Source</th>
                  <th>Consecutive failures</th>
                  <th>Last check</th>
                  <th>Actions</th>
                </tr>
              </thead>
              <tbody>
                <tr v-for="source in failingSources" :key="source.id">
                  <td>{{ getSourceLabel(source) }}</td>
                  <td>
                    <v-chip color="error" size="small">{{ source.error_count }}</v-chip>
                  </td>
                  <td>{{ formatDate(source.last_check) }}</td>
                  <td>
                    <v-btn
                      size="small"
                      variant="text"
                      color="primary"
                      @click="retrySource(source)"
                    >
                      Retry
                    </v-btn>
                    <v-btn size="small" variant="text" to="/subscriptions">
                      View
                      <v-tooltip activator="parent">View in Subscriptions</v-tooltip>
                    </v-btn>
                  </td>
                </tr>
              </tbody>
            </v-table>
            <div v-else class="text-caption text-medium-emphasis text-center py-3">
              No sources in failing state
            </div>
          </v-card-text>
        </v-card>
      </v-col>
    </v-row>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue'
import { useSourcesStore } from '../stores/sources'
import { useDownloadsStore } from '../stores/downloads'
import { useCredentialsStore } from '../stores/credentials'
import { useNotificationStore } from '../stores/notifications'
import { useSettingsStore } from '../stores/settings'
import { settingsApi, downloadsApi } from '../services/api'

const sourcesStore = useSourcesStore()
const downloadsStore = useDownloadsStore()
const credentialsStore = useCredentialsStore()
const notifications = useNotificationStore()
const settingsStore = useSettingsStore()

// Supported platforms for credential status
const supportedPlatforms = ['patreon', 'subscribestar', 'hentaifoundry', 'discord', 'pixiv', 'deviantart']

// State
const checkingAll = ref(false)
const retryingAll = ref(false)
const resettingOrphaned = ref(false)
const storageStats = ref(null)
const activeDownloads = ref([])
const loadingStats = ref(true)
const loadingActivity = ref(true)
const loadingStorage = ref(true)
const refreshingStorage = ref(false)
let refreshInterval = null

// Computed
const stats = computed(() => downloadsStore.stats)
const recentActivity = computed(() => downloadsStore.recentActivity)

// Read threshold from settings, default 5 if unset
const failureThreshold = computed(() =>
  settingsStore.settings['dashboard.failure_threshold'] ?? 5
)

// Per-platform health for platforms with ≥1 enabled source
const platformHealth = computed(() => {
  const enabled = sourcesStore.sources.filter(s => s.enabled)
  return supportedPlatforms
    .map(platform => {
      const sources = enabled.filter(s => s.platform === platform)
      if (sources.length === 0) return null
      const failing = sources.filter(
        s => (s.error_count || 0) >= failureThreshold.value
      ).length
      return { platform, total: sources.length, failing }
    })
    .filter(Boolean)
})

// Sources currently in failing state, most-recent-check first
const failingSources = computed(() => {
  return sourcesStore.sources
    .filter(s => s.enabled && (s.error_count || 0) >= failureThreshold.value)
    .sort((a, b) => new Date(b.last_check || 0) - new Date(a.last_check || 0))
})

const totalFailingCount = computed(() => failingSources.value.length)


const failedCount = computed(() => stats.value?.active_failed || 0)
const activeDownloadsCount = computed(() =>
  (stats.value?.queued || 0) + (stats.value?.running || 0)
)
// Running jobs that might be stuck (shows count for UI, actual stuck detection happens server-side)
const stuckRunningCount = computed(() => stats.value?.running || 0)

onMounted(() => {
  // Load data in background - DON'T await, let UI render immediately
  loadDashboardData()
  // Start auto-refresh for running downloads
  startAutoRefresh()
})

onUnmounted(() => {
  stopAutoRefresh()
})

function loadDashboardData() {
  // Fire off all requests in parallel, don't block UI
  // Each section handles its own loading state
  sourcesStore.fetchSources().catch(e => console.error('Failed to fetch sources:', e))
  credentialsStore.fetchCredentials().catch(e => console.error('Failed to fetch credentials:', e))
  settingsStore.fetchSettings().catch(e => console.error('Failed to fetch settings:', e))

  downloadsStore.fetchStats()
    .catch(e => console.error('Failed to fetch stats:', e))
    .finally(() => loadingStats.value = false)

  downloadsStore.fetchRecentActivity({ limit: 10 })
    .catch(e => console.error('Failed to fetch recent activity:', e))
    .finally(() => loadingActivity.value = false)

  fetchActiveDownloads()

  // Storage stats can be slow - load independently
  fetchStorageStats()
}

async function fetchActiveDownloads() {
  try {
    // Fetch both queued and running downloads
    const [queuedResponse, runningResponse] = await Promise.all([
      downloadsStore.fetchDownloads({ status: 'queued', per_page: 20 }),
      downloadsStore.fetchDownloads({ status: 'running', per_page: 20 }),
    ])
    // Combine and sort: running first, then queued
    const running = runningResponse.items.filter(d => d.status === 'running')
    const queued = queuedResponse.items.filter(d => d.status === 'queued')
    activeDownloads.value = [...running, ...queued]
  } catch (e) {
    console.error('Failed to fetch active downloads:', e)
  }
}

async function fetchStorageStats() {
  loadingStorage.value = true
  try {
    const response = await settingsApi.get()
    storageStats.value = response.data.storage_stats
  } catch (e) {
    console.error('Failed to fetch storage stats:', e)
  } finally {
    loadingStorage.value = false
  }
}

async function refreshStorageStats() {
  refreshingStorage.value = true
  try {
    await settingsApi.refreshStorageStats()
    notifications.success('Storage stats refresh queued')
    // Wait a moment then fetch updated stats
    setTimeout(() => fetchStorageStats(), 3000)
  } catch (e) {
    console.error('Failed to refresh storage stats:', e)
    notifications.error('Failed to refresh storage stats')
  } finally {
    refreshingStorage.value = false
  }
}

function startAutoRefresh() {
  // Refresh active downloads every 5 seconds when there are active downloads
  refreshInterval = setInterval(async () => {
    if (activeDownloads.value.length > 0 || activeDownloadsCount.value > 0) {
      await fetchActiveDownloads()
      await downloadsStore.fetchStats()
      await downloadsStore.fetchRecentActivity({ limit: 10 })
    }
  }, 5000)
}

function stopAutoRefresh() {
  if (refreshInterval) {
    clearInterval(refreshInterval)
    refreshInterval = null
  }
}

async function refreshActive() {
  await fetchActiveDownloads()
}

async function checkAllSources() {
  checkingAll.value = true
  try {
    const enabledSources = sourcesStore.sources.filter(s => s.enabled)
    const results = await Promise.allSettled(
      enabledSources.map(source => sourcesStore.triggerCheck(source.id))
    )
    const queued = results.filter(r => r.status === 'fulfilled').length
    const failed = results.filter(r => r.status === 'rejected').length
    if (failed > 0) {
      notifications.success(`Queued ${queued} sources (${failed} failed to queue)`)
    } else {
      notifications.success(`Queued checks for ${queued} sources`)
    }
    await fetchActiveDownloads()
    await downloadsStore.fetchStats()
  } catch (error) {
    notifications.error(`Failed to check sources: ${error.message}`)
  } finally {
    checkingAll.value = false
  }
}

async function retryAllFailed() {
  retryingAll.value = true
  try {
    const response = await downloadsStore.fetchDownloads({ status: 'failed', per_page: 100, exclude_superseded: true })
    const failed = response.items
    let retried = 0
    for (const dl of failed) {
      try {
        await downloadsStore.retryDownload(dl.id)
        retried++
      } catch (e) {
        console.error(`Failed to retry ${dl.id}:`, e)
      }
    }
    notifications.success(`Queued retry for ${retried} downloads`)
    await downloadsStore.fetchStats()
    await fetchActiveDownloads()
  } catch (error) {
    notifications.error(`Failed to retry downloads: ${error.message}`)
  } finally {
    retryingAll.value = false
  }
}

async function resetOrphanedJobs() {
  resettingOrphaned.value = true
  try {
    const response = await downloadsApi.resetOrphaned(0)  // 0 = reset all running
    notifications.success(response.data.message || `Reset ${response.data.reset_count} stuck jobs`)
    await downloadsStore.fetchStats()
    await fetchActiveDownloads()
  } catch (error) {
    notifications.error(`Failed to reset stuck jobs: ${error.message}`)
  } finally {
    resettingOrphaned.value = false
  }
}

function getStatusIcon(status) {
  const icons = {
    completed: 'mdi-check-circle',
    failed: 'mdi-alert-circle',
    running: 'mdi-loading mdi-spin',
    queued: 'mdi-clock-outline',
    pending: 'mdi-clock-outline',
    skipped: 'mdi-skip-next',
  }
  return icons[status] || 'mdi-help-circle'
}

function getPlatformIcon(platform) {
  const icons = {
    patreon: 'mdi-patreon',
    subscribestar: 'mdi-star',
    hentaifoundry: 'mdi-palette',
    discord: 'mdi-discord',
    pixiv: 'mdi-alpha-p-box',
    deviantart: 'mdi-deviantart',
  }
  return icons[platform] || 'mdi-web'
}

function getStatusColor(status) {
  const colors = {
    completed: 'success',
    failed: 'error',
    running: 'info',
    queued: 'warning',
    pending: 'warning',
    skipped: 'grey',
  }
  return colors[status] || 'grey'
}

function formatDate(dateStr) {
  if (!dateStr) return 'Never'
  return new Date(dateStr).toLocaleString()
}

function formatRelativeTime(dateStr) {
  if (!dateStr) return 'Unknown'
  const date = new Date(dateStr)
  const now = new Date()
  const diffMs = now - date
  const diffMins = Math.floor(diffMs / 60000)
  const diffHours = Math.floor(diffMs / 3600000)
  const diffDays = Math.floor(diffMs / 86400000)

  if (diffMins < 1) return 'Just now'
  if (diffMins < 60) return `${diffMins} min${diffMins !== 1 ? 's' : ''} ago`
  if (diffHours < 24) return `${diffHours} hour${diffHours !== 1 ? 's' : ''} ago`
  if (diffDays < 7) return `${diffDays} day${diffDays !== 1 ? 's' : ''} ago`
  return date.toLocaleDateString()
}

function truncate(str, length) {
  if (!str) return ''
  if (str.length <= length) return str
  return str.substring(0, length) + '...'
}

function getDownloadLabel(download) {
  if (download.subscription_name && download.platform) {
    return `${download.subscription_name}:${download.platform}`
  }
  // Fallback to truncated URL if source info not available
  return truncate(download.url, 35)
}

function getSourceLabel(source) {
  const name = source.subscription_name || source.subscription?.name || 'Unknown'
  return `${name}:${source.platform}`
}

async function retrySource(source) {
  try {
    await sourcesStore.triggerCheck(source.id)
    notifications.success(`Queued check for ${getSourceLabel(source)}`)
    // Refresh recent activity after retrying
    await downloadsStore.fetchRecentActivity({ limit: 10 })
  } catch (error) {
    notifications.error(`Failed to queue check: ${error.message}`)
  }
}
</script>

<style scoped>
.download-running {
  border-left: 3px solid rgb(var(--v-theme-primary));
  animation: pulse-border 2s ease-in-out infinite;
}

@keyframes pulse-border {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0.4; }
}

.platform-label {
  min-width: 110px;
  text-transform: capitalize;
}

.count-label {
  min-width: 50px;
  text-align: right;
}
</style>
