'use client'

import { useCallback, useEffect, useRef, useState } from 'react'
import { cn } from '@/lib/utils'
import { getAgentTasks, getAgentActions } from '@/lib/api/agent'
import type { AgentAction, AgentTask } from '@/lib/api/agent'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/Card'
import { Badge } from '@/components/ui/Badge'
import { Skeleton } from '@/components/ui/Skeleton'
import { EmptyState } from '@/components/ui/EmptyState'
import { ErrorState } from '@/components/ui/ErrorState'
import {
  Activity, Zap, AlertTriangle,
  Database, Search, Truck, Package, CreditCard, CheckCircle2,
  Eye, ExternalLink, PlayCircle,
} from 'lucide-react'
import { TASK_STATUS_LABELS, formatRelativeTime } from '@/lib/types'
import { createClient } from '@/lib/supabase/client'
import { useBusiness } from '@/components/providers/BusinessProvider'

interface ActivityItem {
  id: string
  type: 'task' | 'action' | 'audit'
  timestamp: string
  title: string
  description: string
  status: string
  icon: React.ComponentType<{ className?: string }>
  color: string
  taskId?: string
  details?: Record<string, unknown>
}

// --- icon/color helpers (pure, module-level) ---

function getActionIcon(toolName: string): React.ComponentType<{ className?: string }> {
  const icons: Record<string, React.ComponentType<{ className?: string }>> = {
    get_order: Search,
    check_inventory: Package,
    reserve_inventory: Database,
    update_order_status: Activity,
    send_customer_notification: Activity,
    find_suppliers: Truck,
    compare_supplier_options: CreditCard,
    request_approval: AlertTriangle,
    submit_purchase_request: CreditCard,
    fulfill_purchase_request: Package,
    deliver_order: CheckCircle2,
  }
  return icons[toolName] || Zap
}

function getStatusColor(status: string): string {
  switch (status) {
    case 'completed': return 'text-emerald-500'
    case 'running': return 'text-blue-500'
    case 'failed': return 'text-red-500'
    default: return 'text-gray-500'
  }
}

function getAuditLabel(action: string): string {
  const labels: Record<string, string> = {
    'agent_task.started': 'Agent Task Started',
    'agent_task.completed': 'Agent Task Completed',
    'agent_task.failed': 'Agent Task Failed',
    'agent.shortage_detected': 'Shortage Detected',
    'agent.supplier_discovery': 'Supplier Discovery',
    'agent.supplier_comparison': 'Supplier Comparison',
    'agent.approval_requested': 'Approval Requested',
    'agent.approval_granted': 'Approval Granted',
    'agent.approval_rejected': 'Approval Rejected',
    'agent.purchase_submitted': 'Purchase Submitted',
    'agent.purchase_fulfilled': 'Purchase Fulfilled',
    'agent.order_ready': 'Order Ready',
    'agent.order_delivered': 'Order Delivered',
    'agent.customer_notified': 'Customer Notified',
  }
  return labels[action] || action
}

function getAuditIcon(action: string): React.ComponentType<{ className?: string }> {
  const icons: Record<string, React.ComponentType<{ className?: string }>> = {
    'agent_task.started': PlayCircle,
    'agent_task.completed': CheckCircle2,
    'agent_task.failed': AlertTriangle,
    'agent.shortage_detected': AlertTriangle,
    'agent.supplier_discovery': Truck,
    'agent.supplier_comparison': CreditCard,
    'agent.approval_requested': AlertTriangle,
    'agent.approval_granted': CheckCircle2,
    'agent.approval_rejected': AlertTriangle,
    'agent.purchase_submitted': CreditCard,
    'agent.purchase_fulfilled': Package,
    'agent.order_ready': CheckCircle2,
    'agent.order_delivered': Truck,
    'agent.customer_notified': Activity,
  }
  return icons[action] || Zap
}

function getAuditColor(action: string): string {
  if (action.includes('completed') || action.includes('granted') || action.includes('fulfilled') || action.includes('delivered')) return 'text-emerald-500'
  if (action.includes('failed') || action.includes('rejected')) return 'text-red-500'
  if (action.includes('detected') || action.includes('requested')) return 'text-amber-500'
  if (action.includes('started') || action.includes('discovery') || action.includes('comparison')) return 'text-blue-500'
  return 'text-indigo-500'
}

// --- component ---

export function ActivityPanel({ limit = 20 }: { limit?: number }) {
  const { business } = useBusiness()
  const [items, setItems] = useState<ActivityItem[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [expanded, setExpanded] = useState<Set<string>>(new Set())
  const [live, setLive] = useState(false)

  // Prevents state updates after unmount
  const mountedRef = useRef(true)
  useEffect(() => {
    mountedRef.current = true
    return () => { mountedRef.current = false }
  }, [])

  const loadActivity = useCallback(async () => {
    try {
      const tasksRes = await getAgentTasks({ limit: limit * 2 })
      if (!tasksRes.success) throw new Error(tasksRes.message)
      const tasks: AgentTask[] = tasksRes.data.tasks
      if (!mountedRef.current) return

      if (tasks.length === 0) {
        setItems([])
        setError(null)
        return
      }

      const allItems: ActivityItem[] = []

      // 1) Audit trail events for recent tasks (single batched query)
      const supabase = createClient()
      if (supabase) {
        const recentIds = tasks.slice(0, 5).map(t => t.id)
        const { data: audits } = await supabase
          .from('audit_logs')
          .select('*')
          .in('task_id', recentIds)
          .order('created_at', { ascending: false })
          .limit(limit)
        if (mountedRef.current && audits) {
          for (const audit of audits) {
            allItems.push({
              id: `audit-${audit.id}`,
              type: 'audit',
              timestamp: audit.created_at,
              title: getAuditLabel(audit.action),
              description: audit.entity_type ? `${audit.entity_type}: ${String(audit.entity_id).slice(0, 8)}` : 'System event',
              status: 'completed',
              icon: getAuditIcon(audit.action),
              color: getAuditColor(audit.action),
              taskId: audit.task_id,
              details: (audit.metadata as Record<string, unknown>) || {},
            })
          }
        }
      }

      // 2) Tool-level actions for recent tasks
      for (const task of tasks.slice(0, 8)) {
        const actionsRes = await getAgentActions(task.id)
        if (!actionsRes.success || !mountedRef.current) continue
        for (const action of actionsRes.data.actions as AgentAction[]) {
          allItems.push({
            id: `action-${action.id}`,
            type: 'action',
            timestamp: action.started_at,
            title: action.description || action.tool_name,
            description: `Tool: ${action.tool_name}`,
            status: action.status,
            icon: getActionIcon(action.tool_name),
            color: getStatusColor(action.status),
            taskId: task.id,
            details: { input: action.input_data, output: action.output_data },
          })
        }
      }

      // 3) Task lifecycle events
      for (const task of tasks.slice(0, 5)) {
        allItems.push({
          id: `task-${task.id}-${task.started_at}`,
          type: 'task',
          timestamp: task.started_at,
          title: `Task: ${task.objective}`,
          description: `Status: ${TASK_STATUS_LABELS[task.status as keyof typeof TASK_STATUS_LABELS] || task.status}`,
          status: task.status,
          icon: Activity,
          color: 'text-indigo-500',
          taskId: task.id,
          details: { task_type: task.task_type, priority: task.priority, current_step: task.current_step },
        })
      }

      allItems.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())

      if (mountedRef.current) {
        setItems(allItems.slice(0, limit))
        setError(null)
      }
    } catch (err) {
      if (mountedRef.current) {
        setError(err instanceof Error ? err.message : 'Failed to load activity')
      }
    } finally {
      if (mountedRef.current) setLoading(false)
    }
  }, [limit])

  // Initial load + polling fallback (always active; realtime only adds instant refreshes)
  useEffect(() => {
    loadActivity()
    const interval = setInterval(loadActivity, 5000)
    return () => clearInterval(interval)
  }, [loadActivity])

  // Supabase Realtime (best-effort). Failure never breaks the panel;
  // polling above remains the reliable fallback.
  useEffect(() => {
    const businessId = business?.businessId
    if (!businessId) return

    const supabase = createClient()
    if (!supabase) return

    const channel = supabase
      .channel(`imbaraga-agent-tasks-${businessId}`)
      .on(
        'postgres_changes',
        {
          event: '*',
          schema: 'public',
          table: 'agent_tasks',
          filter: `business_id=eq.${businessId}`,
        },
        () => { loadActivity() }
      )
      .subscribe((status: string) => {
        if (mountedRef.current) setLive(status === 'SUBSCRIBED')
      })

    return () => {
      supabase.removeChannel(channel)
      if (mountedRef.current) setLive(false)
    }
  }, [business?.businessId, loadActivity])

  function toggleExpand(id: string) {
    setExpanded(prev => {
      const next = new Set(prev)
      if (next.has(id)) next.delete(id)
      else next.add(id)
      return next
    })
  }

  const header = (
    <CardTitle className="flex items-center gap-2">
      <Activity className="h-5 w-5 text-indigo-600" aria-hidden="true" />
      Agent Activity Timeline
      {live && (
        <span className="ml-1 inline-flex items-center gap-1 text-xs font-normal text-emerald-600 dark:text-emerald-400">
          <span className="h-1.5 w-1.5 rounded-full bg-emerald-500 animate-pulse" aria-hidden="true" />
          Live
        </span>
      )}
    </CardTitle>
  )

  if (loading && items.length === 0) {
    return (
      <Card>
        <CardHeader>{header}</CardHeader>
        <CardContent>
          <div className="space-y-4" aria-busy="true" aria-label="Loading agent activity">
            {Array.from({ length: 4 }).map((_, i) => (
              <div key={i} className="flex gap-4">
                <div className="h-10 w-10 flex-shrink-0 animate-pulse rounded-full bg-gray-200 dark:bg-gray-700" />
                <div className="flex-1 space-y-2">
                  <Skeleton className="h-4 w-1/2" />
                  <Skeleton className="h-3 w-1/3" />
                </div>
              </div>
            ))}
          </div>
        </CardContent>
      </Card>
    )
  }

  if (error && items.length === 0) {
    return (
      <Card>
        <CardHeader>{header}</CardHeader>
        <CardContent>
          <ErrorState message={error} onRetry={loadActivity} />
        </CardContent>
      </Card>
    )
  }

  if (items.length === 0) {
    return (
      <Card>
        <CardHeader>{header}</CardHeader>
        <CardContent>
          <EmptyState
            icon={Activity}
            title="No agent activity yet"
            description="Create an order to see IMBARAGA in action"
          />
        </CardContent>
      </Card>
    )
  }

  return (
    <Card>
      <CardHeader>
        {header}
        <span className="text-xs font-normal text-gray-500 dark:text-gray-400">
          {items.length} events
        </span>
      </CardHeader>
      <CardContent className="p-0">
        <ol className="divide-y divide-gray-200 dark:divide-gray-700" aria-label="Agent activity events">
          {items.map((item, index) => {
            const isExpanded = expanded.has(item.id)
            const hasDetails = !!item.details && Object.keys(item.details).length > 0
            return (
              <li key={item.id} className="flex gap-4 p-4 transition-colors hover:bg-gray-50 dark:hover:bg-gray-800/50">
                <div className="relative flex-shrink-0">
                  <div className={cn('flex h-10 w-10 items-center justify-center rounded-full bg-gray-100 dark:bg-gray-800')}>
                    <item.icon className={cn('h-5 w-5', item.color)} aria-hidden="true" />
                  </div>
                  {index < items.length - 1 && (
                    <div className="absolute left-5 top-10 bottom-0 w-0.5 bg-gray-200 dark:bg-gray-700" aria-hidden="true" />
                  )}
                </div>
                <div className="min-w-0 flex-1 pt-1">
                  <div className="flex flex-wrap items-center gap-2">
                    <span className="font-medium text-gray-900 dark:text-white">{item.title}</span>
                    <Badge
                      variant={
                        item.status === 'completed' ? 'success' :
                        item.status === 'running' ? 'info' :
                        item.status === 'failed' ? 'danger' : 'default'
                      }
                    >
                      {item.status}
                    </Badge>
                    {hasDetails && (
                      <button
                        type="button"
                        onClick={() => toggleExpand(item.id)}
                        className="ml-auto rounded p-1 text-gray-400 hover:bg-gray-100 hover:text-gray-600 dark:hover:bg-gray-800 dark:hover:text-gray-300"
                        aria-label={isExpanded ? `Collapse details for ${item.title}` : `Expand details for ${item.title}`}
                        aria-expanded={isExpanded}
                      >
                        {isExpanded ? <Eye className="h-4 w-4" /> : <ExternalLink className="h-4 w-4" />}
                      </button>
                    )}
                  </div>
                  <p className="mt-0.5 text-sm text-gray-500 dark:text-gray-400">{item.description}</p>
                  <p className="mt-1 text-xs text-gray-400 dark:text-gray-500">
                    <time dateTime={item.timestamp}>{formatRelativeTime(item.timestamp)}</time>
                  </p>

                  {isExpanded && hasDetails && (
                    <div className="mt-3 animate-slide-down rounded-lg border border-gray-200 bg-gray-50 p-3 dark:border-gray-700 dark:bg-gray-800/50">
                      <pre className="max-h-64 overflow-auto text-xs text-gray-600 dark:text-gray-400">
                        {JSON.stringify(item.details, null, 2)}
                      </pre>
                    </div>
                  )}
                </div>
              </li>
            )
          })}
        </ol>
      </CardContent>
    </Card>
  )
}