import { useState, useEffect, useRef, useCallback } from 'react'
import { useNavigate, Link } from 'react-router-dom'
import { Ticket, ChevronDown, Check, AlertCircle } from 'lucide-react'
import { integrationsApi } from '@/api/integrations'
import type { PSABoard, PSATicketSearchResult } from '@/types/integrations'
import { cn } from '@/lib/utils'

const PAGE_SIZE = 5

type Tab = 'mine' | 'unassigned'

function SkeletonRows() {
  return (
    <div className="space-y-0">
      {[0, 1, 2].map((i) => (
        <div
          key={i}
          className="flex items-center gap-4 px-5 py-3.5"
          style={{ borderBottom: '1px solid var(--color-border-default)' }}
        >
          <div className="flex-1 space-y-2">
            <div className="h-3 w-1/3 rounded bg-[rgba(255,255,255,0.06)] animate-pulse" />
            <div className="h-3 w-2/3 rounded bg-[rgba(255,255,255,0.04)] animate-pulse" />
            <div className="h-2.5 w-1/4 rounded bg-[rgba(255,255,255,0.03)] animate-pulse" />
          </div>
          <div className="h-6 w-16 rounded bg-[rgba(255,255,255,0.04)] animate-pulse shrink-0" />
          <div className="h-7 w-24 rounded bg-[rgba(255,255,255,0.04)] animate-pulse shrink-0" />
        </div>
      ))}
    </div>
  )
}

interface BoardSelectorProps {
  boards: PSABoard[]
  selectedIds: number[]
  onChange: (ids: number[]) => void
}

function BoardSelector({ boards, selectedIds, onChange }: BoardSelectorProps) {
  const [open, setOpen] = useState(false)
  const ref = useRef<HTMLDivElement>(null)

  useEffect(() => {
    function handleClickOutside(e: MouseEvent) {
      if (ref.current && !ref.current.contains(e.target as Node)) {
        setOpen(false)
      }
    }
    if (open) {
      document.addEventListener('mousedown', handleClickOutside)
    }
    return () => document.removeEventListener('mousedown', handleClickOutside)
  }, [open])

  const allSelected = selectedIds.length === 0
  const label = allSelected
    ? 'All Boards'
    : selectedIds.length === 1
    ? (boards.find((b) => b.id === selectedIds[0])?.name ?? '1 board')
    : `${selectedIds.length} boards`

  const handleAllBoards = () => {
    onChange([])
  }

  const handleToggleBoard = (id: number) => {
    if (selectedIds.includes(id)) {
      const next = selectedIds.filter((x) => x !== id)
      onChange(next)
    } else {
      onChange([...selectedIds, id])
    }
  }

  if (boards.length === 0) return null

  return (
    <div ref={ref} className="relative">
      <button
        onClick={() => setOpen((v) => !v)}
        className="flex items-center gap-1.5 rounded-lg border border-[rgba(255,255,255,0.08)] bg-[rgba(255,255,255,0.04)] px-3 py-1.5 text-xs text-muted-foreground hover:text-foreground hover:border-[rgba(255,255,255,0.14)] transition-colors"
      >
        {label}
        <ChevronDown size={12} className={cn('transition-transform', open && 'rotate-180')} />
      </button>

      {open && (
        <div className="absolute right-0 top-full mt-1 z-50 w-52 rounded-lg border border-[rgba(255,255,255,0.1)] bg-card shadow-lg py-1">
          {/* All Boards */}
          <button
            onClick={handleAllBoards}
            className="flex w-full items-center gap-2.5 px-3 py-2 text-xs text-foreground hover:bg-[rgba(255,255,255,0.06)] transition-colors"
          >
            <span
              className={cn(
                'flex h-3.5 w-3.5 shrink-0 items-center justify-center rounded border',
                allSelected
                  ? 'border-accent bg-accent'
                  : 'border-[rgba(255,255,255,0.2)] bg-transparent',
              )}
            >
              {allSelected && <Check size={9} className="text-white" />}
            </span>
            All Boards
          </button>

          {boards.length > 0 && (
            <div className="my-1" style={{ borderTop: '1px solid var(--color-border-default)' }} />
          )}

          {boards.map((board) => {
            const checked = selectedIds.includes(board.id)
            return (
              <button
                key={board.id}
                onClick={() => handleToggleBoard(board.id)}
                className="flex w-full items-center gap-2.5 px-3 py-2 text-xs text-foreground hover:bg-[rgba(255,255,255,0.06)] transition-colors"
              >
                <span
                  className={cn(
                    'flex h-3.5 w-3.5 shrink-0 items-center justify-center rounded border',
                    checked
                      ? 'border-accent bg-accent'
                      : 'border-[rgba(255,255,255,0.2)] bg-transparent',
                  )}
                >
                  {checked && <Check size={9} className="text-white" />}
                </span>
                <span className="truncate">{board.name}</span>
              </button>
            )
          })}
        </div>
      )}
    </div>
  )
}

interface TicketRowProps {
  ticket: PSATicketSearchResult
  isLast: boolean
  onStartSession: (ticket: PSATicketSearchResult) => void
}

function TicketRow({ ticket, isLast, onStartSession }: TicketRowProps) {
  return (
    <div
      className="flex items-center gap-3 px-5 py-3.5"
      style={{ borderBottom: isLast ? undefined : '1px solid var(--color-border-default)' }}
    >
      {/* Left: ticket info */}
      <div className="flex-1 min-w-0">
        <div className="flex items-baseline gap-2 mb-0.5">
          <span className="font-mono text-xs font-semibold text-accent shrink-0">
            #{ticket.id}
          </span>
          <span className="text-sm text-foreground truncate">{ticket.summary}</span>
        </div>
        <div className="flex items-center gap-1.5 text-[0.6875rem] text-muted-foreground">
          {ticket.company_name && <span className="truncate">{ticket.company_name}</span>}
          {ticket.company_name && ticket.priority_name && (
            <span className="shrink-0">&middot;</span>
          )}
          {ticket.priority_name && <span className="shrink-0">{ticket.priority_name}</span>}
        </div>
      </div>

      {/* Right: status badge + action */}
      <div className="flex items-center gap-2 shrink-0">
        {ticket.status_name && (
          <span className="hidden sm:inline-flex items-center rounded-md border border-[rgba(255,255,255,0.08)] bg-[rgba(255,255,255,0.04)] px-2 py-0.5 text-[0.625rem] text-muted-foreground">
            {ticket.status_name}
          </span>
        )}
        <button
          onClick={() => onStartSession(ticket)}
          className="flex items-center gap-1.5 rounded-lg border border-accent/30 bg-accent-dim px-3 py-1.5 text-xs font-medium text-accent hover:bg-accent/20 hover:border-accent/50 transition-colors"
        >
          <Ticket size={11} />
          Start Session
        </button>
      </div>
    </div>
  )
}

export function TicketQueue() {
  const navigate = useNavigate()
  const [hasConnection, setHasConnection] = useState<boolean | null>(null)
  const [hasMemberMapping, setHasMemberMapping] = useState<boolean | null>(null) // null = loading
  const [boards, setBoards] = useState<PSABoard[]>([])
  const [selectedBoardIds, setSelectedBoardIds] = useState<number[]>([])
  const [activeTab, setActiveTab] = useState<Tab>('mine')
  const [tickets, setTickets] = useState<PSATicketSearchResult[]>([])
  const [loading, setLoading] = useState(false)
  // Monotonically increasing fetch token — late responses with a stale id
  // are dropped so they can't overwrite the latest query's results.
  const latestRequestId = useRef(0)
  const [error, setError] = useState<string | null>(null)

  // Check connection on mount
  useEffect(() => {
    integrationsApi.getConnection()
      .then((conn) => {
        const active = !!(conn && conn.is_active)
        setHasConnection(active)
      })
      .catch(() => setHasConnection(false))
  }, [])

  // Detect member mapping on mount
  useEffect(() => {
    integrationsApi.getMemberMappings()
      .then(mappings => {
        setHasMemberMapping(mappings.length > 0)
      })
      .catch(() => setHasMemberMapping(false))
  }, [])

  // Fetch boards once connection confirmed
  useEffect(() => {
    if (!hasConnection) return
    integrationsApi.listBoards()
      .then(setBoards)
      .catch(() => {}) // boards are optional — don't block UI
  }, [hasConnection])

  const fetchTickets = useCallback(
    async (tab: Tab, boardIds: number[]) => {
      const params: Parameters<typeof integrationsApi.searchTicketsQueue>[0] = {
        page: 1,
        page_size: PAGE_SIZE,
      }
      if (tab === 'mine') {
        params.assigned_to_me = true
      } else {
        params.unassigned = true
      }
      if (boardIds.length > 0) {
        params.board_ids = boardIds.join(',')
      }

      // Clear stale data + flip loading inside the async function so the
      // writes happen after the awaitable boundary — avoids the
      // synchronous-setState-in-effect cascade the lint rule flags. The
      // fetch is also wrapped in a request-id check so a stale response
      // can't clobber a newer query.
      const requestId = ++latestRequestId.current
      setTickets([])
      setLoading(true)

      try {
        const results = await integrationsApi.searchTicketsQueue(params)
        if (requestId !== latestRequestId.current) return
        setTickets(results.items)
        setError(null)
      } catch {
        if (requestId !== latestRequestId.current) return
        setError('Failed to load tickets. Check your PSA connection.')
      } finally {
        if (requestId === latestRequestId.current) setLoading(false)
      }
    },
    [],
  )

  // Initial + reset fetch when tab or board selection changes
  useEffect(() => {
    if (!hasConnection) return
    if (activeTab === 'mine' && hasMemberMapping !== true) return
    fetchTickets(activeTab, selectedBoardIds)
  }, [activeTab, selectedBoardIds, hasConnection, hasMemberMapping, fetchTickets])

  const handleStartSession = (ticket: PSATicketSearchResult) => {
    navigate('/pilot', {
      state: {
        psaTicketId: ticket.id,
        psaTicket: {
          id: ticket.id,
          summary: ticket.summary,
          company_name: ticket.company_name,
          board_name: ticket.board_name,
          status_name: ticket.status_name,
          priority_name: ticket.priority_name,
        },
      },
    })
  }

  // Don't render until we know connection status
  if (hasConnection === null) return null
  // No active connection → hide entirely
  if (!hasConnection) return null

  return (
    <div className="card-flat overflow-hidden">
      {/* Header */}
      <div
        className="flex items-center justify-between px-5 py-3"
        style={{ borderBottom: '1px solid var(--color-border-default)' }}
      >
        <div className="flex items-center gap-2">
          <Ticket size={14} className="text-accent" />
          <h3 className="font-heading text-sm font-bold text-foreground">Ticket Queue</h3>
        </div>
        <BoardSelector
          boards={boards}
          selectedIds={selectedBoardIds}
          onChange={(ids) => setSelectedBoardIds(ids)}
        />
      </div>

      {/* Tabs */}
      <div
        className="flex"
        style={{ borderBottom: '1px solid var(--color-border-default)' }}
      >
        {(['mine', 'unassigned'] as Tab[]).map((tab) => (
          <button
            key={tab}
            onClick={() => setActiveTab(tab)}
            className={cn(
              'px-5 py-2.5 text-xs font-medium transition-colors border-b-2 -mb-px',
              activeTab === tab
                ? 'border-accent text-accent'
                : 'border-transparent text-muted-foreground hover:text-foreground',
            )}
          >
            {tab === 'mine' ? 'My Tickets' : 'Unassigned'}
          </button>
        ))}
      </div>

      {/* Content */}
      <div>
        {/* Mapping prompt for "mine" tab when no member mapping configured */}
        {activeTab === 'mine' && hasMemberMapping === false && (
          <div className="px-5 py-6 text-center">
            <p className="text-sm text-muted-foreground">
              <Link to="/account/integrations" className="text-accent hover:underline">
                Map your PSA member
              </Link>{' '}
              to see your ticket queue.
            </p>
          </div>
        )}

        {/* Error */}
        {error && (
          <div className="flex items-center gap-2 px-5 py-4 text-sm text-danger">
            <AlertCircle size={14} className="shrink-0" />
            <span>{error}</span>
          </div>
        )}

        {/* Loading skeleton */}
        {!error && loading && <SkeletonRows />}

        {/* Ticket rows */}
        {!error && !loading && tickets.length > 0 && (
          <>
            {tickets.map((ticket, i) => (
              <TicketRow
                key={ticket.id}
                ticket={ticket}
                isLast={i === tickets.length - 1}
                onStartSession={handleStartSession}
              />
            ))}
          </>
        )}

        {/* View all tickets link */}
        {tickets.length > 0 && (
          <div className="px-5 py-3 border-t border-default">
            <Link
              to="/tickets?assigned=me"
              className="text-xs text-accent hover:text-accent/80 transition-colors"
            >
              View all tickets →
            </Link>
          </div>
        )}

        {/* Empty states */}
        {!error && !loading && tickets.length === 0 && (
          <div className="px-5 py-8 text-center">
            <Ticket size={24} className="mx-auto mb-2 text-muted-foreground/40" />
            {activeTab === 'mine' ? (
              <>
                <p className="text-sm text-muted-foreground">No open tickets assigned to you</p>
                <p className="mt-1 text-[0.6875rem] text-muted-foreground/60">
                  Make sure your member mapping is configured in Account &rarr; Integrations
                </p>
              </>
            ) : (
              <p className="text-sm text-muted-foreground">No unassigned open tickets</p>
            )}
          </div>
        )}

      </div>
    </div>
  )
}
