"use client";

import { useState, type ReactNode } from "react";
import { AnimatePresence, motion } from "framer-motion";
import { ChartPie, Check, ChevronRight, Copy, Loader2, RefreshCw } from "lucide-react";
import type { ChanceGlobal } from "@/lib/chance-global";
import { FUSO, haQuantoTempo, porcentoLegivel, type MetricasDoLink } from "@/lib/metricas-do-link";
import { AnelDeValor } from "./graficos";
import { faixaDaChance } from "./janela";

/*
  A faixa do orçamento, logo abaixo do título, em três blocos:
  - Criado por: quem fez e quando.
  - Chance de fechar: a chance "no geral" (a taxa da empresa, a relação do
    cliente com ela, o valor e o tempo aberto — lib/chance-global.ts). Abre a
    janela que explica de onde sai o número.
  - Link do orçamento: quantas vezes o cliente abriu, como está o prazo, o
    botão das métricas do link (que continuam iguais, com a chance pelo
    link lá dentro) e o de copiar.

  Uma peça só, no traço do painel do título: blocos com o mesmo desenho
  (rótulo pequeno em cima, valor forte, uma linha útil embaixo), alinhados
  pelo topo e separados por filetes quase invisíveis. A cor aparece em
  pontos pequenos: o anel da chance, o ponto verde de "aberto agora", o
  ponto do estado do link.
*/

const formatoHora = new Intl.DateTimeFormat("pt-BR", { timeZone: FUSO, hour: "2-digit", minute: "2-digit" });
const formatoDia = new Intl.DateTimeFormat("pt-BR", { timeZone: FUSO, day: "2-digit", month: "2-digit" });
const formatoDiaComAno = new Intl.DateTimeFormat("pt-BR", { timeZone: FUSO, day: "2-digit", month: "2-digit", year: "numeric" });
const formatoAno = new Intl.DateTimeFormat("pt-BR", { timeZone: FUSO, year: "numeric" });

/* "06/03" no ano corrente; "06/03/2027" quando é de outro ano. */
function dia(momento: number, agora: number) {
  const data = new Date(momento);
  return formatoAno.format(data) === formatoAno.format(new Date(agora)) ? formatoDia.format(data) : formatoDiaComAno.format(data);
}

/* "22/09 às 15:01" (o ano só aparece quando não é o corrente). */
function quando(iso: string | null | undefined, agora: number) {
  if (!iso) return "";
  const momento = Date.parse(iso);
  return Number.isFinite(momento) ? `${dia(momento, agora)} às ${formatoHora.format(new Date(momento))}` : "";
}

function iniciais(nome: string) {
  const palavras = nome
    .replace(/[()]/g, " ")
    .split(/\s+/)
    .filter((palavra) => /[\p{L}\d]/u.test(palavra));
  return ((palavras[0]?.[0] ?? "") + (palavras[1]?.[0] ?? "")).toUpperCase() || "?";
}

function Rotulo({ children }: { children: ReactNode }) {
  return <p className="text-[10.5px] font-bold uppercase tracking-[0.14em] text-[var(--ks-color-text-soft)]">{children}</p>;
}

/* Um bloco da faixa. Todos começam pelo topo, para os rótulos ficarem na
   mesma linha. As bordas desenham a grade: no celular, duas colunas em cima
   e o link embaixo; no computador, uma linha só. */
function Parte({
  children,
  className = "",
  aoClicar,
  rotuloDoClique,
  seta = false,
}: {
  children: ReactNode;
  className?: string;
  aoClicar?: () => void;
  rotuloDoClique?: string;
  seta?: boolean;
}) {
  const base = `group relative flex min-w-0 flex-col items-stretch justify-start border-[var(--ks-color-border-subtle)] px-4 py-4 text-left sm:px-5 ${className}`;
  if (!aoClicar) return <div className={base}>{children}</div>;
  return (
    <button
      type="button"
      onClick={aoClicar}
      aria-label={rotuloDoClique}
      className={`${base} transition-colors hover:bg-[var(--ks-color-bg-hover)] focus-visible:bg-[var(--ks-color-bg-hover)] focus-visible:outline-none`}
    >
      {children}
      {seta ? (
        <ChevronRight
          size={16}
          aria-hidden
          className="absolute right-3 top-1/2 -translate-y-1/2 text-[var(--ks-color-text-soft)] opacity-0 transition-opacity group-hover:opacity-100 group-focus-visible:opacity-100"
        />
      ) : null}
    </button>
  );
}

type EstadoDoLink = { ponto: string; titulo: string; texto: string; vencido: boolean; enviado: boolean };

const dias = (quantidade: number) => `${quantidade} ${quantidade === 1 ? "dia" : "dias"}`;

/*
  O prazo é gravado na hora de copiar ou mandar o link (lib/prazo-do-link.ts).
  Antes disso o link não foi para ninguém, e dizer "sem prazo" confundia quem
  ligou a validade de 5 dias: a faixa diz "ainda não enviado" e qual validade
  vai valer. Enviado = um envio registrado (painel ou API), uma abertura do
  cliente (inclusive as de antes do registro detalhado) ou um prazo já gravado.
  Orçamento que já virou pedido ou foi recusado diz só "não enviado".
*/
function estadoDoLink(input: {
  ativo: boolean;
  venceEm: string | null;
  agora: number;
  enviado: boolean;
  encerrado: boolean;
  prazoConfigurado: number | null;
}): EstadoDoLink {
  const { venceEm, agora, prazoConfigurado } = input;
  const vence = venceEm ? Date.parse(venceEm) : NaN;
  const temPrazo = Number.isFinite(vence);

  /* Link desligado depois de usado: o que foi registrado fica nas métricas. */
  if (!input.ativo && input.enviado) {
    return {
      ponto: "var(--ks-color-border-strong)",
      titulo: "Link desligado",
      texto: "As aberturas registradas continuam nas métricas",
      vencido: false,
      enviado: true,
    };
  }
  if (!input.ativo || (!input.enviado && !temPrazo)) {
    return {
      ponto: "var(--ks-color-border-strong)",
      titulo: input.encerrado ? "Não enviado" : "Ainda não enviado",
      texto: prazoConfigurado ? `Vale ${dias(prazoConfigurado)} depois de enviado` : "Depois de enviado, não vence",
      vencido: false,
      enviado: false,
    };
  }
  if (!temPrazo) {
    return {
      ponto: "var(--ks-color-status-success)",
      titulo: "Sem prazo",
      /* Mandado antes de a empresa ligar a validade: vale o que foi gravado
         no envio, e a próxima cópia aplica o prazo. */
      texto: prazoConfigurado ? `Copie de novo para valer ${dias(prazoConfigurado)}` : "O link não vence",
      vencido: false,
      enviado: true,
    };
  }
  if (vence < agora) {
    return {
      ponto: "var(--ks-color-status-danger)",
      titulo: `Venceu em ${dia(vence, agora)}`,
      texto: "O cliente não consegue mais abrir",
      vencido: true,
      enviado: true,
    };
  }
  const faltam = Math.ceil((vence - agora) / 86_400_000);
  return {
    ponto: "var(--ks-brand-500)",
    titulo: `Vence em ${dia(vence, agora)}`,
    texto: faltam <= 1 ? "Falta menos de um dia" : `Faltam ${faltam} dias`,
    vencido: false,
    enviado: true,
  };
}

/* O prazo mais recente entre o da tela e o das métricas: copiar de novo só
   empurra o prazo para a frente, então o maior é o que vale — seja a cópia
   feita agora nesta tela, seja uma feita em outra aba. */
function prazoMaisRecente(...prazos: Array<string | null | undefined>) {
  let maior: string | null = null;
  for (const prazo of prazos) {
    if (!prazo || !Number.isFinite(Date.parse(prazo))) continue;
    if (!maior || Date.parse(prazo) > Date.parse(maior)) maior = prazo;
  }
  return maior;
}

function Maiuscula({ texto }: { texto: string }) {
  return <>{texto.charAt(0).toUpperCase() + texto.slice(1)}</>;
}

/* O conteúdo do bloco da chance: anel pequeno, faixa (Alta, Média, Baixa) e
   uma linha de contexto. */
function ResumoDaChance({ chance, erro, agora }: { chance: ChanceGlobal | null; erro: boolean; agora: number }) {
  if (!chance && erro) {
    return (
      <>
        <AnelDeValor fracao={0} tamanho={44} espessura={5} rotulo="Chance de fechar indisponível">
          <span className="text-[12px] font-extrabold text-[var(--ks-color-text-soft)]">—</span>
        </AnelDeValor>
        <span className="text-xs leading-4 text-[var(--ks-color-text-muted)]">Não deu para calcular agora</span>
      </>
    );
  }
  if (!chance) {
    return (
      <>
        <AnelDeValor fracao={0} tamanho={44} espessura={5} rotulo="Calculando a chance de fechar">
          <Loader2 size={14} className="animate-spin text-[var(--ks-color-text-soft)]" />
        </AnelDeValor>
        <span className="text-xs text-[var(--ks-color-text-muted)]">Calculando…</span>
      </>
    );
  }
  if (chance.estado === "fechado") {
    return (
      <>
        <AnelDeValor fracao={1} tamanho={44} espessura={5} cor="var(--ks-color-status-success)" rotulo="Virou pedido">
          <Check size={16} className="text-[var(--ks-color-status-success)]" />
        </AnelDeValor>
        <div className="min-w-0">
          <div className="text-sm font-bold text-[var(--ks-color-text-primary)]">Virou pedido</div>
          {chance.em ? <div className="text-xs text-[var(--ks-color-text-muted)]">em {dia(Date.parse(chance.em), agora)}</div> : null}
        </div>
      </>
    );
  }
  if (chance.estado === "aprovado") {
    return (
      <>
        <AnelDeValor fracao={1} tamanho={44} espessura={5} cor="var(--ks-color-status-warning)" rotulo="Aprovado no painel, sem pedido gerado">
          <Check size={16} className="text-[var(--ks-color-status-warning)]" />
        </AnelDeValor>
        <div className="min-w-0">
          <div className="text-sm font-bold text-[var(--ks-color-text-primary)]">Aprovado</div>
          <div className="text-xs text-[var(--ks-color-text-muted)]">sem pedido gerado</div>
        </div>
      </>
    );
  }
  if (chance.estado === "recusado") {
    return (
      <>
        <AnelDeValor fracao={0} tamanho={44} espessura={5} rotulo="Orçamento recusado">
          <span className="text-[12px] font-extrabold text-[var(--ks-color-text-soft)]">—</span>
        </AnelDeValor>
        <div className="text-sm font-bold text-[var(--ks-color-text-primary)]">Recusado</div>
      </>
    );
  }
  if (chance.estado === "sem-conta") {
    return (
      <>
        <AnelDeValor fracao={0} tamanho={44} espessura={5} rotulo="Sem conta de chance">
          <span className="text-[12px] font-extrabold text-[var(--ks-color-text-soft)]">—</span>
        </AnelDeValor>
        <div className="min-w-0 text-xs leading-4 text-[var(--ks-color-text-muted)]">{chance.motivo}</div>
      </>
    );
  }
  const faixa = faixaDaChance(chance.chance);
  /* "amanhã 21%" quando a queda aparece no número; num orçamento parado há
     semanas, a linha diz há quanto tempo ele está aberto. */
  const caiAmanha = porcentoLegivel(chance.amanha) !== porcentoLegivel(chance.chance);
  return (
    <>
      <AnelDeValor fracao={chance.chance} tamanho={44} espessura={5} cor={faixa.cor} rotulo={`Chance de fechar: ${porcentoLegivel(chance.chance)}`}>
        <span className="text-[11.5px] font-extrabold tracking-tight text-[var(--ks-color-text-primary)]">{porcentoLegivel(chance.chance)}</span>
      </AnelDeValor>
      <div className="min-w-0">
        <div className="truncate text-sm font-bold text-[var(--ks-color-text-primary)]">
          <Maiuscula texto={faixa.rotulo.replace("Chance ", "")} />
        </div>
        <div className="truncate text-xs text-[var(--ks-color-text-muted)]">
          {caiAmanha ? (
            `amanhã ${porcentoLegivel(chance.amanha)}`
          ) : (
            <>
              <span className="hidden sm:inline">aberto </span>
              {haQuantoTempo(new Date(agora - chance.horasAberto * 3_600_000).toISOString(), agora)}
            </>
          )}
        </div>
      </div>
    </>
  );
}

export function FaixaDoOrcamento({
  criadoPor,
  criadoEm,
  chance,
  chanceComErro,
  aoAbrirChance,
  linkAtivo,
  linkVenceEm,
  contadorAntigo,
  ultimaAntiga,
  metricas,
  aoAbrirMetricas,
  aoCopiarLink,
  copiado,
  gerandoLink,
  prazoConfigurado,
  enviadoAqui,
  encerrado,
}: {
  criadoPor: string | null;
  criadoEm: string | null;
  /* A chance no geral (null enquanto calcula). */
  chance: ChanceGlobal | null;
  /* A rota da chance falhou: a faixa diz, em vez de ficar calculando para sempre. */
  chanceComErro: boolean;
  aoAbrirChance: () => void;
  linkAtivo: boolean;
  linkVenceEm: string | null;
  contadorAntigo: number;
  ultimaAntiga: string | null;
  metricas: MetricasDoLink | null;
  aoAbrirMetricas: () => void;
  aoCopiarLink: () => void;
  copiado: boolean;
  gerandoLink: boolean;
  /* Dias de validade que a empresa ligou nas configurações de orçamento, ou null sem validade. */
  prazoConfigurado: number | null;
  /* O link acabou de ser copiado ou mandado nesta tela (as métricas ainda vão voltar). */
  enviadoAqui: boolean;
  /* Já virou pedido ou foi recusado: mandar o link deixou de ser o próximo passo. */
  encerrado: boolean;
}) {
  /* O "agora" das contas: o da resposta das métricas; antes dela, o da montagem. */
  const [agoraDaMontagem] = useState(() => Date.now());
  const agora = metricas ? Date.parse(metricas.geradoEm) : agoraDaMontagem;
  const agoraDaChance = chance ? Date.parse(chance.geradoEm) : agoraDaMontagem;
  const venceEm = prazoMaisRecente(linkVenceEm, metricas?.orcamento.linkVenceEm);
  /* O número é o do cliente (sem a própria equipe). Enquanto as métricas não
     chegam, vale o contador de sempre. */
  const aberturas = metricas ? metricas.resumo.aberturas : contadorAntigo;
  const ultima = metricas ? metricas.resumo.ultima : ultimaAntiga;
  const abertoAgora = Boolean(metricas?.resumo.abertoAgora);
  const enviado = enviadoAqui || aberturas > 0 || Boolean(metricas?.envios.length);
  /* Com história (aberturas ou envios), o número e as métricas ficam na
     faixa mesmo com o link desligado ou o pedido já gerado. */
  const temHistorico = aberturas > 0 || Boolean(metricas?.envios.length);
  const link = estadoDoLink({ ativo: linkAtivo, venceEm, agora, enviado, encerrado, prazoConfigurado });
  /* Com o orçamento em aberto, copiar é o que falta fazer antes de enviar (ou
     depois de vencer): o botão fica cheio. */
  const pedeBotaoCheio = !encerrado && (!link.enviado || link.vencido);

  const botaoDeCopiar = (
    <div className="relative shrink-0">
      <AnimatePresence>
        {copiado ? (
          <motion.span
            initial={{ opacity: 0, y: 6 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -6 }}
            transition={{ duration: 0.2 }}
            className="absolute -top-9 right-0 whitespace-nowrap rounded-full bg-[var(--ks-color-text-primary)] px-2.5 py-1 text-[11px] font-semibold text-[var(--ks-color-bg-elevated)] shadow-sm"
            role="status"
          >
            Link copiado
          </motion.span>
        ) : null}
      </AnimatePresence>
      <button
        type="button"
        onClick={aoCopiarLink}
        disabled={gerandoLink}
        aria-label={copiado ? "Link copiado" : link.vencido ? "Gerar o link de novo e copiar" : "Copiar link"}
        className={`ks-button ks-button-sm whitespace-nowrap ${pedeBotaoCheio ? "ks-button-primary" : "ks-button-secondary"}`}
      >
        {gerandoLink ? <Loader2 size={14} className="animate-spin" /> : copiado ? <Check size={14} /> : link.vencido ? <RefreshCw size={14} /> : <Copy size={14} />}
        {copiado ? "Copiado" : link.vencido ? "Gerar de novo" : "Copiar link"}
      </button>
    </div>
  );

  return (
    <section
      data-faixa-do-orcamento
      aria-label="Resumo do orçamento"
      className="no-print mt-6 grid grid-cols-2 overflow-hidden rounded-3xl border border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-elevated)] lg:flex"
    >
      {/* Quem criou */}
      <Parte className="lg:flex-[0.8]">
        <Rotulo>Criado por</Rotulo>
        <div className="mt-2 flex items-center gap-3">
          {/* No celular a coluna é estreita: o nome e a data valem mais que as iniciais. */}
          <span
            aria-hidden
            className="hidden h-9 w-9 shrink-0 items-center justify-center rounded-full text-[12px] font-bold text-white sm:flex"
            style={{ background: "linear-gradient(135deg, var(--ks-brand-500) 0%, var(--ks-brand-700) 100%)" }}
          >
            {iniciais(criadoPor || "Empresa")}
          </span>
          <div className="min-w-0">
            <div className="truncate text-sm font-bold text-[var(--ks-color-text-primary)]">{criadoPor || "—"}</div>
            {criadoEm ? (
              <div className="truncate text-xs text-[var(--ks-color-text-muted)]">
                <span className="hidden sm:inline">em </span>
                {quando(criadoEm, agoraDaMontagem)}
              </div>
            ) : null}
          </div>
        </div>
      </Parte>

      {/* A chance no geral: empresa, cliente, valor e tempo aberto */}
      <Parte className="border-l lg:flex-[0.85]" aoClicar={aoAbrirChance} rotuloDoClique="Ver de onde vem a chance de fechar" seta>
        <Rotulo>Chance de fechar</Rotulo>
        <div className="mt-2 flex items-center gap-3">
          <ResumoDaChance chance={chance} erro={chanceComErro} agora={agoraDaChance} />
        </div>
      </Parte>

      {/* O link: aberturas do cliente, prazo, métricas e cópia */}
      <div className="col-span-2 flex min-w-0 flex-col border-t border-[var(--ks-color-border-subtle)] px-4 py-4 sm:px-5 lg:flex-[2.3] lg:border-l lg:border-t-0">
        <Rotulo>Link do orçamento</Rotulo>
        <div className="mt-2 flex flex-col gap-3 sm:flex-row sm:items-center sm:gap-0">
          {linkAtivo || temHistorico ? (
            <button
              type="button"
              onClick={aoAbrirMetricas}
              aria-label="Ver as métricas do link"
              className="group -mx-2 flex min-w-0 items-center gap-3 rounded-2xl px-2 py-1 text-left transition-colors hover:bg-[var(--ks-color-bg-hover)] focus-visible:bg-[var(--ks-color-bg-hover)] focus-visible:outline-none sm:mr-0 sm:w-[46%] sm:shrink-0 lg:w-auto"
            >
              <span className="text-[26px] font-extrabold leading-none tracking-tight text-[var(--ks-color-text-primary)]">
                {aberturas.toLocaleString("pt-BR")}
              </span>
              <span className="min-w-0 flex-1">
                <span className="block truncate text-xs font-semibold text-[var(--ks-color-text-secondary)]">
                  {aberturas === 1 ? "abertura" : "aberturas"}
                </span>
                {abertoAgora ? (
                  <span className="flex items-center gap-1.5 text-xs">
                    <span className="relative flex h-2 w-2" aria-hidden>
                      <span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-[var(--ks-color-status-success)] opacity-60 motion-reduce:hidden" />
                      <span className="relative inline-flex h-2 w-2 rounded-full bg-[var(--ks-color-status-success)]" />
                    </span>
                    <span className="font-semibold text-[var(--ks-color-status-success)]">Aberto agora</span>
                  </span>
                ) : (
                  <span className="block truncate text-xs text-[var(--ks-color-text-muted)]">
                    {ultima ? `última ${haQuantoTempo(ultima, agora)}` : "ainda não abriu"}
                  </span>
                )}
              </span>
              <span
                aria-hidden
                title="Métricas do link"
                className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full border border-[var(--ks-color-border-strong)] bg-[var(--ks-color-bg-elevated)] text-[var(--ks-brand-600)] transition-colors group-hover:border-[var(--ks-brand-500)] group-hover:bg-[var(--ks-brand-600)] group-hover:text-white"
              >
                <ChartPie size={15} />
              </span>
            </button>
          ) : null}

          <div
            className={`flex min-w-0 flex-1 items-center justify-between gap-3 ${
              linkAtivo || temHistorico ? "border-t border-[var(--ks-color-border-subtle)] pt-3 sm:ml-4 sm:border-l sm:border-t-0 sm:pl-4 sm:pt-0" : ""
            }`}
          >
            <div className="flex min-w-0 flex-1 items-start gap-2">
              <span aria-hidden className="mt-1.5 h-2 w-2 shrink-0 rounded-full" style={{ background: link.ponto }} />
              <div className="min-w-0">
                <div className="truncate text-sm font-bold text-[var(--ks-color-text-primary)]">{link.titulo}</div>
                <div className="truncate text-xs text-[var(--ks-color-text-muted)]" title={link.texto}>
                  {link.texto}
                </div>
              </div>
            </div>
            {botaoDeCopiar}
          </div>
        </div>
      </div>
    </section>
  );
}
