import { useMemo, useState } from 'react'
import { Link } from 'react-router'
import { useQuery, useQueries } from '@tanstack/react-query'
import { apiFetch, apiFetchBlob } from '@/lib/api'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import type { Invoice, WorkOrder, Client, Vehicle } from '@/lib/types'

type PeriodKey = 'month' | '30d' | '90d' | 'year' | 'all'
type DocFilter = 'all' | 'quote' | 'invoice'

const PERIOD_OPTIONS: { key: PeriodKey; label: string }[] = [
  { key: 'month', label: 'Mês atual' },
  { key: '30d', label: '30 dias' },
  { key: '90d', label: '90 dias' },
  { key: 'year', label: '12 meses' },
  { key: 'all', label: 'Todo o período' },
]

function getPeriodStart(period: PeriodKey, now = new Date()) {
  const start = new Date(now)
  if (period === 'all') return null
  if (period === 'month') {
    start.setDate(1)
    start.setHours(0, 0, 0, 0)
    return start
  }
  if (period === '30d') {
    start.setDate(now.getDate() - 30)
    return start
  }
  if (period === '90d') {
    start.setDate(now.getDate() - 90)
    return start
  }
  start.setMonth(now.getMonth() - 12)
  return start
}

export default function InvoicesPage() {
  const [viewError, setViewError] = useState('')
  const [period, setPeriod] = useState<PeriodKey>('month')
  const [clientFilter, setClientFilter] = useState('all')
  const [docFilter, setDocFilter] = useState<DocFilter>('all')
  const [dateFrom, setDateFrom] = useState('')
  const [dateTo, setDateTo] = useState('')

  const { data: invoices = [], isLoading } = useQuery<Invoice[]>({
    queryKey: ['invoices'],
    queryFn: () => apiFetch<Invoice[]>('/invoices'),
  })

  const { data: workOrders = [] } = useQuery<WorkOrder[]>({
    queryKey: ['work-orders-for-transactions'],
    queryFn: () => apiFetch<WorkOrder[]>('/work-orders'),
  })
  const { data: clients = [] } = useQuery<Client[]>({
    queryKey: ['clients'],
    queryFn: () => apiFetch<Client[]>('/clients'),
  })

  const clientNameById = Object.fromEntries(clients.map((c) => [c.id, c.name]))
  const woById = Object.fromEntries(workOrders.map((wo) => [wo.id, wo]))
  const uniqueClientIds = Array.from(
    new Set(workOrders.map((wo) => wo.client_id).filter((id): id is string => !!id))
  )
  const vehiclesByClientQ = useQueries({
    queries: uniqueClientIds.map((clientId) => ({
      queryKey: ['vehicles', clientId, 'transactions'],
      queryFn: () => apiFetch<Vehicle[]>(`/clients/${clientId}/vehicles`),
      staleTime: 5 * 60 * 1000,
    })),
  })
  const vehicleById = useMemo(() => {
    const map: Record<string, Vehicle> = {}
    for (const q of vehiclesByClientQ) {
      for (const v of (q.data ?? [])) map[v.id] = v
    }
    return map
  }, [vehiclesByClientQ])

  const filtered = useMemo(() => {
    const start = getPeriodStart(period)
    return invoices.filter((inv) => {
      if (docFilter !== 'all' && inv.type !== docFilter) return false
      const wo = woById[inv.work_order_id]
      if (clientFilter !== 'all' && wo?.client_id !== clientFilter) return false
      const issued = new Date(inv.issued_at)
      if (start && issued < start) return false
      if (dateFrom) {
        const from = new Date(`${dateFrom}T00:00:00`)
        if (issued < from) return false
      }
      if (dateTo) {
        const to = new Date(`${dateTo}T23:59:59`)
        if (issued > to) return false
      }
      return true
    })
  }, [invoices, woById, period, clientFilter, docFilter, dateFrom, dateTo])

  const sorted = [...filtered].sort(
    (a, b) => new Date(b.issued_at).getTime() - new Date(a.issued_at).getTime()
  )
  const totalQuotes = sorted.filter((d) => d.type === 'quote').length
  const totalInvoices = sorted.filter((d) => d.type === 'invoice').length

  async function openPDF(inv: Invoice) {
    setViewError('')
    try {
      const blob = await apiFetchBlob(`/invoices/${inv.id}/pdf`)
      const url = URL.createObjectURL(blob)
      window.open(url, '_blank', 'noopener,noreferrer')
      setTimeout(() => URL.revokeObjectURL(url), 60_000)
    } catch (err) {
      setViewError((err as Error).message)
    }
  }

  return (
    <div>
      <div className="mb-6 flex items-center justify-between gap-4">
        <div>
          <h1 className="text-2xl font-bold text-white">Transações</h1>
          <p className="mt-0.5 text-sm text-slate-400">
            Consulta e impressão de documentos gerados pelo fluxo das OTs.
          </p>
        </div>
        <Link to="/app/work-orders" className="text-xs text-cyan-300 hover:text-cyan-200">
          Ir para Ordens de Trabalho →
        </Link>
      </div>

      <div className="mb-4 grid gap-3 rounded-lg border border-slate-700 bg-slate-900/50 p-4 md:grid-cols-5">
        <div className="space-y-1">
          <label className="text-xs text-slate-400">Período</label>
          <select
            value={period}
            onChange={(e) => setPeriod(e.target.value as PeriodKey)}
            className="w-full rounded-md border border-slate-600 bg-slate-900 px-3 py-2 text-sm text-white"
          >
            {PERIOD_OPTIONS.map((opt) => (
              <option key={opt.key} value={opt.key}>{opt.label}</option>
            ))}
          </select>
        </div>
        <div className="space-y-1">
          <label className="text-xs text-slate-400">Cliente</label>
          <select
            value={clientFilter}
            onChange={(e) => setClientFilter(e.target.value)}
            className="w-full rounded-md border border-slate-600 bg-slate-900 px-3 py-2 text-sm text-white"
          >
            <option value="all">Todos os clientes</option>
            {clients.map((c) => (
              <option key={c.id} value={c.id}>{c.name}</option>
            ))}
          </select>
        </div>
        <div className="space-y-1">
          <label className="text-xs text-slate-400">Tipo de documento</label>
          <select
            value={docFilter}
            onChange={(e) => setDocFilter(e.target.value as DocFilter)}
            className="w-full rounded-md border border-slate-600 bg-slate-900 px-3 py-2 text-sm text-white"
          >
            <option value="all">Todos</option>
            <option value="quote">Orçamentos</option>
            <option value="invoice">Faturas</option>
          </select>
        </div>
        <div className="space-y-1">
          <label className="text-xs text-slate-400">Data início</label>
          <input
            type="date"
            value={dateFrom}
            onChange={(e) => setDateFrom(e.target.value)}
            className="w-full rounded-md border border-slate-600 bg-slate-900 px-3 py-2 text-sm text-white"
          />
        </div>
        <div className="space-y-1">
          <label className="text-xs text-slate-400">Data fim</label>
          <input
            type="date"
            value={dateTo}
            onChange={(e) => setDateTo(e.target.value)}
            className="w-full rounded-md border border-slate-600 bg-slate-900 px-3 py-2 text-sm text-white"
          />
        </div>
      </div>

      <div className="mb-4 flex items-center gap-3 text-sm">
        <Badge variant="secondary">{totalQuotes} orçamentos</Badge>
        <Badge>{totalInvoices} faturas</Badge>
        <span className="text-slate-400">{sorted.length} documento(s) no filtro atual</span>
      </div>

      {viewError && <p className="mb-4 text-sm text-red-400">{viewError}</p>}

      {isLoading ? (
        <p className="text-slate-400">A carregar...</p>
      ) : sorted.length === 0 ? (
        <p className="text-sm text-slate-500">Nenhum documento encontrado com os filtros selecionados.</p>
      ) : (
        <div className="overflow-hidden rounded-lg border border-slate-700">
          <table className="w-full text-sm">
            <thead className="bg-slate-800">
              <tr>
                <th className="px-4 py-2 text-left font-medium text-slate-400">Tipo</th>
                <th className="px-4 py-2 text-left font-medium text-slate-400">Nº</th>
                <th className="px-4 py-2 text-left font-medium text-slate-400">OT / Cliente / Viatura</th>
                <th className="px-4 py-2 text-left font-medium text-slate-400">Emitida</th>
                <th className="px-4 py-2"></th>
              </tr>
            </thead>
            <tbody>
              {sorted.map((inv) => {
                const wo = woById[inv.work_order_id]
                const clientName = wo?.client_id ? (clientNameById[wo.client_id] ?? '—') : '—'
                const vehiclePlate = wo?.vehicle_id ? (vehicleById[wo.vehicle_id]?.plate ?? '—') : '—'
                return (
                  <tr key={inv.id} className="border-t border-slate-700 hover:bg-slate-800/50">
                    <td className="px-4 py-2">
                      {inv.type === 'quote' ? (
                        <span className="inline-flex rounded-full border border-amber-400 bg-amber-100 px-2 py-0.5 text-xs font-medium text-slate-800">
                          Orçamento
                        </span>
                      ) : (
                        <span className="inline-flex rounded-full border border-emerald-400 bg-emerald-100 px-2 py-0.5 text-xs font-medium text-slate-800">
                          Fatura
                        </span>
                      )}
                    </td>
                    <td className="px-4 py-2 font-mono text-white">#{inv.number}</td>
                    <td className="px-4 py-2 text-xs text-slate-400">
                      <div className="font-mono text-slate-300">#{wo?.number ?? '—'}</div>
                      <div>{clientName}</div>
                      <div>{vehiclePlate}</div>
                    </td>
                    <td className="px-4 py-2 text-slate-400">
                      {new Intl.DateTimeFormat('pt-PT').format(new Date(inv.issued_at))}
                    </td>
                    <td className="px-4 py-2 text-right">
                      <Button size="sm" variant="outline" onClick={() => openPDF(inv)}>Ver PDF</Button>
                    </td>
                  </tr>
                )
              })}
            </tbody>
          </table>
        </div>
      )}
    </div>
  )
}
