import { getPayload, type Where } from 'payload'
import React from 'react'

import config from '@/payload.config'
import './styles.css'
import { PastorsTable, type PastorRow } from './PastorsTable'

export const dynamic = 'force-dynamic'

const PAGE_SIZE = 25

// Idioma usado para mostrar los códigos ISO de país como nombres legibles.
const DISPLAY_LOCALE = 'es'
const regionNames = new Intl.DisplayNames([DISPLAY_LOCALE], { type: 'region' })

const localizedCountry = (code?: string | null): string | null => {
  if (!code) return null
  try {
    return regionNames.of(code.toUpperCase()) ?? code
  } catch {
    return code
  }
}

// Código ISO alpha-2 -> emoji de bandera (símbolos indicadores regionales).
const flag = (code?: string | null): string => {
  if (!code || code.length !== 2) return ''
  const base = 0x1f1e6
  const cc = code.toUpperCase()
  return String.fromCodePoint(base + (cc.charCodeAt(0) - 65), base + (cc.charCodeAt(1) - 65))
}

// Accent/case-insensitive normalizer for search matching ("méxico" ~ "mexico").
const normalize = (s: string): string =>
  s
    .normalize('NFD')
    .replace(/\p{Diacritic}/gu, '')
    .toLowerCase()
    .trim()

// All ISO 3166-1 alpha-2 codes, so a country typed by name resolves to its code
// (country is stored as the ISO code, e.g. "MX" for México).
// prettier-ignore
const ALPHA2 = ['AD','AE','AF','AG','AI','AL','AM','AO','AQ','AR','AS','AT','AU','AW','AX','AZ','BA','BB','BD','BE','BF','BG','BH','BI','BJ','BL','BM','BN','BO','BQ','BR','BS','BT','BV','BW','BY','BZ','CA','CC','CD','CF','CG','CH','CI','CK','CL','CM','CN','CO','CR','CU','CV','CW','CX','CY','CZ','DE','DJ','DK','DM','DO','DZ','EC','EE','EG','EH','ER','ES','ET','FI','FJ','FK','FM','FO','FR','GA','GB','GD','GE','GF','GG','GH','GI','GL','GM','GN','GP','GQ','GR','GS','GT','GU','GW','GY','HK','HM','HN','HR','HT','HU','ID','IE','IL','IM','IN','IO','IQ','IR','IS','IT','JE','JM','JO','JP','KE','KG','KH','KI','KM','KN','KP','KR','KW','KY','KZ','LA','LB','LC','LI','LK','LR','LS','LT','LU','LV','LY','MA','MC','MD','ME','MF','MG','MH','MK','ML','MM','MN','MO','MP','MQ','MR','MS','MT','MU','MV','MW','MX','MY','MZ','NA','NC','NE','NF','NG','NI','NL','NO','NP','NR','NU','NZ','OM','PA','PE','PF','PG','PH','PK','PL','PM','PN','PR','PS','PT','PW','PY','QA','RE','RO','RS','RU','RW','SA','SB','SC','SD','SE','SG','SH','SI','SJ','SK','SL','SM','SN','SO','SR','SS','ST','SV','SX','SY','SZ','TC','TD','TF','TG','TH','TJ','TK','TL','TM','TN','TO','TR','TT','TV','TW','TZ','UA','UG','UM','US','UY','UZ','VA','VC','VE','VG','VI','VN','VU','WF','WS','YE','YT','ZA','ZM','ZW']

// Precomputed [normalizedName, code] pairs in the display locale.
const COUNTRY_NAME_INDEX: [string, string][] = ALPHA2.map((code) => [
  normalize(localizedCountry(code) ?? code),
  code,
])

// Country codes whose localized name contains the search term.
const countryCodesMatching = (term: string): string[] => {
  const t = normalize(term)
  if (!t) return []
  return COUNTRY_NAME_INDEX.filter(([name]) => name.includes(t)).map(([, code]) => code)
}

export default async function HomePage({
  searchParams,
}: {
  searchParams: Promise<{ q?: string; page?: string }>
}) {
  const { q = '', page = '1' } = await searchParams
  const currentPage = Math.max(1, parseInt(page, 10) || 1)
  const search = q.trim()

  const payload = await getPayload({ config: await config })

  // Country is stored as an ISO code, so resolve any country *name* in the
  // search term to its code(s) and match those too.
  const countryCodes = countryCodesMatching(search)
  const where: Where = search
    ? {
        or: [
          { name: { like: search } },
          { email: { like: search } },
          { city: { like: search } },
          { country: { like: search } },
          ...(countryCodes.length ? [{ country: { in: countryCodes } }] : []),
        ],
      }
    : {}

  const result = await payload.find({
    collection: 'pastors',
    where,
    sort: 'name',
    depth: 1,
    page: currentPage,
    limit: PAGE_SIZE,
  })

  // Running total of impacted people across ALL matching records (not just the
  // current page). Only the number field is selected to keep this light.
  const impactedAgg = await payload.find({
    collection: 'pastors',
    where,
    pagination: false,
    depth: 0,
    select: { impactedPeople: true },
  })
  const totalImpacted = impactedAgg.docs.reduce((sum, d) => sum + (d.impactedPeople ?? 0), 0)

  const rows: PastorRow[] = result.docs.map((p) => {
    const letter = p.letter && typeof p.letter === 'object' ? p.letter : null
    return {
      id: p.id,
      name: p.name,
      churchName: p.churchName ?? null,
      email: p.email ?? null,
      telephone: Array.isArray(p.telephone) ? p.telephone.filter(Boolean) : [],
      place: p.place ?? null,
      city: p.city ?? null,
      state: p.state ?? null,
      country: p.country ?? null,
      countryName: localizedCountry(p.country),
      countryFlag: flag(p.country),
      impactedPeople: p.impactedPeople ?? null,
      churchRegistered: Boolean(p.churchRegistered),
      registrationNumber: p.registrationNumber ?? null,
      inTelegram: Boolean(p.inTelegram),
      notes: p.notes ?? null,
      letterUrl: letter?.url ?? null,
      letterName: letter?.filename ?? null,
    }
  })

  return (
    <section className="max-w-7xl mx-auto w-full px-4 py-10">
      <div className="flex flex-wrap items-center justify-between gap-4 mb-6">
        <div>
          <h1 className="text-3xl font-bold">Pastores</h1>
          <p className="text-base-content/60 text-sm mt-1">
            {result.totalDocs.toLocaleString('es')} registros
            <span className="mx-2 opacity-40">·</span>
            <span className="font-medium text-base-content/80">
              {totalImpacted.toLocaleString('es')}
            </span>{' '}
            personas impactadas
          </p>
        </div>
        <form method="get" className="join">
          <input
            type="text"
            name="q"
            defaultValue={search}
            placeholder="Buscar nombre, correo, ciudad, país…"
            className="input input-bordered join-item w-64 max-w-full"
          />
          <button type="submit" className="btn btn-primary join-item">
            Buscar
          </button>
          {search && (
            <a href="/" className="btn btn-ghost join-item">
              Limpiar
            </a>
          )}
        </form>
      </div>

      <PastorsTable rows={rows} />

      <div className="flex items-center justify-between mt-6">
        <p className="text-sm text-base-content/60">
          Página {result.page} de {result.totalPages}
        </p>
        <div className="join">
          <a
            href={`/?${new URLSearchParams({ ...(search ? { q: search } : {}), page: String(currentPage - 1) })}`}
            className={`btn join-item ${result.hasPrevPage ? '' : 'btn-disabled'}`}
            aria-disabled={!result.hasPrevPage}
          >
            « Anterior
          </a>
          <a
            href={`/?${new URLSearchParams({ ...(search ? { q: search } : {}), page: String(currentPage + 1) })}`}
            className={`btn join-item ${result.hasNextPage ? '' : 'btn-disabled'}`}
            aria-disabled={!result.hasNextPage}
          >
            Siguiente »
          </a>
        </div>
      </div>
    </section>
  )
}
