// @ts-nocheck
import { useState, useRef, useEffect } from 'react'
import { Link } from 'react-router-dom'
import { ComposableMap, Geographies, Geography } from 'react-simple-maps'

const geoUrl = 'https://cdn.jsdelivr.net/npm/us-atlas@3/states-10m.json'

interface BillSample {
  bill_number: string
  title: string
  status: string
  type: string
  action: string
  date?: string  // Format: "Jan 2026"
  state: string
}

interface StateData {
  state: string
  total_bills: number
  type_counts: {
    ban: number
    restriction: number
    protection: number
    other: number
  }
  status_counts: {
    enacted: number
    failed: number
    pending: number
  }
  primary_type: string
  primary_status: string
  map_category: string
  sample_bills?: BillSample[]
}

interface USMapProps {
  stateData: Record<string, StateData>
  onStateClick?: (stateCode: string) => void
  legend?: {
    types: Record<string, string>
    statuses: Record<string, string>
  }
}

// State code to FIPS mapping
const STATE_FIPS: Record<string, string> = {
  'AL': '01', 'AK': '02', 'AZ': '04', 'AR': '05', 'CA': '06',
  'CO': '08', 'CT': '09', 'DE': '10', 'FL': '12', 'GA': '13',
  'HI': '15', 'ID': '16', 'IL': '17', 'IN': '18', 'IA': '19',
  'KS': '20', 'KY': '21', 'LA': '22', 'ME': '23', 'MD': '24',
  'MA': '25', 'MI': '26', 'MN': '27', 'MS': '28', 'MO': '29',
  'MT': '30', 'NE': '31', 'NV': '32', 'NH': '33', 'NJ': '34',
  'NM': '35', 'NY': '36', 'NC': '37', 'ND': '38', 'OH': '39',
  'OK': '40', 'OR': '41', 'PA': '42', 'RI': '44', 'SC': '45',
  'SD': '46', 'TN': '47', 'TX': '48', 'UT': '49', 'VT': '50',
  'VA': '51', 'WA': '53', 'WV': '54', 'WI': '55', 'WY': '56',
  'DC': '11', 'PR': '72'
}

const FIPS_STATE: Record<string, string> = Object.fromEntries(
  Object.entries(STATE_FIPS).map(([k, v]) => [v, k])
)

// Flexible color palette for different legislation types
const TYPE_COLOR_PALETTE: Record<string, string> = {
  // Fluoridation categories
  'mandate': '#4CAF50',      // Green - Mandate
  'removal': '#F44336',      // Red - Removal
  'study': '#9C27B0',        // Purple - Study
  
  // Dental/Oral Health categories  
  'coverage_expansion': '#4CAF50',  // Green - Expansion
  'screening': '#FF9800',          // Orange - Screening
  'provider_access': '#2196F3',    // Blue - Provider Access
  
  // Medicaid categories
  'expansion': '#4CAF50',     // Green - Expansion
  'coverage': '#2196F3',      // Blue - Coverage
  'reimbursement': '#FF9800', // Orange - Reimbursement
  'eligibility': '#9C27B0',   // Purple - Eligibility
  
  // Education categories
  'requirement': '#FF9800',   // Orange - Requirement
  'curriculum': '#2196F3',    // Blue - Curriculum
  'reform': '#9C27B0',        // Purple - Reform
  
  // Health/General categories
  'protection': '#4CAF50',    // Green - Protection
  'restriction': '#F44336',   // Red - Restriction
  
  // Generic categories
  'support': '#4CAF50',       // Green - Support
  'oppose': '#F44336',        // Red - Oppose
  'regulate': '#FF9800',      // Orange - Regulate
  
  // Shared
  'funding': '#2196F3',       // Blue - Funding (appears in multiple)
  'other': '#9E9E9E',         // Gray - Other
}

// Get color for any category with fallback
const getColorForCategory = (category: string): string => {
  return TYPE_COLOR_PALETTE[category] || '#9E9E9E' // Default to gray
}

// Color scheme based on the user's description
const getStateColor = (stateCode: string, stateData: Record<string, StateData>): string => {
  const data = stateData[stateCode]
  
  if (!data || data.total_bills === 0) {
    return '#E3F2FD' // Light blue - no legislation
  }
  
  const { primary_type, primary_status } = data
  
  // Get base color for this type
  let baseColor = getColorForCategory(primary_type)
  
  // Adjust shade based on status
  if (primary_status === 'enacted') {
    // Slightly darker for enacted (reduce lightness)
    return adjustColorBrightness(baseColor, -20)
  } else if (primary_status === 'failed') {
    // Lighter for failed (increase lightness)
    return adjustColorBrightness(baseColor, 40)
  }
  
  return baseColor
}

// Helper to adjust color brightness
const adjustColorBrightness = (hex: string, percent: number): string => {
  // Simple brightness adjustment
  const num = parseInt(hex.replace('#', ''), 16)
  const amt = Math.round(2.55 * percent)
  const R = (num >> 16) + amt
  const G = (num >> 8 & 0x00FF) + amt
  const B = (num & 0x0000FF) + amt
  
  return '#' + (
    0x1000000 +
    (R < 255 ? (R < 1 ? 0 : R) : 255) * 0x10000 +
    (G < 255 ? (G < 1 ? 0 : G) : 255) * 0x100 +
    (B < 255 ? (B < 1 ? 0 : B) : 255)
  ).toString(16).slice(1).toUpperCase()
}

const getPatternForState = (stateCode: string, stateData: Record<string, StateData>): string | null => {
  const data = stateData[stateCode]
  
  if (!data || data.total_bills === 0) {
    return null
  }
  
  const { primary_status } = data
  
  if (primary_status === 'failed') {
    return 'crosshatch'
  } else if (primary_status === 'enacted') {
    return 'diagonal'
  }
  
  return null
}

export default function USMap({ stateData, onStateClick, legend }: USMapProps) {
  const [hoveredState, setHoveredState] = useState<string | null>(null)
  const [tooltipPosition, setTooltipPosition] = useState({ x: 0, y: 0 })
  const hoverTimeoutRef = useRef<NodeJS.Timeout | null>(null)
  const hoveredStateElementRef = useRef<any>(null)
  const containerRef = useRef<HTMLDivElement>(null)
  
  // Get unique types from actual state data if legend not provided
  const legislationTypes = legend?.types || {}
  const legislationStatuses = legend?.statuses || {
    'enacted': 'Enacted',
    'failed': 'Failed', 
    'pending': 'Pending'
  }
  
  // Helper to calculate position relative to container
  const calculateRelativePosition = (element: any) => {
    if (!element || !containerRef.current) return { x: 0, y: 0 }
    
    const stateBounds = element.getBoundingClientRect()
    const containerBounds = containerRef.current.getBoundingClientRect()
    
    return {
      x: stateBounds.left - containerBounds.left + stateBounds.width / 2,
      y: stateBounds.top - containerBounds.top
    }
  }
  
  // Update tooltip position on scroll
  useEffect(() => {
    const updateTooltipPosition = () => {
      if (hoveredState && hoveredStateElementRef.current) {
        setTooltipPosition(calculateRelativePosition(hoveredStateElementRef.current))
      }
    }
    
    if (hoveredState) {
      window.addEventListener('scroll', updateTooltipPosition, true)
      return () => window.removeEventListener('scroll', updateTooltipPosition, true)
    }
  }, [hoveredState])
  
  const handleMouseEnter = (event: any, stateCode: string) => {
    // Clear any pending state change
    if (hoverTimeoutRef.current) {
      clearTimeout(hoverTimeoutRef.current)
      hoverTimeoutRef.current = null
    }
    
    // Store the element reference for scroll updates
    hoveredStateElementRef.current = event.target
    
    // If no tooltip showing, show immediately
    if (!hoveredState) {
      setHoveredState(stateCode)
      setTooltipPosition(calculateRelativePosition(event.target))
    } 
    // If tooltip already showing for different state, delay switch
    // This prevents accidental switches when moving mouse to tooltip
    else if (hoveredState !== stateCode) {
      hoverTimeoutRef.current = setTimeout(() => {
        setHoveredState(stateCode)
        setTooltipPosition(calculateRelativePosition(event.target))
      }, 200) // 200ms delay prevents accidental switches
    }
  }
  
  const handleMouseLeave = () => {
    // Clear any pending state change when leaving
    if (hoverTimeoutRef.current) {
      clearTimeout(hoverTimeoutRef.current)
      hoverTimeoutRef.current = null
    }
  }
  
  // Close button handler
  const handleCloseTooltip = () => {
    setHoveredState(null)
    if (hoverTimeoutRef.current) {
      clearTimeout(hoverTimeoutRef.current)
      hoverTimeoutRef.current = null
    }
  }
  
  const hoveredData = hoveredState ? stateData[hoveredState] : null
  
  return (
    <div ref={containerRef} className="relative">
      {/* SVG Patterns for overlays */}
      <svg width="0" height="0">
        <defs>
          {/* Crosshatch pattern for failed */}
          <pattern id="crosshatch" width="10" height="10" patternUnits="userSpaceOnUse">
            <line x1="0" y1="0" x2="10" y2="10" stroke="#000" strokeWidth="1" opacity="0.3" />
            <line x1="10" y1="0" x2="0" y2="10" stroke="#000" strokeWidth="1" opacity="0.3" />
          </pattern>
          
          {/* Diagonal stripes for enacted */}
          <pattern id="diagonal" width="10" height="10" patternUnits="userSpaceOnUse">
            <line x1="0" y1="0" x2="10" y2="10" stroke="#000" strokeWidth="2" opacity="0.4" />
          </pattern>
        </defs>
      </svg>
      
      <ComposableMap
        projection="geoAlbersUsa"
        projectionConfig={{
          scale: 1000,
        }}
        className="w-full h-auto"
      >
        <Geographies geography={geoUrl}>
          {({ geographies }) =>
            geographies.map((geo) => {
              const fips = geo.id
              const stateCode = FIPS_STATE[fips] || fips
              const data = stateData[stateCode]
              const pattern = getPatternForState(stateCode, stateData)
              
              return (
                <Geography
                  key={geo.rsmKey}
                  geography={geo}
                  fill={pattern ? `url(#${pattern})` : getStateColor(stateCode, stateData)}
                  stroke="#FFFFFF"
                  strokeWidth={0.5}
                  style={{
                    default: {
                      fill: getStateColor(stateCode, stateData),
                      outline: 'none',
                    },
                    hover: {
                      fill: '#607D8B',
                      outline: 'none',
                      cursor: 'pointer',
                    },
                    pressed: {
                      fill: '#455A64',
                      outline: 'none',
                    },
                  }}
                  onClick={() => onStateClick?.(stateCode)}
                  onMouseEnter={(event) => handleMouseEnter(event, stateCode)}
                  onMouseLeave={handleMouseLeave}
                />
              )
            })
          }
        </Geographies>
      </ComposableMap>
      
      {/* Tooltip - Stays visible until hover another state or click close */}
      {hoveredState && hoveredData && (
        <div 
          className="absolute z-50 pointer-events-auto"
          style={{
            left: `${tooltipPosition.x}px`,
            top: `${tooltipPosition.y - 10}px`,
            transform: 'translate(-50%, -100%)'
          }}
        >
          <div className="bg-gray-900 text-white px-4 py-3 rounded-lg shadow-xl max-w-sm border border-gray-700">
            {/* Close button */}
            <button
              onClick={handleCloseTooltip}
              className="absolute top-2 right-2 text-gray-400 hover:text-white transition-colors"
              aria-label="Close tooltip"
            >
              <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
              </svg>
            </button>
            <div className="flex items-center justify-between mb-3">
              <div className="font-bold text-lg">{hoveredState}</div>
              <div className="text-xs text-gray-400">
                {hoveredData.total_bills.toLocaleString()} bill{hoveredData.total_bills !== 1 ? 's' : ''}
              </div>
            </div>
            
            {hoveredData.total_bills > 0 && (
              <>
                {/* Primary Type and Status - Prominent */}
                <div className="mb-3 p-2 bg-gray-800 rounded-md">
                  <div className="flex items-center justify-between">
                    <div className="flex items-center gap-2">
                      <div className={`
                        w-3 h-3 rounded-full
                        ${hoveredData.primary_type === 'removal' ? 'bg-red-500' : 
                          hoveredData.primary_type === 'mandate' ? 'bg-green-500' :
                          hoveredData.primary_type === 'study' ? 'bg-blue-500' :
                          hoveredData.primary_type === 'funding' ? 'bg-yellow-500' :
                          'bg-gray-500'}
                      `} />
                      <div>
                        <div className="text-sm font-semibold text-white">
                          {legislationTypes[hoveredData.primary_type] || hoveredData.primary_type}
                        </div>
                        <div className="text-xs text-gray-400">Primary Type</div>
                      </div>
                    </div>
                    <div className={`
                      px-2 py-1 rounded text-xs font-medium
                      ${hoveredData.primary_status === 'enacted' ? 'bg-green-500/30 text-green-300 border border-green-500/50' : 
                        hoveredData.primary_status === 'failed' ? 'bg-red-500/30 text-red-300 border border-red-500/50' : 
                        'bg-yellow-500/30 text-yellow-300 border border-yellow-500/50'}
                    `}>
                      {hoveredData.primary_status === 'enacted' ? '✓ Enacted' : 
                       hoveredData.primary_status === 'failed' ? '✗ Failed' : 
                       '⏳ Pending'}
                    </div>
                  </div>
                </div>
                
                {/* Sample Bills Grouped by Type */}
                {hoveredData.sample_bills && hoveredData.sample_bills.length > 0 && (
                  <div className="mb-3 max-h-48 overflow-y-auto">
                    <div className="text-xs font-medium text-gray-300 mb-2">Recent Bills by Type:</div>
                    <div className="space-y-2">
                      {(() => {
                        // Group bills by type
                        const billsByType = hoveredData.sample_bills.reduce((acc, bill) => {
                          if (!acc[bill.type]) acc[bill.type] = []
                          acc[bill.type].push(bill)
                          return acc
                        }, {} as Record<string, BillSample[]>)
                        
                        return Object.entries(billsByType).map(([type, bills]) => (
                          <div key={type} className="bg-gray-800/50 rounded p-2">
                            <div className="flex items-center gap-2 mb-1.5">
                              <div className={`
                                w-2 h-2 rounded-full
                                ${type === 'removal' ? 'bg-red-500' : 
                                  type === 'mandate' ? 'bg-green-500' :
                                  type === 'study' ? 'bg-blue-500' :
                                  type === 'funding' ? 'bg-yellow-500' :
                                  'bg-gray-500'}
                              `} />
                              <div className="text-xs font-medium text-gray-200">
                                {legislationTypes[type] || type} ({bills.length})
                              </div>
                            </div>
                            <div className="space-y-1 ml-4">
                              {bills.map((bill, idx) => (
                                <Link
                                  key={idx}
                                  to={`/bill/${bill.state}-${bill.bill_number}`}
                                  className="block text-xs hover:bg-gray-700/50 rounded px-2 py-1 transition-colors group"
                                >
                                  <div className="flex items-center justify-between gap-2">
                                    <span className="font-mono text-blue-300 group-hover:text-blue-200 font-semibold">
                                      {bill.bill_number}
                                    </span>
                                    <span className={`
                                      px-1.5 py-0.5 rounded text-[10px] font-medium
                                      ${bill.status === 'enacted' ? 'bg-green-500/20 text-green-300' : 
                                        bill.status === 'failed' ? 'bg-red-500/20 text-red-300' : 
                                        'bg-yellow-500/20 text-yellow-300'}
                                    `}>
                                      {bill.status === 'enacted' ? '✓ Enacted' : 
                                       bill.status === 'failed' ? '✗ Failed' : '⏳ Pending'}
                                    </span>
                                  </div>
                                  <div className="text-gray-400 text-[10px] mt-0.5 flex items-center gap-1">
                                    {bill.date && <span className="text-gray-500">📅 {bill.date}</span>}
                                    {bill.date && bill.action && <span className="text-gray-600">•</span>}
                                    <span className="flex-1 truncate">{bill.action || 'Click for details'}</span>
                                  </div>
                                </Link>
                              ))}
                            </div>
                          </div>
                        ))
                      })()}
                    </div>
                  </div>
                )}
                
                {/* Status Summary */}
                <div className="grid grid-cols-3 gap-2 mb-3 text-xs">
                  <div className="bg-green-500/10 border border-green-500/30 rounded px-2 py-1.5">
                    <div className="text-green-400 font-bold text-base">{hoveredData.status_counts.enacted}</div>
                    <div className="text-green-300/70">Enacted</div>
                  </div>
                  <div className="bg-yellow-500/10 border border-yellow-500/30 rounded px-2 py-1.5">
                    <div className="text-yellow-400 font-bold text-base">{hoveredData.status_counts.pending}</div>
                    <div className="text-yellow-300/70">Pending</div>
                  </div>
                  <div className="bg-red-500/10 border border-red-500/30 rounded px-2 py-1.5">
                    <div className="text-red-400 font-bold text-base">{hoveredData.status_counts.failed}</div>
                    <div className="text-red-300/70">Failed</div>
                  </div>
                </div>
                
                {/* Drill Down Button */}
                <button
                  onClick={() => onStateClick && onStateClick(hoveredState)}
                  className="w-full bg-blue-600 hover:bg-blue-700 text-white font-medium text-sm py-2 px-3 rounded transition-colors flex items-center justify-center gap-2"
                >
                  <span>View All Bills</span>
                  <span className="text-lg">→</span>
                </button>
              </>
            )}
            
            {hoveredData.total_bills === 0 && (
              <div className="text-gray-400 text-sm italic text-center py-2">No legislation found</div>
            )}
            
            {/* Tooltip arrow */}
            <div 
              className="absolute left-1/2 bottom-0 transform -translate-x-1/2 translate-y-full"
              style={{
                width: 0,
                height: 0,
                borderLeft: '8px solid transparent',
                borderRight: '8px solid transparent',
                borderTop: '8px solid rgb(17, 24, 39)'
              }}
            />
          </div>
        </div>
      )}
      
      {/* Legend - Absolute on desktop, below map on mobile */}
      <div className="relative md:absolute md:bottom-4 md:right-4 mt-4 md:mt-0 bg-white/95 rounded-lg shadow-lg p-4 border border-gray-200 max-w-xs mx-auto md:mx-0">
        <div className="text-sm font-semibold text-gray-800 mb-3">Legend</div>
        
        {/* Type of Legislation - Show actual types from data */}
        {(() => {
          // Get unique types from actual state data
          const uniqueTypes = new Set<string>()
          Object.values(stateData).forEach(state => {
            if (state.primary_type) uniqueTypes.add(state.primary_type)
          })
          
          return uniqueTypes.size > 0 && (
            <div className="mb-3">
              <div className="text-xs font-medium text-gray-600 mb-2">Type of Legislation</div>
              <div className="space-y-1">
                {Array.from(uniqueTypes).sort().map(type => (
                  <div key={type} className="flex items-center gap-2">
                    <div className="w-4 h-4 rounded flex-shrink-0" style={{ backgroundColor: getColorForCategory(type) }} />
                    <span className="text-xs text-gray-700 capitalize">{legislationTypes[type] || type.replace(/_/g, ' ')}</span>
                  </div>
                ))}
                <div className="flex items-center gap-2">
                  <div className="w-4 h-4 rounded flex-shrink-0" style={{ backgroundColor: '#E3F2FD' }} />
                  <span className="text-xs text-gray-700">No Legislation</span>
                </div>
              </div>
            </div>
          )
        })()}
        
        {/* Status of Legislation */}
        <div>
          <div className="text-xs font-medium text-gray-600 mb-2">Status</div>
          <div className="space-y-1">
            <div className="flex items-center gap-2">
              <div className="w-4 h-4 rounded border border-gray-300 flex-shrink-0" style={{ backgroundColor: '#666' }} />
              <span className="text-xs text-gray-700">Enacted (darker)</span>
            </div>
            <div className="flex items-center gap-2">
              <div className="w-4 h-4 rounded border border-gray-300 flex-shrink-0 bg-white" />
              <span className="text-xs text-gray-700">Pending (normal)</span>
            </div>
            <div className="flex items-center gap-2">
              <div className="w-4 h-4 rounded border border-gray-300 flex-shrink-0" style={{ backgroundColor: '#ddd' }} />
              <span className="text-xs text-gray-700">Failed (lighter)</span>
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}
