'use client'

import { useCallback, useEffect, useRef, useState } from 'react'
import {
  AlertTriangle,
  Cookie,
  Loader2,
  RefreshCw,
  ShieldAlert,
  Trash2,
  Zap,
  Link,
  Link2,
} from 'lucide-react'
import { tone } from './Badge'
import './SessionMonitor.css'

interface Session {
  _id: string
  label: string
  applicantName: string
  email: string
  cookies: Record<string, string>
  formUrl: string
  applicationId?: string
  lastCheckAt: string | null
  lastStatus: 'idle' | 'checking' | 'slot_detected' | 'error' | 'session_expired'
  lastError: string | null
  snapshot: Record<string, unknown> | null
  createdAt: string
}

interface CheckResult {
  status: string
  changed: boolean
  hasSlotSignal: boolean
  throttled?: boolean
  error?: string
  signals?: {
    enabledSections: string[]
    newlyEnabled: string[]
    slotRelatedQuestions: any[]
    sectionCount: number
  }
}

interface ActivityEvent {
  id: number
  tone: string
  text: string
  time: string
}

const POLL_MS = 15000

function timeNow(): string {
  return new Date().toLocaleTimeString('en-GB', {
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    hour12: false,
  })
}

function timeSince(iso: string | null): string {
  if (!iso) return 'never checked'
  const sec = Math.max(0, Math.round((Date.now() - new Date(iso).getTime()) / 1000))
  if (sec < 60) return `${sec}s ago`
  if (sec < 3600) return `${Math.floor(sec / 60)}m ago`
  return `${Math.floor(sec / 3600)}h ago`
}

function extractFromCurl(curl: string): { cookies: Record<string, string>; url: string } {
  const cookies: Record<string, string> = {}
  const cleaned = curl.replace(/\^/g, '').replace(/%\^%/g, '%')

  let url = ''
  const urlMatch = cleaned.match(/(?:curl\s+['"]?(https?:\/\/[^\s'"]+))|(?:--url\s+['"]?(https?:\/\/[^\s'"]+))/i)
  if (urlMatch) url = (urlMatch[1] || urlMatch[2] || '').replace(/['"]/g, '')

  const patterns = [
    /(?:--cookie|-b)\s+['"]([^'"]+)['"]/gi,
    /-H\s+['"]Cookie:\s*([^'"]+)['"]/gi,
    /--header\s+['"]Cookie:\s*([^'"]+)['"]/gi,
  ]

  let raw = ''
  for (const pat of patterns) {
    let m
    while ((m = pat.exec(cleaned)) !== null) {
      raw += '; ' + m[1]
    }
  }

  if (!raw.trim()) {
    const bareMatch = cleaned.match(/(?:^|\s)((?:[\w-]+=[^;\s]+(?:;\s*)?)+)/)
    if (bareMatch) raw = bareMatch[1]
  }

  for (const part of raw.split(';')) {
    const t = part.trim()
    const eq = t.indexOf('=')
    if (eq > 0) {
      const k = t.slice(0, eq).trim().replace(/[^\x20-\x7E]/g, '')
      const v = t.slice(eq + 1).trim().replace(/[^\x20-\x7E]/g, '')
      if (k && v) cookies[k] = v
    }
  }
  return { cookies, url }
}

function parseCookies(raw: string): Record<string, string> {
  const cookies: Record<string, string> = {}
  const lines = raw.split(/[;\n]+/)
  for (const line of lines) {
    const t = line.trim()
    if (!t || t.startsWith('#') || t.startsWith('//')) continue
    const eqIdx = t.indexOf('=')
    if (eqIdx > 0) {
      const key = t.slice(0, eqIdx).trim().replace(/[^\x20-\x7E]/g, '')
      const val = t.slice(eqIdx + 1).trim().replace(/[^\x20-\x7E]/g, '')
      if (key && val) cookies[key] = val
    }
  }
  return cookies
}

function parseAnyCookieFormat(raw: string): { cookies: Record<string, string>; url: string } {
  const trimmed = raw.trim()
  if (trimmed.toLowerCase().startsWith('curl ') || trimmed.includes('-H') || trimmed.includes('-b ') || trimmed.includes('--cookie')) {
    return extractFromCurl(trimmed)
  }
  return { cookies: parseCookies(trimmed), url: '' }
}

function simplifyError(err: string): string {
  if (!err) return ''
  if (/session.expired|401|403|re.?login|auth/i.test(err)) return 'Session expired — please reconnect your account'
  if (/cookies|invalid cookie/i.test(err)) return 'Invalid cookies — please paste fresh cookies from Amazon Jobs'
  if (/network|ECONNREFUSED|fetch/i.test(err)) return 'Network error — check your internet connection'
  if (/playwright|chromium|executable|browser/i.test(err)) return 'Could not connect — cookies may be expired or invalid'
  if (/rate.?limit|429|throttl/i.test(err)) return 'Amazon rate limited — will retry automatically'
  if (/profile not extractable/i.test(err)) return 'Could not read profile — cookies may be expired'
  return err.replace(/\|.*$/s, '').trim().slice(0, 80)
}

function detectName(cookies: Record<string, string>): string {
  const email = cookies['email'] || cookies['user_email'] || ''
  if (email) return email.split('@')[0]
  const pid = cookies['passport_id'] || ''
  if (pid) return `User ${pid.slice(0, 8)}`
  return `Session ${new Date().toLocaleDateString('en-GB', { day: '2-digit', month: 'short' })}`
}

interface SessionMonitorProps {
  applications: { id: string; jobTitle: string; location: string }[]
  onSlotDetected?: (session: Session, signals: any) => void
}

export function SessionMonitor({ applications, onSlotDetected }: SessionMonitorProps) {
  const [sessions, setSessions] = useState<Session[]>([])
  const [loading, setLoading] = useState(true)
  const [pasteText, setPasteText] = useState('')
  const [pasteError, setPasteError] = useState('')
  const [connecting, setConnecting] = useState(false)
  const [activity, setActivity] = useState<ActivityEvent[]>([])
  const [autoPoll, setAutoPoll] = useState(true)
  const [showSteps, setShowSteps] = useState(true)
  const [inputMode, setInputMode] = useState<'curl' | 'cookies'>('curl')
  const [cookieText, setCookieText] = useState('')
  const [cookieError, setCookieError] = useState('')
  const [connectingCookie, setConnectingCookie] = useState(false)
  const activityId = useRef(0)
  const pollingRef = useRef<ReturnType<typeof setInterval> | null>(null)
  const textareaRef = useRef<HTMLTextAreaElement>(null)

  const push = useCallback((toneName: string, text: string) => {
    setActivity((prev) =>
      [{ id: activityId.current++, tone: toneName, text, time: timeNow() }, ...prev].slice(0, 50)
    )
  }, [])

  const loadSessions = useCallback(async () => {
    try {
      const res = await fetch('/api/sessions')
      if (res.ok) {
        const data = await res.json()
        setSessions(data.sessions || [])
      }
    } catch { /* ignore */ }
    finally { setLoading(false) }
  }, [])

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

const checkSession = useCallback(async (sessionId: string) => {
    try {
      const res = await fetch(`/api/sessions/${sessionId}/check`, { method: 'POST' })
      if (!res.ok) { push('red', 'Check failed'); return }
      const result: CheckResult = await res.json()
      if (result.status === 'slot_detected') {
        push('green', `SLOT DETECTED! Form changed`)
        if (result.signals?.slotRelatedQuestions.length) {
          for (const q of result.signals.slotRelatedQuestions) {
            push('green', `"${q.text?.slice(0, 50)}"`)
          }
        }
        try { new Audio('data:audio/wav;base64,UklGRnoGAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQoGAACBhYqFbF1fdH+JkI+Gd2BbY3B4h42Oi31sYGN1gomPjomAdWZmZXR+h42NinlyZmRyeoeOjYl5c2dlc3qIj42Ke3VpZnN5h4+MiHh0aWVyeIeOjIh4dGlmcniHjoyIeHRpZnJ4h46MiHh0aWZyeIeOjIh4dGlmcniHjoyIeHRpZnJ4h46MiHh0aWZyeA==').play() } catch { /* blocked */ }
      } else if (result.throttled) {
        push('slate', 'Amazon rate limit — check auto-paused for a moment')
      } else if (result.status === 'session_expired') {
        push('red', 'Session expired — re-login on Amazon Jobs')
      } else if (result.status === 'error') {
        push('amber', `Error: ${result.error || 'unknown'}`)
      } else {
        push('slate', `Checked — no change (${result.signals?.sectionCount || 0} sections)`)
      }
      await loadSessions()
    } catch { push('red', 'Network error') }
  }, [push, loadSessions])

  const checkAll = useCallback(async () => {
    // Run all checks in parallel — don't block on each other
    await Promise.allSettled(
      sessions
        .filter((s) => s.lastStatus !== 'checking')
        .map((s) => checkSession(s._id))
    )
  }, [sessions, checkSession])

  useEffect(() => {
    if (pollingRef.current) clearInterval(pollingRef.current)
    if (autoPoll && sessions.length > 0) {
      pollingRef.current = setInterval(checkAll, POLL_MS)
    }
    return () => { if (pollingRef.current) clearInterval(pollingRef.current) }
  }, [autoPoll, sessions, checkAll])

  const handleConnect = useCallback(async () => {
    setPasteError('')
    const raw = pasteText.trim()
    if (!raw) { setPasteError('Paste your cookies first.'); return }

    setConnecting(true)
    const { cookies, url } = parseAnyCookieFormat(raw)
    const count = Object.keys(cookies).length
    if (count === 0) {
      setPasteError('No valid cookies found. Paste the Cookie header or cURL command.')
      setConnecting(false)
      return
    }

    const name = detectName(cookies)
    try {
      // /api/connect uses the real Amazon GraphQL to fetch profile immediately
      const res = await fetch('/api/connect', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ cookies }),
      })
      if (!res.ok) {
        const data = await res.json()
        setPasteError(data.error || 'Failed to connect')
        return
      }
      const data = await res.json()
      setPasteText('')
      push('green', `Connected: ${data.name || name} (${count} cookies)`)
      await loadSessions()
      if (data.sessionId) {
        if (data.accountReady) {
          push('green', `Profile loaded: ${data.name}`)
        } else {
          push('slate', 'Fetching your Amazon profile in background…')
          // Poll a few times to pick up the background scrape result
          let tries = 0
          const poll = setInterval(async () => {
            tries++
            await loadSessions()
            if (tries >= 6) clearInterval(poll) // stop after 30s
          }, 5000)
        }
      }
    } catch {
      setPasteError('Network error')
    } finally {
      setConnecting(false)
    }
  }, [pasteText, push, loadSessions])

  const handleDelete = async (id: string, name: string) => {
    await fetch(`/api/sessions/${id}`, { method: 'DELETE' })
    push('red', `Disconnected: ${name}`)
    await loadSessions()
  }

  const handleLink = async (sessionId: string, applicationId: string) => {
    await fetch(`/api/sessions/${sessionId}`, {
      method: 'PATCH',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ applicationId: applicationId || undefined }),
    })
    const app = applications.find((a) => a.id === applicationId)
    push('slate', app ? `Linked ${app.jobTitle} to session` : 'Session unlinked')
    await loadSessions()
  }

  const handleDirectCookieConnect = useCallback(async () => {
    setCookieError('')
    const raw = cookieText.trim()
    if (!raw) { setCookieError('Cookie field is empty.'); return }

    // Parse cookies — supports 3 formats:
    // 1. JSON array: [{"name":"x","value":"y"}, ...]
    // 2. name=value; name2=value2
    // 3. cURL -b format
    const cookies: Record<string, string> = {}

    if (raw.startsWith('[')) {
      // JSON array format (browser extension export)
      try {
        const arr = JSON.parse(raw)
        if (Array.isArray(arr)) {
          for (const c of arr) {
            if (c.name && c.value !== undefined && c.value !== '') {
              cookies[c.name] = String(c.value)
            }
          }
        }
      } catch {
        setCookieError('Invalid JSON — please paste a valid JSON array.')
        return
      }
    } else {
      // name=value; name2=value2 format
      for (const part of raw.split(';')) {
        const t = part.trim()
        const eq = t.indexOf('=')
        if (eq > 0) {
          const k = t.slice(0, eq).trim().replace(/[^\x20-\x7E]/g, '')
          const v = t.slice(eq + 1).trim().replace(/[^\x20-\x7E]/g, '')
          if (k && v) cookies[k] = v
        }
      }
    }

    const count = Object.keys(cookies).length
    if (count === 0) {
      setCookieError('No valid cookies found.')
      return
    }

    setConnectingCookie(true)
    try {
      const res = await fetch('/api/connect', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ cookies }),
      })
      const data = await res.json()
      if (!res.ok) {
        setCookieError(data.error || 'Failed to connect')
        return
      }
      setCookieText('')
      push('green', `Connected: ${data.name || 'Account'} (${count} cookies)`)
      await loadSessions()
      if (data.sessionId) {
        let t = 0
        const poll = setInterval(async () => {
          t++
          await loadSessions()
          if (t >= 6) clearInterval(poll)
        }, 5000)
      }
    } catch {
      setCookieError('Network error')
    } finally {
      setConnectingCookie(false)
    }
  }, [cookieText, push, loadSessions])

  return (
    <section className="panel session-panel">
      <div className="panel-heading">
        <div>
          <h2>Connect Amazon account</h2>
          <p>Paste your cookies to start monitoring for slots.</p>
        </div>
        <div className="panel-tools">
          <span className={`live-badge ${autoPoll ? 'on' : 'off'}`}>
            <span className="dot" />
            {autoPoll ? 'Watching' : 'Paused'}
          </span>
          <button className="refresh small" onClick={() => setAutoPoll((v) => !v)}>
            {autoPoll ? 'Pause' : 'Resume'}
          </button>
          {sessions.length > 0 && (
            <button className="refresh small" onClick={checkAll}>
              <RefreshCw size={14} /> Check all
            </button>
          )}
        </div>
      </div>

      {/* ── HOW TO CONNECT ── */}
      {showSteps && (
        <div className="connect-steps">
          <button className="steps-close" onClick={() => setShowSteps(false)}>×</button>
          <div className="steps-grid">
            <div className="step">
              <div className="step-num">1</div>
              <div>
                <b>Open Amazon Jobs</b>
                <span>Go to amazon.jobs and log in</span>
              </div>
            </div>
            <div className="step">
              <div className="step-num">2</div>
              <div>
                <b>Open DevTools</b>
                <span>Press <code>F12</code> → <code>Network</code> tab</span>
              </div>
            </div>
            <div className="step">
              <div className="step-num">3</div>
              <div>
                <b>Copy as cURL</b>
                <span>Right-click any request → <code>Copy</code> → <code>Copy as cURL</code></span>
              </div>
            </div>
            <div className="step">
              <div className="step-num">4</div>
              <div>
                <b>Paste & connect</b>
                <span>Paste in the box below → hit Connect</span>
              </div>
            </div>
          </div>
        </div>
      )}

      {/* ── INPUT MODE TABS ── */}
      <div className="connect-tabs">
        <button
          className={`connect-tab ${inputMode === 'curl' ? 'active' : ''}`}
          onClick={() => { setInputMode('curl'); setPasteError('') }}
        >
          cURL / Cookie Header
        </button>
        <button
          className={`connect-tab ${inputMode === 'cookies' ? 'active' : ''}`}
          onClick={() => { setInputMode('cookies'); setCookieError('') }}
        >
          Direct Session Cookie
        </button>
      </div>

      {/* ── CURL PASTE ZONE ── */}
      {inputMode === 'curl' && (
      <div className={`connect-paste-zone ${connecting ? 'connecting' : ''}`}>
        <textarea
          ref={textareaRef}
          className="connect-textarea"
          rows={4}
          placeholder={'Paste a cURL command here...\n\nRight-click any request on Amazon Jobs → Copy → Copy as cURL\nThen paste here and click Connect'}
          value={pasteText}
          onChange={(e) => { setPasteText(e.target.value); setPasteError('') }}
          onPaste={(e) => {
            const text = e.clipboardData.getData('text/plain')
            if (text && (text.toLowerCase().startsWith('curl ') || text.includes('Cookie:'))) {
              e.preventDefault()
              setPasteText(text)
            }
          }}
          onKeyDown={(e) => {
            if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') handleConnect()
          }}
          disabled={connecting}
        />
        <div className="connect-paste-actions">
          <span className="connect-paste-hint">
            {pasteText ? `${Object.keys(parseAnyCookieFormat(pasteText).cookies).length} cookies detected` : 'Ctrl+V to paste, Ctrl+Enter to connect'}
          </span>
          <button
            className="refresh small connect-btn"
            onClick={handleConnect}
            disabled={connecting || !pasteText.trim()}
          >
            {connecting ? <Loader2 className="spin" size={14} /> : <Link size={14} />}
            {connecting ? 'Connecting…' : 'Connect'}
          </button>
        </div>
      </div>
      )}

      {pasteError && inputMode === 'curl' && (
        <div className="session-form-error">
          <AlertTriangle size={14} /> {pasteError}
        </div>
      )}

      {/* ── DIRECT COOKIE ZONE ── */}
      {inputMode === 'cookies' && (
        <div className="direct-cookie-zone">
          <div className="direct-cookie-info">
            <b>Paste your browser cookie export:</b>
            <p style={{margin:'4px 0 6px', fontSize:'12px', color:'#334155'}}>
              Supports two formats — paste directly:
            </p>
            <ul style={{margin:'0 0 8px 16px', padding:0, fontSize:'12px', color:'#334155', lineHeight:'1.7'}}>
              <li><b>JSON Array</b> — exported from Cookie Editor extension <code>[{"{"}...{"}"}]</code></li>
              <li><b>Cookie String</b> — <code>name=value; name2=value2</code></li>
            </ul>
            <p className="direct-cookie-hint">
              Chrome Extension: Install <b>Cookie Editor</b> → go to jobsatamazon.co.uk → Export → All cookies → paste here
            </p>
          </div>
          <div className={`connect-paste-zone ${connectingCookie ? 'connecting' : ''}`}>
            <textarea
              className="connect-textarea"
              rows={5}
              placeholder={'JSON Array format:\n[{"name":"HVH_ACCESS_TOKEN","value":"eyJ..."},{"name":"JSESSIONID","value":"xxx"},...]\n\nঅথবা Cookie String:\nHVH_ACCESS_TOKEN=eyJ...; JSESSIONID=xxx; aws-waf-token=xxx'}
              value={cookieText}
              onChange={(e) => { setCookieText(e.target.value); setCookieError('') }}
              onKeyDown={(e) => { if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') handleDirectCookieConnect() }}
              disabled={connectingCookie}
            />
            <div className="connect-paste-actions">
              <span className="connect-paste-hint">
                {cookieText
                  ? (() => {
                      try {
                        const arr = JSON.parse(cookieText.trim())
                        if (Array.isArray(arr)) return `${arr.filter(c => c.name && c.value).length} cookies detected (JSON)`
                      } catch {}
                      return `${cookieText.split(';').filter(p => p.includes('=')).length} cookies detected`
                    })()
                  : 'JSON Array বা Cookie String paste করুন'}
              </span>
              <button
                className="refresh small connect-btn"
                onClick={handleDirectCookieConnect}
                disabled={connectingCookie || !cookieText.trim()}
              >
                {connectingCookie ? <Loader2 className="spin" size={14} /> : <Link size={14} />}
                {connectingCookie ? 'Connecting…' : 'Connect'}
              </button>
            </div>
          </div>
          {cookieError && (
            <div className="session-form-error">
              <AlertTriangle size={14} /> {cookieError}
            </div>
          )}
        </div>
      )}

      {/* ── CONNECTED ACCOUNTS ── */}
      {sessions.length > 0 && (
        <div className="session-cards">
          {sessions.map((s) => (
            <div key={s._id} className={`session-card ${s.lastStatus === 'slot_detected' ? 'card-alert' : s.lastStatus === 'session_expired' ? 'card-expired' : ''}`}>
              <div className="session-card-top">
                <div className="session-card-avatar">
                  {s.applicantName.charAt(0).toUpperCase()}
                </div>
                <div className="session-card-info">
                  <b>{s.applicantName}</b>
                  <small>{s.email || s.label}</small>
                </div>
                <div className={`session-card-status status tone-${
                  s.lastStatus === 'slot_detected' ? 'green' :
                  s.lastStatus === 'session_expired' ? 'red' :
                  s.lastStatus === 'error' ? 'red' :
                  s.lastStatus === 'checking' ? 'amber' : 'slate'
                }`}>
                  <span className="dot" />
                  {s.lastStatus === 'slot_detected' && <Zap size={12} />}
                  {s.lastStatus === 'session_expired' && <ShieldAlert size={12} />}
                  {s.lastStatus.replace('_', ' ')}
                </div>
              </div>
              <div className="session-card-bottom">
                <span className="session-card-time">
                  <Link size={11} /> {Object.keys(s.cookies).length} cookies · {timeSince(s.lastCheckAt)}
                </span>
                <div className="session-card-actions">
                  <button
                    className="session-check-btn"
                    onClick={() => checkSession(s._id)}
                    disabled={s.lastStatus === 'checking'}
                    title="Check now"
                  >
                    {s.lastStatus === 'checking' ? <Loader2 className="spin" size={14} /> : <RefreshCw size={14} />}
                  </button>
                  <button
                    className="session-delete-btn"
                    onClick={() => handleDelete(s._id, s.applicantName)}
                    title="Disconnect"
                  >
                    <Trash2 size={14} />
                  </button>
                </div>
              </div>
              <div className="session-card-link">
                <div className="link-field">
                  <Link2 size={12} />
                  <select
                    value={s.applicationId || ''}
                    onChange={(e) => handleLink(s._id, e.target.value)}
                  >
                    <option value="">Link to application…</option>
                    {applications.map((a) => (
                      <option key={a.id} value={a.id}>
                        {a.jobTitle} — {a.location}
                      </option>
                    ))}
                  </select>
                </div>
                {s.applicationId && (
                  <span className="linked-app-label">
                    Linked to {applications.find((a) => a.id === s.applicationId)?.jobTitle || s.applicationId}
                  </span>
                )}
              </div>
              {s.lastError && (
                <div className="session-card-error">
                  <AlertTriangle size={12} /> {simplifyError(s.lastError)}
                </div>
              )}
            </div>
          ))}
        </div>
      )}

      {sessions.length === 0 && !loading && (
        <div className="session-empty">
          <Cookie size={40} />
          <b>No connected accounts</b>
          <span>Paste your Amazon cookies above to start monitoring</span>
        </div>
      )}

      {/* ── ACTIVITY LOG ── */}
      {activity.length > 0 && (
        <div className="session-activity">
          <div className="feed-head">
            <h3>Activity</h3>
            <span>{activity.length} events</span>
          </div>
          <div className="timeline">
            {activity.map((event) => (
              <div className="event" key={event.id}>
                <div className={`event-dot ${tone(event.tone)}`} />
                <div>
                  <b>{event.text}</b>
                  <small>{event.time}</small>
                </div>
              </div>
            ))}
          </div>
        </div>
      )}
    </section>
  )
}
