// natal-chart.jsx — animated natal chart visualization

const ZODIAC_ORDER = [
  'aries','taurus','gemini','cancer','leo','virgo',
  'libra','scorpio','sagittarius','capricorn','aquarius','pisces'
];

// Sample planet positions (degrees from 0° Aries, counterclockwise)
const DEFAULT_PLACEMENTS = [
  { planet: 'sun',     deg: 98,  house: 4 },
  { planet: 'moon',    deg: 215, house: 8 },
  { planet: 'mercury', deg: 110, house: 4 },
  { planet: 'venus',   deg: 76,  house: 3 },
  { planet: 'mars',    deg: 178, house: 7 },
  { planet: 'jupiter', deg: 305, house: 11 },
  { planet: 'saturn',  deg: 260, house: 10 },
];

// polar to cartesian: chart is centered at cx,cy with radius r
// Astrology charts are drawn with 0° Aries at left (9 o'clock) going counterclockwise.
const polar = (cx, cy, r, deg) => {
  // convert: 0° = left, going CCW
  const rad = ((180 - deg) * Math.PI) / 180;
  return { x: cx + r * Math.cos(rad), y: cy - r * Math.sin(rad) };
};

const NatalChart = ({
  size = 560,
  placements = DEFAULT_PLACEMENTS,
  animated = true,
  showAspects = true,
  showHouses = true,
  variant = 'full', // 'full' | 'minimal' | 'tiny'
  glow = true,
}) => {
  const cx = size / 2;
  const cy = size / 2;
  const rOuter = size * 0.46;
  const rZodiac = size * 0.42;
  const rHouse = size * 0.34;
  const rPlanet = size * 0.30;
  const rInner = size * 0.18;

  // simple aspects between placements: opposition (~180°), trine (~120°), square (~90°)
  const aspects = [];
  if (showAspects) {
    for (let i = 0; i < placements.length; i++) {
      for (let j = i + 1; j < placements.length; j++) {
        let d = Math.abs(placements[i].deg - placements[j].deg);
        if (d > 180) d = 360 - d;
        let type = null;
        if (Math.abs(d - 180) < 6) type = 'opp';
        else if (Math.abs(d - 120) < 6) type = 'trine';
        else if (Math.abs(d - 90) < 5) type = 'square';
        else if (Math.abs(d - 60) < 4) type = 'sextile';
        if (type) aspects.push({ a: placements[i], b: placements[j], type });
      }
    }
  }

  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} style={{ overflow: 'visible' }}>
      <defs>
        <radialGradient id="np-glow" cx="50%" cy="50%" r="50%">
          <stop offset="0%" stopColor="var(--gold)" stopOpacity="0.18" />
          <stop offset="60%" stopColor="var(--gold)" stopOpacity="0.04" />
          <stop offset="100%" stopColor="var(--gold)" stopOpacity="0" />
        </radialGradient>
        <filter id="np-soft" x="-50%" y="-50%" width="200%" height="200%">
          <feGaussianBlur stdDeviation="0.6" />
        </filter>
      </defs>

      {/* Background glow */}
      {glow && <circle cx={cx} cy={cy} r={rOuter * 1.1} fill="url(#np-glow)" />}

      {/* Outer ring + zodiac wheel */}
      <g style={animated ? { transformOrigin: `${cx}px ${cy}px`, animation: 'orbit 240s linear infinite' } : {}}>
        <circle cx={cx} cy={cy} r={rOuter} fill="none" stroke="var(--line)" strokeWidth="1" />
        <circle cx={cx} cy={cy} r={rZodiac} fill="none" stroke="var(--line)" strokeWidth="1" />

        {/* 12 zodiac divisions */}
        {ZODIAC_ORDER.map((_, i) => {
          const deg = i * 30;
          const p1 = polar(cx, cy, rZodiac, deg);
          const p2 = polar(cx, cy, rOuter, deg);
          return <line key={`zd-${i}`} x1={p1.x} y1={p1.y} x2={p2.x} y2={p2.y} stroke="var(--line)" strokeWidth="0.8" />;
        })}

        {/* Zodiac glyphs */}
        {ZODIAC_ORDER.map((z, i) => {
          const center = polar(cx, cy, (rZodiac + rOuter) / 2, i * 30 + 15);
          return (
            <g key={`zg-${i}`} transform={`translate(${center.x - 9}, ${center.y - 9})`}>
              <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="var(--ink-secondary)" strokeWidth="1.1" strokeLinecap="round" strokeLinejoin="round" style={{ overflow: 'visible' }}>
                {Zodiac[z]}
              </svg>
            </g>
          );
        })}
      </g>

      {/* Houses ring */}
      {showHouses && (
        <g>
          <circle cx={cx} cy={cy} r={rHouse} fill="none" stroke="var(--line-soft)" strokeWidth="1" strokeDasharray="2 3" />
          {Array.from({ length: 12 }).map((_, i) => {
            const deg = i * 30 + 12;
            const p1 = polar(cx, cy, rInner, deg);
            const p2 = polar(cx, cy, rHouse, deg);
            return <line key={`h-${i}`} x1={p1.x} y1={p1.y} x2={p2.x} y2={p2.y} stroke="var(--line-soft)" strokeWidth="0.6" />;
          })}
          {/* house numbers */}
          {Array.from({ length: 12 }).map((_, i) => {
            const p = polar(cx, cy, rInner + 14, i * 30 + 12 + 15);
            return (
              <text key={`hn-${i}`} x={p.x} y={p.y} textAnchor="middle" dominantBaseline="middle"
                fontFamily="JetBrains Mono, monospace" fontSize="9" fill="var(--ink-faint)">
                {i + 1}
              </text>
            );
          })}
        </g>
      )}

      {/* Aspect lines */}
      {showAspects && aspects.map((a, i) => {
        const p1 = polar(cx, cy, rPlanet, a.a.deg);
        const p2 = polar(cx, cy, rPlanet, a.b.deg);
        const colors = { opp: 'var(--rose)', square: 'var(--rose)', trine: 'var(--sage)', sextile: 'var(--celest)' };
        const dash = a.type === 'opp' ? '4 3' : a.type === 'square' ? '2 3' : a.type === 'trine' ? '0' : '1 4';
        return (
          <line key={`asp-${i}`} x1={p1.x} y1={p1.y} x2={p2.x} y2={p2.y}
            stroke={colors[a.type]} strokeWidth="0.8" strokeDasharray={dash} opacity="0.55" />
        );
      })}

      {/* Inner circle */}
      <circle cx={cx} cy={cy} r={rInner} fill="none" stroke="var(--line)" strokeWidth="1" />

      {/* Planets — slowly drift */}
      <g style={animated ? { transformOrigin: `${cx}px ${cy}px`, animation: 'orbit 600s linear infinite reverse' } : {}}>
        {placements.map((pl, i) => {
          const p = polar(cx, cy, rPlanet, pl.deg);
          const tick1 = polar(cx, cy, rZodiac - 2, pl.deg);
          const tick2 = polar(cx, cy, rZodiac - 8, pl.deg);
          return (
            <g key={`pl-${i}`}>
              {/* tick on zodiac ring */}
              <line x1={tick1.x} y1={tick1.y} x2={tick2.x} y2={tick2.y} stroke="var(--gold)" strokeWidth="1.2" />
              {/* planet glyph */}
              <g transform={`translate(${p.x - 10}, ${p.y - 10})`}>
                <circle cx="10" cy="10" r="11" fill="var(--bg-raised)" stroke="var(--gold)" strokeWidth="0.8" />
                <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="var(--gold)" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" style={{ overflow: 'visible' }}>
                  <g transform="scale(0.7) translate(5,5)">
                    {Planet[pl.planet]}
                  </g>
                </svg>
              </g>
            </g>
          );
        })}
      </g>

      {/* Center mark */}
      <circle cx={cx} cy={cy} r={2.5} fill="var(--gold)" />

      {/* Scattered tiny twinkling stars */}
      {variant === 'full' && Array.from({ length: 18 }).map((_, i) => {
        const r = rOuter + 10 + (i % 5) * 8;
        const deg = (i * 37) % 360;
        const p = polar(cx, cy, r, deg);
        return (
          <circle key={`st-${i}`} cx={p.x} cy={p.y} r={0.8 + (i % 3) * 0.3}
            fill="var(--ink-primary)"
            style={{ animation: `twinkle ${3 + (i % 4)}s ease-in-out ${i * 0.4}s infinite` }} />
        );
      })}
    </svg>
  );
};

// Minimal version — just orbital rings and a few planets, for backgrounds
const NatalChartBg = ({ size = 800, opacity = 0.5 }) => {
  const cx = size / 2;
  const cy = size / 2;
  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} style={{ opacity }}>
      <g style={{ transformOrigin: `${cx}px ${cy}px`, animation: 'orbit 400s linear infinite' }}>
        {[0.18, 0.24, 0.30, 0.36, 0.42, 0.48].map((m, i) => (
          <circle key={i} cx={cx} cy={cy} r={size * m} fill="none" stroke="var(--line)" strokeWidth="0.6" strokeDasharray={i % 2 ? "1 4" : "0"} opacity={0.7 - i * 0.06} />
        ))}
        {Array.from({ length: 12 }).map((_, i) => {
          const deg = i * 30;
          const p1 = polar(cx, cy, size * 0.18, deg);
          const p2 = polar(cx, cy, size * 0.48, deg);
          return <line key={`l-${i}`} x1={p1.x} y1={p1.y} x2={p2.x} y2={p2.y} stroke="var(--line-soft)" strokeWidth="0.4" />;
        })}
      </g>
      {/* drifting planets */}
      <g style={{ transformOrigin: `${cx}px ${cy}px`, animation: 'orbit 800s linear infinite reverse' }}>
        {[
          { r: 0.42, deg: 45, c: 'var(--gold)' },
          { r: 0.30, deg: 200, c: 'var(--rose)' },
          { r: 0.36, deg: 285, c: 'var(--celest)' },
          { r: 0.24, deg: 120, c: 'var(--sage)' },
        ].map((p, i) => {
          const pt = polar(cx, cy, size * p.r, p.deg);
          return <circle key={i} cx={pt.x} cy={pt.y} r={3} fill={p.c} opacity="0.9" style={{ filter: `drop-shadow(0 0 6px ${p.c})` }}/>;
        })}
      </g>
      {/* twinkling stars */}
      {Array.from({ length: 40 }).map((_, i) => {
        const x = (i * 73) % size;
        const y = (i * 113) % size;
        return <circle key={`s-${i}`} cx={x} cy={y} r={0.6 + (i % 3) * 0.3} fill="var(--ink-primary)"
          style={{ animation: `twinkle ${2 + (i % 5)}s ease-in-out ${i * 0.2}s infinite` }} />;
      })}
    </svg>
  );
};

Object.assign(window, { NatalChart, NatalChartBg, polar, ZODIAC_ORDER });
