import { useCallback, useEffect, useMemo, useState } from 'react'
import {
  pendingLinkagesApi,
  PendingLinkageResponse,
  ReviewDecision,
} from '../api/pendingLinkages'
import { apiClient } from '../api/client'
import { useAuth } from '../context/AuthContext'
import { videosApi } from '../api/videos'

type DecisionValue = 'approve' | 'deny'

type SortKey = 'photo' | 'tag' | 'submitted_by' | 'submitted_at' | 'status'

function formatDate(value: string | null | undefined): string {
  if (!value) {
    return '-'
  }
  try {
    return new Date(value).toLocaleString()
  } catch (error) {
    console.error('Failed to format date', error)
    return value
  }
}

export default function UserTaggedPhotos() {
  const { isAdmin } = useAuth()
  const [linkages, setLinkages] = useState<PendingLinkageResponse[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [statusFilter, setStatusFilter] = useState<string>('pending')
  const [decisions, setDecisions] = useState<Record<number, DecisionValue | null>>({})
  const [submitting, setSubmitting] = useState(false)
  const [clearing, setClearing] = useState(false)
  const [sortBy, setSortBy] = useState<SortKey>('submitted_at')
  const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('desc')

  const loadLinkages = useCallback(async () => {
    setLoading(true)
    setError(null)
    try {
      const response = await pendingLinkagesApi.listPendingLinkages(
        statusFilter || undefined
      )
      setLinkages(response.items)
      setDecisions({})
    } catch (err: any) {
      setError(err.response?.data?.detail || err.message || 'Failed to load user tagged photos')
      console.error('Error loading pending linkages:', err)
    } finally {
      setLoading(false)
    }
  }, [statusFilter])

  useEffect(() => {
    loadLinkages()
  }, [loadLinkages])

  const pendingCount = useMemo(
    () => linkages.filter((item) => item.status === 'pending').length,
    [linkages]
  )

  const sortedLinkages = useMemo(() => {
    const items = [...linkages]
    items.sort((a, b) => {
      const direction = sortDirection === 'asc' ? 1 : -1

      const compareStrings = (x: string | null | undefined, y: string | null | undefined) =>
        (x || '').localeCompare(y || '', undefined, { sensitivity: 'base' })

      if (sortBy === 'photo') {
        return (a.photo_id - b.photo_id) * direction
      }

      if (sortBy === 'tag') {
        const aTag = a.resolved_tag_name || a.proposed_tag_name || ''
        const bTag = b.resolved_tag_name || b.proposed_tag_name || ''
        return compareStrings(aTag, bTag) * direction
      }

      if (sortBy === 'submitted_by') {
        const aName = a.user_name || a.user_email || ''
        const bName = b.user_name || b.user_email || ''
        return compareStrings(aName, bName) * direction
      }

      if (sortBy === 'submitted_at') {
        const aTime = a.created_at || ''
        const bTime = b.created_at || ''
        return (aTime < bTime ? -1 : aTime > bTime ? 1 : 0) * direction
      }

      if (sortBy === 'status') {
        return compareStrings(a.status, b.status) * direction
      }

      return 0
    })
    return items
  }, [linkages, sortBy, sortDirection])

  const toggleSort = (key: SortKey) => {
    setSortBy((currentKey) => {
      if (currentKey === key) {
        setSortDirection((currentDirection) => (currentDirection === 'asc' ? 'desc' : 'asc'))
        return currentKey
      }
      setSortDirection('asc')
      return key
    })
  }

  const renderSortLabel = (label: string, key: SortKey) => {
    const isActive = sortBy === key
    const directionSymbol = !isActive ? '↕' : sortDirection === 'asc' ? '▲' : '▼'
    return (
      <button
        type="button"
        onClick={() => toggleSort(key)}
        className="inline-flex items-center gap-1 text-xs font-medium text-gray-500 uppercase tracking-wider hover:text-gray-700"
      >
        <span>{label}</span>
        <span className="text-[10px]">{directionSymbol}</span>
      </button>
    )
  }

  const hasPendingDecision = useMemo(
    () =>
      Object.entries(decisions).some(([id, value]) => {
        const linkage = linkages.find((item) => item.id === Number(id))
        return value !== null && linkage?.status === 'pending'
      }),
    [decisions, linkages]
  )

  const handleDecisionChange = (id: number, nextDecision: DecisionValue) => {
    setDecisions((prev) => {
      const current = prev[id] ?? null
      const toggled = current === nextDecision ? null : nextDecision
      return {
        ...prev,
        [id]: toggled,
      }
    })
  }

  const handleSelectAllApprove = () => {
    const pendingIds = linkages
      .filter((item) => item.status === 'pending')
      .map((item) => item.id)

    if (pendingIds.length === 0) {
      return
    }

    const newDecisions: Record<number, DecisionValue> = {}
    pendingIds.forEach((id) => {
      newDecisions[id] = 'approve'
    })

    setDecisions((prev) => ({
      ...prev,
      ...newDecisions,
    }))
  }

  const handleSelectAllDeny = () => {
    const pendingIds = linkages
      .filter((item) => item.status === 'pending')
      .map((item) => item.id)

    if (pendingIds.length === 0) {
      return
    }

    const newDecisions: Record<number, DecisionValue> = {}
    pendingIds.forEach((id) => {
      newDecisions[id] = 'deny'
    })

    setDecisions((prev) => ({
      ...prev,
      ...newDecisions,
    }))
  }

  const handleSubmit = async () => {
    const decisionsList: ReviewDecision[] = Object.entries(decisions)
      .filter(([id, decision]) => {
        const linkage = linkages.find((item) => item.id === Number(id))
        return decision !== null && linkage?.status === 'pending'
      })
      .map(([id, decision]) => ({
        id: Number(id),
        decision: decision as DecisionValue,
      }))

    if (decisionsList.length === 0) {
      alert('Select Approve or Deny for at least one pending tag.')
      return
    }

    const approveCount = decisionsList.filter((item) => item.decision === 'approve').length
    const denyCount = decisionsList.length - approveCount

    const confirmMessage = [
      `Submit ${decisionsList.length} decision(s)?`,
      approveCount ? `✅ Approve: ${approveCount}` : null,
      denyCount ? `❌ Deny: ${denyCount}` : null,
    ]
      .filter(Boolean)
      .join('\n')

    if (!confirm(confirmMessage)) {
      return
    }

    setSubmitting(true)
    try {
      const response = await pendingLinkagesApi.reviewPendingLinkages({
        decisions: decisionsList,
      })

      const summary = [
        `Approved: ${response.approved}`,
        `Denied: ${response.denied}`,
        response.tags_created ? `New tags: ${response.tags_created}` : null,
        response.linkages_created ? `New linkages: ${response.linkages_created}` : null,
        response.errors.length ? `Errors: ${response.errors.join('; ')}` : null,
      ]
        .filter(Boolean)
        .join('\n')

      alert(summary || 'Review complete.')
      await loadLinkages()
      setDecisions({})
    } catch (err: any) {
      const message = err.response?.data?.detail || err.message || 'Failed to submit decisions'
      alert(message)
      console.error('Error submitting pending linkage decisions:', err)
    } finally {
      setSubmitting(false)
    }
  }

  const handleClearDatabase = async () => {
    const confirmMessage = [
      'Delete all approved and denied records?',
      '',
      'Only records with Pending status will remain.',
      'This action cannot be undone.',
    ].join('\n')

    if (!confirm(confirmMessage)) {
      return
    }

    setClearing(true)
    try {
      const response = await pendingLinkagesApi.cleanupPendingLinkages()
      const summary = [
        `✅ Deleted ${response.deleted_records} record(s)`,
        response.warnings && response.warnings.length > 0
          ? `ℹ️ ${response.warnings.join('; ')}`
          : '',
        response.errors.length > 0 ? `⚠️ ${response.errors.join('; ')}` : '',
      ]
        .filter(Boolean)
        .join('\n')

      alert(summary || 'Cleanup complete.')

      if (response.errors.length > 0) {
        console.error('Cleanup errors:', response.errors)
      }
      if (response.warnings && response.warnings.length > 0) {
        console.info('Cleanup warnings:', response.warnings)
      }

      await loadLinkages()
    } catch (err: any) {
      const errorMessage =
        err.response?.data?.detail || err.message || 'Failed to cleanup pending linkages'
      alert(`Error: ${errorMessage}`)
      console.error('Error clearing pending linkages:', err)
    } finally {
      setClearing(false)
    }
  }

  return (
    <div className="space-y-6">
      <div className="flex flex-col gap-4">
        <div>
          <p className="text-gray-600">
            Review tags suggested by users. Approving creates/links the tag to the selected photo.
          </p>
        </div>

        <div className="flex flex-wrap items-center gap-4">
          <label className="text-sm font-medium text-gray-700 flex items-center gap-2">
            Status
            <select
              value={statusFilter}
              onChange={(event) => setStatusFilter(event.target.value)}
              className="border border-gray-300 rounded-md px-3 py-1 text-sm"
            >
              <option value="pending">Pending</option>
              <option value="">All Statuses</option>
              <option value="approved">Approved</option>
              <option value="denied">Denied</option>
            </select>
          </label>

          <button
            type="button"
            onClick={loadLinkages}
            className="inline-flex items-center px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50"
          >
            Refresh
          </button>

          <div className="text-sm text-gray-500">
            Pending items: <span className="font-semibold text-gray-800">{pendingCount}</span>
          </div>

          <div className="flex-1" />

          {linkages.filter((item) => item.status === 'pending').length > 0 && (
            <div className="flex items-center gap-2">
              <button
                type="button"
                onClick={handleSelectAllApprove}
                className="px-4 py-1 text-sm bg-gray-200 text-gray-700 rounded-md hover:bg-gray-300 font-medium"
              >
                Select All to Approve
              </button>
              <button
                type="button"
                onClick={handleSelectAllDeny}
                className="px-4 py-1 text-sm bg-gray-200 text-gray-700 rounded-md hover:bg-gray-300 font-medium"
              >
                Select All to Deny
              </button>
            </div>
          )}

          <button
            type="button"
            onClick={handleSubmit}
            disabled={submitting || loading || !hasPendingDecision}
            className={`inline-flex items-center px-4 py-2 rounded-md text-sm font-semibold text-white ${
              submitting || loading || !hasPendingDecision
                ? 'bg-gray-400 cursor-not-allowed'
                : 'bg-blue-600 hover:bg-blue-700'
            }`}
          >
            {submitting ? 'Submitting...' : 'Submit Decisions'}
          </button>
        </div>

        <div className="flex flex-wrap items-center gap-3">
          <button
            onClick={() => {
              if (!isAdmin) {
                return
              }
              handleClearDatabase()
            }}
            disabled={clearing || !isAdmin}
            className="px-3 py-1.5 text-sm bg-red-100 text-red-700 rounded-md hover:bg-red-200 disabled:bg-gray-200 disabled:text-gray-500 disabled:cursor-not-allowed font-medium"
            title={
              isAdmin
                ? 'Delete approved/denied records'
                : 'Only admins can clear pending linkages'
            }
          >
            {clearing ? 'Clearing...' : '🗑️ Clear Database'}
          </button>
          <span className="text-sm text-gray-700">
            Clear approved/denied records
          </span>
        </div>
      </div>

      {error && (
        <div className="bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded-md">
          {error}
        </div>
      )}

      {loading ? (
        <div className="flex items-center justify-center h-64 text-gray-500">Loading...</div>
      ) : linkages.length === 0 ? (
        <div className="bg-white border border-gray-200 rounded-lg p-6 text-center text-gray-500">
          No user tagged photos found for this filter.
        </div>
      ) : (
        <div className="bg-white border border-gray-200 rounded-lg shadow-sm overflow-hidden">
          <div className="overflow-x-auto">
            <table className="min-w-full divide-y divide-gray-200">
              <thead className="bg-gray-50">
                <tr>
                  <th scope="col" className="px-6 py-3 text-left">
                    {renderSortLabel('Photo', 'photo')}
                  </th>
                  <th scope="col" className="px-6 py-3 text-left">
                    {renderSortLabel('Proposed Tag', 'tag')}
                  </th>
                  <th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                    Current Tags
                  </th>
                  <th scope="col" className="px-6 py-3 text-left">
                    {renderSortLabel('Submitted By', 'submitted_by')}
                  </th>
                  <th scope="col" className="px-6 py-3 text-left">
                    {renderSortLabel('Submitted At', 'submitted_at')}
                  </th>
                  <th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                    Notes
                  </th>
                  <th scope="col" className="px-6 py-3 text-left">
                    {renderSortLabel('Status', 'status')}
                  </th>
                  <th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                    Decision
                  </th>
                </tr>
              </thead>
              <tbody className="bg-white divide-y divide-gray-200">
                {sortedLinkages.map((linkage) => {
                  const canReview = linkage.status === 'pending'
                  const decision = decisions[linkage.id] ?? null
                  return (
                    <tr key={linkage.id} className={canReview ? '' : 'opacity-70 bg-gray-50'}>
                      <td className="px-6 py-4 whitespace-nowrap">
                        {linkage.photo_id ? (
                          <div
                            className="cursor-pointer hover:opacity-90 transition-opacity w-24"
                            onClick={() => {
                              const isVideo = linkage.photo_media_type === 'video'
                              const url = isVideo
                                ? videosApi.getVideoUrl(linkage.photo_id)
                                : `${apiClient.defaults.baseURL}/api/v1/photos/${linkage.photo_id}/image`
                              window.open(url, '_blank')
                            }}
                            title={linkage.photo_media_type === 'video' ? 'Open video in new tab' : 'Open photo in new tab'}
                          >
                            {linkage.photo_media_type === 'video' ? (
                              <img
                                src={videosApi.getThumbnailUrl(linkage.photo_id)}
                                alt={`Video ${linkage.photo_id}`}
                                className="w-24 h-24 object-cover rounded border border-gray-300"
                                loading="lazy"
                                onError={(event) => {
                                  const target = event.target as HTMLImageElement
                                  target.style.display = 'none'
                                  const parent = target.parentElement
                                  if (parent && !parent.querySelector('.fallback-text')) {
                                    const fallback = document.createElement('div')
                                    fallback.className = 'fallback-text text-gray-400 text-xs text-center'
                                    fallback.textContent = `#${linkage.photo_id}`
                                    parent.appendChild(fallback)
                                  }
                                }}
                              />
                            ) : (
                              <img
                                src={`/api/v1/photos/${linkage.photo_id}/image`}
                                alt={`Photo ${linkage.photo_id}`}
                                className="w-24 h-24 object-cover rounded border border-gray-300"
                                loading="lazy"
                                onError={(event) => {
                                  const target = event.target as HTMLImageElement
                                  target.style.display = 'none'
                                  const parent = target.parentElement
                                  if (parent && !parent.querySelector('.fallback-text')) {
                                    const fallback = document.createElement('div')
                                    fallback.className = 'fallback-text text-gray-400 text-xs text-center'
                                    fallback.textContent = `#${linkage.photo_id}`
                                    parent.appendChild(fallback)
                                  }
                                }}
                              />
                            )}
                          </div>
                        ) : (
                          <div className="text-xs text-gray-400">Photo not found</div>
                        )}
                        <div className="text-xs text-gray-500 mt-1">
                          {linkage.photo_filename || `Photo #${linkage.photo_id}`}
                        </div>
                      </td>
                      <td className="px-6 py-4 whitespace-nowrap">
                        <div className="flex flex-col">
                          <span className="text-sm font-medium text-gray-900">
                            {linkage.resolved_tag_name || linkage.proposed_tag_name || '-'}
                          </span>
                          {linkage.tag_id === null && linkage.proposed_tag_name && (
                            <span className="text-xs text-yellow-700 bg-yellow-50 px-2 py-0.5 rounded mt-1 inline-flex items-center gap-1">
                              <span>New tag</span>
                            </span>
                          )}
                          {linkage.tag_id && (
                            <span className="text-xs text-green-700 bg-green-50 px-2 py-0.5 rounded mt-1 inline-flex items-center gap-1">
                              <span>Existing tag</span>
                              <span>#{linkage.tag_id}</span>
                            </span>
                          )}
                        </div>
                      </td>
                      <td className="px-6 py-4">
                        {linkage.photo_tags.length === 0 ? (
                          <span className="text-sm text-gray-400 italic">No tags</span>
                        ) : (
                          <div className="flex flex-wrap gap-2">
                            {linkage.photo_tags.map((tag) => (
                              <span
                                key={tag}
                                className="px-2 py-0.5 text-xs bg-gray-100 text-gray-700 rounded-full"
                              >
                                {tag}
                              </span>
                            ))}
                          </div>
                        )}
                      </td>
                      <td className="px-6 py-4 whitespace-nowrap">
                        <div className="text-sm text-gray-900">{linkage.user_name || 'Unknown'}</div>
                        <div className="text-xs text-gray-500">{linkage.user_email || '-'}</div>
                      </td>
                      <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
                        {formatDate(linkage.created_at)}
                      </td>
                      <td className="px-6 py-4">
                        {linkage.notes ? (
                          <div className="text-sm text-gray-700 whitespace-pre-wrap bg-gray-50 border border-gray-200 rounded p-2">
                            {linkage.notes}
                          </div>
                        ) : (
                          <span className="text-sm text-gray-400 italic">-</span>
                        )}
                      </td>
                      <td className="px-6 py-4 whitespace-nowrap">
                        <span
                          className={`px-2 py-1 text-xs font-semibold rounded-full ${
                            linkage.status === 'pending'
                              ? 'bg-yellow-100 text-yellow-800'
                              : linkage.status === 'approved'
                              ? 'bg-green-100 text-green-800'
                              : 'bg-red-100 text-red-800'
                          }`}
                        >
                          {linkage.status}
                        </span>
                      </td>
                      <td className="px-6 py-4 whitespace-nowrap">
                        {canReview ? (
                          <div className="flex items-center gap-4">
                            <label className="flex items-center gap-2 cursor-pointer">
                              <input
                                type="checkbox"
                                checked={decision === 'approve'}
                                onChange={() => handleDecisionChange(linkage.id, 'approve')}
                                className="w-4 h-4 text-green-600 focus:ring-green-500"
                              />
                              <span className="text-sm text-gray-700">Approve</span>
                            </label>
                            <label className="flex items-center gap-2 cursor-pointer">
                              <input
                                type="checkbox"
                                checked={decision === 'deny'}
                                onChange={() => handleDecisionChange(linkage.id, 'deny')}
                                className="w-4 h-4 text-red-600 focus:ring-red-500"
                              />
                              <span className="text-sm text-gray-700">Deny</span>
                            </label>
                          </div>
                        ) : (
                          <span className="text-sm text-gray-500 italic">-</span>
                        )}
                      </td>
                    </tr>
                  )
                })}
              </tbody>
            </table>
          </div>
        </div>
      )}
    </div>
  )
}


