#ifndef DECK_ASTRO_H
#define DECK_ASTRO_H

#include <time.h>

#define NUM_BODIES 10
#define MAX_ASPECTS 100

/* Named distinctly from Astronomy Engine's own astro_body_t constants
 * (BODY_SUN, BODY_MOON, ...) to avoid colliding with them in astro.c,
 * which includes both headers. */
typedef enum {
  PLANET_SUN = 0,
  PLANET_MOON,
  PLANET_MERCURY,
  PLANET_VENUS,
  PLANET_MARS,
  PLANET_JUPITER,
  PLANET_SATURN,
  PLANET_URANUS,
  PLANET_NEPTUNE,
  PLANET_PLUTO
} Body;

typedef enum {
  SIGN_ARIES = 0,
  SIGN_TAURUS,
  SIGN_GEMINI,
  SIGN_CANCER,
  SIGN_LEO,
  SIGN_VIRGO,
  SIGN_LIBRA,
  SIGN_SCORPIO,
  SIGN_SAGITTARIUS,
  SIGN_CAPRICORN,
  SIGN_AQUARIUS,
  SIGN_PISCES
} ZodiacSign;

typedef enum {
  MOON_NEW = 0,
  MOON_WAXING_CRESCENT,
  MOON_FIRST_QUARTER,
  MOON_WAXING_GIBBOUS,
  MOON_FULL,
  MOON_WANING_GIBBOUS,
  MOON_LAST_QUARTER,
  MOON_WANING_CRESCENT
} MoonPhaseName;

typedef enum {
  ASPECT_CONJUNCTION = 0,
  ASPECT_SEXTILE,
  ASPECT_SQUARE,
  ASPECT_TRINE,
  ASPECT_OPPOSITION
} AspectType;

typedef struct {
  double ecliptic_longitude; /* geocentric, degrees, [0, 360) */
  ZodiacSign sign;
  double degree_in_sign; /* [0, 30) */
  int house; /* 1-12, whole-sign, always relative to the natal Ascendant -
              * for DailyTransits.bodies this places today's transiting
              * planets in the natal chart's own houses (the standard,
              * personalized way to read transits), not a fresh "houses
              * for right now" chart. */
} PlanetPosition;

typedef struct {
  int year, month, day;   /* birth date, local calendar */
  int hour, minute;       /* birth time, local clock */
  double utc_offset_hours; /* local time = UTC + utc_offset_hours */
  double latitude;         /* degrees north positive */
  double longitude;        /* degrees east positive */
} BirthData;

typedef struct {
  PlanetPosition bodies[NUM_BODIES];
  double ascendant_longitude;
  ZodiacSign houses[12]; /* houses[0] = sign of house 1 (whole-sign system) */
} NatalChart;

typedef struct {
  Body transiting_planet;
  Body natal_planet;
  AspectType type;
  double orb; /* how many degrees off exact, always >= 0 */
} Aspect;

typedef struct {
  PlanetPosition bodies[NUM_BODIES];
  MoonPhaseName moon_phase;
  Aspect aspects[MAX_ASPECTS];
  int aspect_count;
} DailyTransits;

void astro_compute_natal_chart(const BirthData *birth, NatalChart *out);
void astro_compute_daily_transits(time_t utc_moment, const NatalChart *natal,
                                   DailyTransits *out);

const char *astro_body_name(Body body);
const char *astro_sign_name(ZodiacSign sign);
const char *astro_moon_phase_name(MoonPhaseName phase);
const char *astro_aspect_name(AspectType type);

/* Stable, language-independent identifiers (e.g. "sun", "waxing_crescent",
 * "square") - the same strings i18n.c's lookup keys are built from. Used
 * for machine-readable output (reading_print_json) that must stay
 * identical regardless of --lang, unlike astro_*_name() above. */
const char *astro_body_slug(Body body);
const char *astro_sign_slug(ZodiacSign sign);
const char *astro_moon_phase_slug(MoonPhaseName phase);
const char *astro_aspect_slug(AspectType type);

#endif
