import { useEffect, useMemo, useState } from 'react'
import { getDeviceAccentClass } from './TestCard'

const CONFIG_MAP_IMAGE_MODULES = import.meta.glob('../assets/TC*_map/*.png', {
  eager: true,
  import: 'default',
})

const STATUS_STYLES = {
  pending: 'bg-gray-700 text-gray-200 border-gray-600',
  completed: 'bg-green-900/60 text-green-200 border-green-700',
  rerun: 'bg-red-900/60 text-red-200 border-red-700',
}

function formatWindowHeader(windowDetails) {
  if (!windowDetails?.start_at || !windowDetails?.end_at) return 'Window details'

  const start = new Date(windowDetails.start_at)
  const end = new Date(windowDetails.end_at)

  const startLabel = start.toLocaleString('en-US', {
    month: 'numeric',
    day: 'numeric',
    hour: 'numeric',
    minute: '2-digit',
    hour12: true,
  }).replace(':00', '').replace(' AM', 'am').replace(' PM', 'pm')

  const endLabel = end.toLocaleString('en-US', {
    month: 'numeric',
    day: 'numeric',
    hour: 'numeric',
    minute: '2-digit',
    hour12: true,
  }).replace(':00', '').replace(' AM', 'am').replace(' PM', 'pm')

  return `${startLabel} - ${endLabel}`
}

function formatHours(minutes) {
  if (!Number.isFinite(minutes) || minutes <= 0) return '0 hrs'
  const hours = minutes / 60
  const rounded = Number.isInteger(hours) ? String(hours) : hours.toFixed(1)
  return `${rounded} hrs`
}

function formatShiftLabel(test) {
  const shiftLabels = {
    1: '12AM–9AM',
    2: '9AM–5PM',
    3: '5PM–12AM',
  }

  const date = test?.scheduled_date
  const label = shiftLabels[test?.shift_index] ?? 'Unknown shift'
  return date ? `${date} ${label}` : label
}

function getWindowTestConfig(windowDetails) {
  if (Array.isArray(windowDetails?.bundle_test_configs)) {
    return windowDetails.bundle_test_configs
      .map((value) => (typeof value === 'string' ? value.trim() : ''))
      .filter(Boolean)
  }

  const tests = windowDetails?.tests ?? []
  const allKeys = new Set()
  for (const test of tests) {
    if (Array.isArray(test?.bundle_test_configs)) {
      for (const key of test.bundle_test_configs) {
        if (typeof key === 'string' && key.trim()) {
          allKeys.add(key.trim())
        }
      }
      continue
    }

    if (typeof test?.test_config === 'string' && test.test_config.trim()) {
      allKeys.add(test.test_config.trim())
    }
  }

  return Array.from(allKeys).sort()
}

function formatConfigEntries(config) {
  if (!config || typeof config !== 'object') return []

  return Object.entries(config)
    .map(([band, data]) => {
      if (!data || typeof data !== 'object') return null
      const testPoint = data.test_point || data['Test Point'] || '—'
      const sta = data.sta || data.STA || '—'
      return { band, testPoint, sta }
    })
    .filter(Boolean)
}

function getConfigMapImages(configKey) {
  if (!configKey) return []

  const folderToken = `/${configKey.toUpperCase()}_map/`
  return Object.entries(CONFIG_MAP_IMAGE_MODULES)
    .filter(([path]) => path.includes(folderToken))
    .sort(([pathA], [pathB]) => pathA.localeCompare(pathB, undefined, { numeric: true }))
    .map(([, assetUrl]) => assetUrl)
}

function TestRow({ test }) {
  const [expanded, setExpanded] = useState(false)
  const statusStyle = STATUS_STYLES[test.status] ?? STATUS_STYLES.pending
  const configEntries = useMemo(() => formatConfigEntries(test.config), [test.config])

  return (
    <div className="rounded-xl border border-gray-700 bg-gray-900/70 overflow-hidden">
      <button
        type="button"
        onClick={() => setExpanded((value) => !value)}
        className="w-full px-4 py-3 text-left hover:bg-gray-800/80 transition-colors"
      >
        <div className="flex items-start justify-between gap-3">
          <div className="flex items-center gap-2">
            <span className={`w-2.5 h-2.5 rounded-full shrink-0 ${getDeviceAccentClass(test.device)}`} aria-hidden="true" />
            <div>
              <p className="text-sm font-semibold text-white">{test.test_id}</p>
              <p className="mt-1 text-xs text-gray-400">{test.device ?? '—'} · {formatShiftLabel(test)}</p>
            </div>
          </div>
          <div className="flex items-center gap-2 shrink-0">
            <span className={`px-2 py-1 rounded-full border text-[11px] font-semibold uppercase tracking-wide ${statusStyle}`}>
              {test.status ?? 'pending'}
            </span>
            <span className="text-xs text-gray-400">{Number.isFinite(test.estimated_minutes) && test.estimated_minutes > 0 ? `${test.estimated_minutes} min` : '—'}</span>
          </div>
        </div>
      </button>

      {expanded && (
        <div className="px-4 pb-4 pt-1 border-t border-gray-800 bg-gray-950/60">
          <div className="grid grid-cols-2 gap-3 text-xs text-gray-300">
            <div>
              <p className="text-gray-500 uppercase tracking-wide text-[11px] mb-1">Type</p>
              <p>{test.test_type ?? '—'}</p>
            </div>
            <div>
              <p className="text-gray-500 uppercase tracking-wide text-[11px] mb-1">Rotation</p>
              <p>{test.rotation ?? '—'}</p>
            </div>
          </div>

          <div className="mt-4">
            <p className="text-gray-500 uppercase tracking-wide text-[11px] mb-2">Config</p>
            {configEntries.length === 0 ? (
              <p className="text-xs text-gray-500">No config details available.</p>
            ) : (
              <div className="rounded-lg border border-gray-800 overflow-hidden">
                <table className="w-full text-xs">
                  <thead className="bg-gray-900/90">
                    <tr>
                      <th className="text-left px-3 py-2 font-semibold text-gray-400 border-b border-gray-800">Band</th>
                      <th className="text-left px-3 py-2 font-semibold text-gray-400 border-b border-gray-800">Testpoint</th>
                      <th className="text-left px-3 py-2 font-semibold text-gray-400 border-b border-gray-800">STA</th>
                    </tr>
                  </thead>
                  <tbody>
                    {configEntries.map((entry) => (
                      <tr key={`${test.test_id}-${entry.band}`} className="odd:bg-gray-950 even:bg-gray-900/60">
                        <td className="px-3 py-2 text-gray-200 border-b border-gray-800">{entry.band}</td>
                        <td className="px-3 py-2 text-gray-300 border-b border-gray-800">{entry.testPoint}</td>
                        <td className="px-3 py-2 text-gray-300 border-b border-gray-800">{entry.sta}</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            )}
          </div>
        </div>
      )}
    </div>
  )
}

export default function TestWindowDetailsPanel({ isOpen, windowDetails, onClose }) {
  const [showConfigMap, setShowConfigMap] = useState(false)
  const windowTests = useMemo(
    () => (Array.isArray(windowDetails?.tests) ? windowDetails.tests : []),
    [windowDetails],
  )
  const windowTestConfig = useMemo(() => getWindowTestConfig(windowDetails), [windowDetails])
  const windowConfigMapKey = useMemo(
    () => (windowTestConfig.length > 0 ? String(windowTestConfig[0]).toUpperCase() : null),
    [windowTestConfig],
  )
  const configMapImages = useMemo(() => getConfigMapImages(windowConfigMapKey), [windowConfigMapKey])
  const hasConfigMapImages = configMapImages.length > 0
  const showMapPane = showConfigMap && hasConfigMapImages

  useEffect(() => {
    if (!isOpen) return undefined

    const handleKeyDown = (event) => {
      if (event.key === 'Escape') {
        onClose()
      }
    }

    window.addEventListener('keydown', handleKeyDown)
    return () => window.removeEventListener('keydown', handleKeyDown)
  }, [isOpen, onClose])

  return (
    <div
      className={`absolute inset-0 z-40 transition-opacity duration-300 ${
        isOpen ? 'pointer-events-auto opacity-100' : 'pointer-events-none opacity-0'
      }`}
      aria-hidden={!isOpen}
    >
      <button
        type="button"
        onClick={onClose}
        className="absolute inset-0 bg-gray-950/45 backdrop-blur-[1px]"
        aria-label="Close test window details"
      />

      <aside
        className={`absolute inset-y-0 right-0 border-l border-gray-700 bg-gray-950/96 shadow-2xl transition-[width,transform] duration-300 ease-in-out ${
          showMapPane ? 'w-full' : 'w-[30rem]'
        } ${
          isOpen ? 'translate-x-0' : 'translate-x-full'
        }`}
      >
        <div className="flex h-full min-w-0 flex-col">
          <div className="flex items-start justify-between gap-4 border-b border-gray-800 px-5 py-5">
            <div>
              <p className="text-[11px] font-semibold uppercase tracking-[0.22em] text-cyan-400">Test Window</p>
              <h2 className="mt-2 text-xl font-semibold text-white">
                {windowDetails ? formatWindowHeader(windowDetails) : 'Window details'}
              </h2>
            </div>
            <button
              type="button"
              onClick={onClose}
              className="rounded-full border border-gray-700 p-2 text-gray-400 hover:border-gray-500 hover:text-white transition-colors"
              aria-label="Close panel"
            >
              <svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8">
                <path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
              </svg>
            </button>
          </div>

          {windowDetails && (
            <div className="flex-1 min-h-0 overflow-y-auto">
              <div className="flex min-h-full min-w-0">
                <div className={`${showMapPane ? 'w-[30rem] min-w-[30rem] border-r border-gray-800' : 'w-full'} px-5 py-5`}>
                <div className="grid grid-cols-2 gap-3">
                  <div className="rounded-2xl px-4 py-3">
                    <p className="text-[11px] font-semibold uppercase tracking-wide text-gray-500">Available Run Time</p>
                    <p className="mt-2 text-2xl font-semibold text-white">{formatHours(windowDetails.available_runtime_minutes)}</p>
                  </div>
                  <div className="rounded-2xl px-4 py-3">
                    <p className="text-[11px] font-semibold uppercase tracking-wide text-gray-500">Estimated Run Time</p>
                    <p className="mt-2 text-2xl font-semibold text-white">{formatHours(windowDetails.estimated_runtime_minutes)}</p>
                  </div>
                </div>

                <div className="mt-5 rounded-2xl border border-gray-800 bg-gray-900/80 p-4">
                  <div className="flex items-center justify-between gap-3">
                    <p className="text-sm font-semibold text-white">Config</p>
                    <span className="rounded-full border border-cyan-700/60 bg-cyan-900/30 px-2 py-1 text-[11px] font-semibold uppercase tracking-wide text-cyan-200">
                      {windowTestConfig.length > 0 ? windowTestConfig.join(', ') : 'N/A'}
                    </span>
                  </div>
                  {windowDetails.configRows?.length ? (
                    <div className="mt-3 overflow-hidden rounded-xl border border-gray-800">
                      <table className="w-full text-xs">
                        <thead className="bg-gray-950/90">
                          <tr>
                            <th className="px-3 py-2 text-left font-semibold text-gray-400 border-b border-gray-800">STA</th>
                            <th className="px-3 py-2 text-left font-semibold text-gray-400 border-b border-gray-800">Testpoint</th>
                          </tr>
                        </thead>
                        <tbody>
                          {windowDetails.configRows.map((row, index) => (
                            <tr key={`${row.sta}-${index}`} className="odd:bg-gray-950 even:bg-gray-900/60">
                              <td className="px-3 py-2 border-b border-gray-800 font-semibold text-gray-200">{row.sta}</td>
                              <td className="px-3 py-2 border-b border-gray-800 text-gray-300">{row.testPoints.join(', ')}</td>
                            </tr>
                          ))}
                        </tbody>
                      </table>
                    </div>
                  ) : (
                    <p className="mt-3 text-xs text-gray-500">No STA placement mapping available for this window.</p>
                  )}

                  <div className="mt-3">
                    <button
                      type="button"
                      onClick={() => setShowConfigMap((value) => !value)}
                      disabled={!hasConfigMapImages}
                      className="inline-flex items-center gap-2 rounded-md border border-gray-700 bg-gray-900 px-3 py-1.5 text-xs font-semibold text-gray-200 hover:bg-gray-800 transition-colors disabled:cursor-not-allowed disabled:opacity-50"
                    >
                      <span>{showMapPane ? 'Hide' : 'Show'} Config Map</span>
                      <span className="text-gray-400">{windowConfigMapKey ?? 'N/A'}</span>
                    </button>

                    {!hasConfigMapImages && (
                      <p className="mt-2 text-xs text-gray-500">No config map images found for this window config.</p>
                    )}
                  </div>
                </div>

                <div className="mt-5">
                  <div className="flex items-center justify-between gap-3 mb-3">
                    <p className="text-sm font-semibold text-white">Tests Scheduled In This Window</p>
                    <span className="text-xs text-gray-500">{windowTests.length} tests</span>
                  </div>
                  {windowTests.length ? (
                    <div className="flex flex-col gap-3">
                      {windowTests.map((test, index) => (
                        <TestRow
                          key={`${test.test_id}-${test.device}-${test.scheduled_date ?? 'na'}-${test.shift_index ?? 'na'}-${test.sequence_in_shift ?? index}`}
                          test={test}
                        />
                      ))}
                    </div>
                  ) : (
                    <div className="rounded-2xl border border-dashed border-gray-800 bg-gray-900/50 px-4 py-6 text-sm text-gray-500">
                      No tests are currently scheduled in this window.
                    </div>
                  )}
                </div>
                </div>

                {showMapPane && (
                  <div className="min-w-0 flex-1 px-6 py-5">
                    <div className="mb-4 flex items-center justify-between gap-3">
                      <p className="text-sm font-semibold text-white">Config Map</p>
                      <span className="rounded-full border border-cyan-700/60 bg-cyan-900/30 px-2 py-1 text-[11px] font-semibold uppercase tracking-wide text-cyan-200">
                        {windowConfigMapKey}
                      </span>
                    </div>
                    <div className="flex flex-col gap-5">
                      {configMapImages.map((imageUrl, index) => (
                        <div key={`${windowConfigMapKey}-map-${index + 1}`} className="rounded-xl p-2">
                          <img
                            src={imageUrl}
                            alt={`${windowConfigMapKey} config map ${index + 1}`}
                            className="w-full max-h-[78vh] rounded-lg object-contain"
                            loading="lazy"
                          />
                        </div>
                      ))}
                    </div>
                  </div>
                )}
              </div>
            </div>
          )}
        </div>
      </aside>
    </div>
  )
}
