"use client";

import type { ReactNode } from "react";
import { motion, useReducedMotion } from "framer-motion";

/*
  Os gráficos redondos da janela de métricas do link.

  Desenhados à mão em SVG (sem biblioteca), no mesmo traço do anel da página
  de Assinatura: trilho claro, arco na cor, ponta redonda, e o número no meio.
  Regras que valem para todos:
  - o texto nunca veste a cor da série: número e rótulo usam as cores de texto;
  - fatias da rosca são separadas por um vão de 2px da cor do fundo, não por
    borda desenhada;
  - toda marca tem um <title> (aparece ao passar o mouse) e o gráfico inteiro
    tem um rótulo para leitor de tela; a lista ao lado repete os números.
*/

const TRILHO = "var(--ks-color-bg-soft)";

/** Anel de valor (medidor): enche até a fração. */
export function AnelDeValor({
  fracao,
  tamanho = 120,
  espessura = 10,
  cor = "var(--ks-brand-600)",
  rotulo,
  atraso = 0.05,
  children,
}: {
  fracao: number;
  tamanho?: number;
  espessura?: number;
  cor?: string;
  rotulo: string;
  atraso?: number;
  children?: ReactNode;
}) {
  const parado = useReducedMotion();
  const raio = (tamanho - espessura) / 2;
  const circunferencia = 2 * Math.PI * raio;
  const cheio = Math.min(1, Math.max(0, Number.isFinite(fracao) ? fracao : 0));
  const alvo = circunferencia * (1 - cheio);
  return (
    <div className="relative shrink-0" style={{ width: tamanho, height: tamanho }} role="img" aria-label={rotulo}>
      <svg width={tamanho} height={tamanho} viewBox={`0 0 ${tamanho} ${tamanho}`} className="-rotate-90" aria-hidden>
        <circle cx={tamanho / 2} cy={tamanho / 2} r={raio} fill="none" stroke={TRILHO} strokeWidth={espessura} />
        {cheio > 0 ? (
          <motion.circle
            cx={tamanho / 2}
            cy={tamanho / 2}
            r={raio}
            fill="none"
            stroke={cor}
            strokeWidth={espessura}
            strokeLinecap="round"
            strokeDasharray={circunferencia}
            initial={parado ? { strokeDashoffset: alvo } : { strokeDashoffset: circunferencia }}
            animate={{ strokeDashoffset: alvo }}
            transition={{ duration: 1, ease: [0.22, 1, 0.36, 1], delay: atraso }}
          />
        ) : null}
      </svg>
      <div className="absolute inset-0 flex flex-col items-center justify-center text-center leading-none">{children}</div>
    </div>
  );
}

export type Fatia = { id: string; rotulo: string; valor: number; cor: string };

/** Rosca: parte do todo, até 5 fatias, com vão entre elas. */
export function Rosca({
  fatias,
  tamanho = 132,
  espessura = 16,
  rotulo,
  children,
}: {
  fatias: Fatia[];
  tamanho?: number;
  espessura?: number;
  rotulo: string;
  children?: ReactNode;
}) {
  const parado = useReducedMotion();
  const total = fatias.reduce((soma, fatia) => soma + Math.max(0, fatia.valor), 0);
  const raio = (tamanho - espessura) / 2;
  const circunferencia = 2 * Math.PI * raio;
  const validas = fatias.filter((fatia) => fatia.valor > 0);
  /* Uma fatia só é o anel inteiro, sem vão. */
  const vao = validas.length > 1 ? 2 : 0;
  let andado = 0;
  return (
    <div className="relative shrink-0" style={{ width: tamanho, height: tamanho }} role="img" aria-label={rotulo}>
      <svg width={tamanho} height={tamanho} viewBox={`0 0 ${tamanho} ${tamanho}`} className="-rotate-90">
        <circle cx={tamanho / 2} cy={tamanho / 2} r={raio} fill="none" stroke={TRILHO} strokeWidth={espessura} />
        {total > 0
          ? validas.map((fatia, indice) => {
              const comprimento = (fatia.valor / total) * circunferencia;
              const desenhado = Math.max(0.5, comprimento - vao);
              const inicio = andado;
              andado += comprimento;
              const porcento = Math.round((fatia.valor / total) * 100);
              return (
                <motion.circle
                  key={fatia.id}
                  cx={tamanho / 2}
                  cy={tamanho / 2}
                  r={raio}
                  fill="none"
                  stroke={fatia.cor}
                  strokeWidth={espessura}
                  strokeDasharray={`${desenhado} ${circunferencia - desenhado}`}
                  strokeDashoffset={-inicio}
                  initial={parado ? false : { opacity: 0 }}
                  animate={{ opacity: 1 }}
                  transition={{ duration: 0.35, delay: 0.08 * indice }}
                >
                  <title>{`${fatia.rotulo}: ${fatia.valor} (${porcento}%)`}</title>
                </motion.circle>
              );
            })
          : null}
      </svg>
      <div className="pointer-events-none absolute inset-0 flex flex-col items-center justify-center text-center leading-none">{children}</div>
    </div>
  );
}

/** Anel pequeno: até onde a pessoa rolou a folha naquela visita. */
export function MiniAnel({ fracao, tamanho = 34, rotulo }: { fracao: number; tamanho?: number; rotulo: string }) {
  const espessura = 3.5;
  const raio = (tamanho - espessura) / 2;
  const circunferencia = 2 * Math.PI * raio;
  const cheio = Math.min(1, Math.max(0, fracao));
  return (
    <div className="relative shrink-0" style={{ width: tamanho, height: tamanho }} role="img" aria-label={rotulo} title={rotulo}>
      <svg width={tamanho} height={tamanho} viewBox={`0 0 ${tamanho} ${tamanho}`} className="-rotate-90" aria-hidden>
        <circle cx={tamanho / 2} cy={tamanho / 2} r={raio} fill="none" stroke={TRILHO} strokeWidth={espessura} />
        {cheio > 0 ? (
          <circle
            cx={tamanho / 2}
            cy={tamanho / 2}
            r={raio}
            fill="none"
            stroke="var(--ks-grafico-1)"
            strokeWidth={espessura}
            strokeLinecap="round"
            strokeDasharray={`${circunferencia * cheio} ${circunferencia}`}
          />
        ) : null}
      </svg>
      <span className="absolute inset-0 flex items-center justify-center text-[8.5px] font-bold tracking-tight text-[var(--ks-color-text-secondary)]">
        {Math.round(cheio * 100)}%
      </span>
    </div>
  );
}

/**
 * Relógio de 24 horas: uma barra por hora, saindo do círculo de base para
 * fora, com o comprimento pelas aberturas. A faixa preferida fica na cor da
 * marca; o resto, mais apagado (ênfase, não arco-íris).
 */
export function RelogioDeHoras({
  horas,
  faixa,
  tamanho = 176,
  children,
}: {
  horas: number[];
  faixa: { inicio: number; fim: number } | null;
  tamanho?: number;
  children?: ReactNode;
}) {
  const parado = useReducedMotion();
  const centro = tamanho / 2;
  /* De fora para dentro: os rótulos das horas a 9px da borda (o "18h" cabe
     inteiro), as barras terminando 11px antes deles, e o círculo de base. O
     meio fica livre para o número. */
  const raioDosRotulos = centro - 9;
  const alcance = tamanho * 0.16;
  const base = raioDosRotulos - 11 - alcance;
  const maximo = Math.max(1, ...horas);
  const total = horas.reduce((soma, valor) => soma + valor, 0);
  const naFaixa = (hora: number) => {
    if (!faixa) return true;
    const { inicio, fim } = faixa;
    return inicio < fim ? hora >= inicio && hora < fim : hora >= inicio || hora < fim;
  };
  const ponto = (hora: number, raio: number) => {
    const angulo = (hora / 24) * 2 * Math.PI - Math.PI / 2;
    return { x: centro + raio * Math.cos(angulo), y: centro + raio * Math.sin(angulo) };
  };
  const espessura = Math.max(4, ((2 * Math.PI * base) / 24) * 0.55);
  const rotulo = total
    ? `Aberturas por hora do dia: ${horas
        .map((valor, hora) => (valor ? `${hora}h, ${valor}` : ""))
        .filter(Boolean)
        .join("; ")}`
    : "Nenhuma abertura registrada por hora ainda";

  return (
    <div className="relative shrink-0" style={{ width: tamanho, height: tamanho }} role="img" aria-label={rotulo}>
      <svg width={tamanho} height={tamanho} viewBox={`0 0 ${tamanho} ${tamanho}`}>
        <circle cx={centro} cy={centro} r={base} fill="none" stroke="var(--ks-color-border-subtle)" strokeWidth={1} />
        {horas.map((valor, hora) => {
          const dentro = ponto(hora, base + 2);
          if (!valor) {
            return <circle key={hora} cx={dentro.x} cy={dentro.y} r={1.3} fill="var(--ks-color-border-strong)" />;
          }
          const fora = ponto(hora, base + 2 + Math.max(espessura / 2, (valor / maximo) * alcance));
          return (
            <g key={hora}>
              <motion.line
                x1={dentro.x}
                y1={dentro.y}
                x2={fora.x}
                y2={fora.y}
                stroke={naFaixa(hora) ? "var(--ks-grafico-1)" : "var(--ks-brand-300)"}
                strokeWidth={espessura}
                strokeLinecap="round"
                initial={parado ? false : { pathLength: 0 }}
                animate={{ pathLength: 1 }}
                transition={{ duration: 0.5, delay: 0.02 * hora }}
              />
              {/* Alvo maior que a barra para o mouse achar. */}
              <line x1={dentro.x} y1={dentro.y} x2={fora.x} y2={fora.y} stroke="transparent" strokeWidth={espessura + 10} strokeLinecap="round">
                <title>{`${hora}h: ${valor} ${valor === 1 ? "abertura" : "aberturas"}`}</title>
              </line>
            </g>
          );
        })}
        {[0, 6, 12, 18].map((hora) => {
          const lugar = ponto(hora, raioDosRotulos);
          return (
            <text
              key={hora}
              x={lugar.x}
              y={lugar.y}
              textAnchor="middle"
              dominantBaseline="central"
              className="fill-[var(--ks-color-text-soft)] text-[10px] font-semibold"
            >
              {hora}h
            </text>
          );
        })}
      </svg>
      <div className="pointer-events-none absolute inset-0 flex flex-col items-center justify-center text-center leading-none">{children}</div>
    </div>
  );
}

/* A cor de cada tipo de aparelho: fixa, a mesma em todas as abas. */
export const COR_DO_TIPO: Record<"celular" | "computador" | "tablet", string> = {
  celular: "var(--ks-grafico-1)",
  computador: "var(--ks-grafico-2)",
  tablet: "var(--ks-grafico-3)",
};

/* A cor de cada aparelho segue a ordem em que ele apareceu (não a posição no
   ranking), para não trocar de cor quando outro passar na frente. */
export const CORES_DE_SERIE = ["var(--ks-grafico-1)", "var(--ks-grafico-2)", "var(--ks-grafico-3)", "var(--ks-grafico-4)"];
export const COR_DOS_OUTROS = "var(--ks-grafico-outros)";
