/**
 * Care intelligence types — the structured care schedule + region context
 * that drive the intelligent multi-modal care engine.
 *
 * These are ADDITIVE: optional fields on SavedPlantProfile. Plants without
 * them fall back to the existing regex text-parsing path until re-enriched.
 */
import type { CohortHistoryEntry } from './cohortHistory';

/** Care actions that support intelligent grouping into cohorts. Water and
 *  fertilize are shared sweeping actions; observation actions stay per-plant. */
export type GroupableCareAction = 'water' | 'fertilize';

/** All care actions that recur on a fixed cadence. */
export type ScheduledCareActionName = GroupableCareAction | 'inspect';

/** A care action that recurs on a fixed cadence (Class 1 — Scheduled). */
export type ScheduledCareAction = {
  action: ScheduledCareActionName;
  everyDays: number;
};

/** A care action that is only known when you SEE the plant (Class 3 — Observation). */
export type ObservationCareAction = 'prune' | 'harvest' | 'mist' | 'rotate';

/**
 * Rich, lifelong guidance for a single care action. Fetched ONCE at enrichment
 * (not re-fetched) — the AI writes practical, species-specific advice.
 */
export type CareActionGuidance = {
  /** How much / how often in practical terms (e.g. "Water until it runs out the drainage holes, then let the top 2-3cm dry before watering again"). */
  howMuch?: string;
  /** Best ways to do it (e.g. "Water from the top slowly, or bottom-water for 20 minutes"). */
  bestWays?: string;
  /** Things to avoid (e.g. "Don't let it sit in standing water; avoid wetting the leaves"). */
  avoid?: string;
};

/** Fertilizer-specific guidance (extends the shared action guidance). */
export type FertilizeGuidance = CareActionGuidance & {
  /** What kind of fertilizer to use / what to look for on the label (e.g. "Balanced 10-10-10, or a bloom formula higher in phosphorus"). */
  fertilizerType?: string;
  /** Whether/how to change fertilizer by season (e.g. "Feed monthly in spring/summer, pause in winter when growth slows"). */
  seasonal?: string;
  /** 1-3 popular local products (region-aware, organic-matched). EMPTY if the AI can't confidently name real ones — never invent brands. */
  localProducts?: Array<{ name: string; type: string; organic: boolean; note?: string }>;
  /** 3-5 search keywords the user can type into a shop/online store to find a suitable fertilizer. Always present. */
  searchKeywords?: string;
};

/** Inspect-specific guidance (extends the shared action guidance). */
export type InspectGuidance = CareActionGuidance & {
  /** What to look for when inspecting (e.g. "Check under leaves for pests, and the soil surface for mold"). */
  whatToLookFor?: string;
  /** Structured list of pest/disease names the gardener should watch for, each
   *  rendered as a tappable link to Google Image Search (Bekky, 2026-08-23).
   *  Empty/absent = the prose `whatToLookFor` is all we have. */
  pests?: string[];
};

/** A single recorded care event (watering/fertilizing) — the raw data the
 * feedback loop learns from (Bekky, 2026-08-21). */
export type CareLogEntry = {
  /** 'water' | 'fertilize' */
  action: GroupableCareAction;
  /** When the notification/task first triggered (local YYYY-MM-DD). */
  triggerDate: string;
  /** When the user actually completed the action (local YYYY-MM-DD). */
  completedDate: string;
  /** Days between trigger and completion — the real cadence signal. */
  actualIntervalDays: number;
  /** The slider value the user picked at completion (moisture or growth). */
  stateAtComplete: string;
  /** How the task was closed: 'complete' | 'postpone' | 'early' | 'manual'. */
  path: 'complete' | 'postpone' | 'early' | 'manual';
};

/**
 * The AI-generated care schedule for a plant, produced given its real context
 * (environment, setup, placement, region, weather, indoor/outdoor, sun exposure).
 */
export type CareSchedule = {
  /** Class 1 — recurring cadence actions. */
  scheduled: ScheduledCareAction[];
  /** Class 3 — observation actions surfaced on photo/memory update. */
  observation: ObservationCareAction[];
  /** Does this plant need weather-triggered warnings (Class 2)? */
  weatherSensitive: boolean;
  /** Young/outdoor plants → frost warning. */
  frostTender?: boolean;
  notes?: string;
  generatedAt: string;
  /**
   * Rich, lifelong per-action guidance. ADDITIVE — plants enriched before this
   * field existed have no `guidance` and fall back to the thin cadence-only view.
   */
  guidance?: {
    water?: CareActionGuidance;
    fertilize?: FertilizeGuidance;
    inspect?: InspectGuidance;
  };
  /**
   * Per-plant cadence overrides set by the user (e.g. "water every 14 days"
   * instead of Pixie's 7). Keyed by action. When set, the care-task builder
   * uses the override instead of the AI's everyDays. Clear to revert to default.
   * NOTE (Bekky, 2026-08-21): the manual override is being REMOVED — it clashes
   * with the intelligence. The user's behavior (via the careLog + slider) becomes
   * the override, expressed as data the AI learns from. Kept here only for
   * backward-compat migration; new writes stop setting it.
   */
  overrides?: Partial<Record<ScheduledCareActionName, number>>;
  /**
   * When the user last did each care action (local YYYY-MM-DD). Set via the
   * cadence wheel's "last done" pill selector — e.g. "I've had this plant a
   * while and just fertilized it last Tuesday." When set, the care-task builder
   * anchors the NEXT due date off this (lastDone + everyDays) instead of
   * today + everyDays. Additive/optional — absent = behave exactly as today.
   */
  lastDone?: Partial<Record<ScheduledCareActionName, string>>;
  /**
   * CARE LOG (Bekky, 2026-08-21): the accumulated history of water/fertilize
   * events. The feedback loop reads this to lengthen/shorten the cadence and
   * the background AI refresh uses it to recompute the baseline. Additive —
   * absent on plants never checked in.
   */
  careLog?: CareLogEntry[];
  /**
   * FEEDBACK ADJUSTMENT (Bekky, 2026-08-21, Phase 2): a signed day-delta the
   * feedback loop applies to the AI baseline cadence for each action. Positive
   * = lengthen (plant needs longer between waterings), negative = shorten
   * (plant dries faster). Computed from the careLog + slider state. The
   * schedule builder applies this on top of the AI's everyDays. This REPLACES
   * the manual `overrides` (which clashed with the intelligence).
   */
  feedbackAdjustment?: Partial<Record<GroupableCareAction, number>>;
  /**
   * CARE CHECK-IN readiness kit (Bekky, 2026-08-20). Generated alongside the
   * care guidance (same call) and refreshed on "Save and refresh Pixie
   * Intelligence". Two parts:
   *   - guidance: the ONLY per-plant part — a real, species+context-specific
   *     "how do I tell if THIS plant is ready?" sentence for water + fertilize.
   *   - chips: STATIC pre-generated postpone reasons split into 3 location
   *     buckets (pot-inside / pot-outside / in-ground), ~3 each for water +
   *     fertilize. Assigned by where the plant lives; reused for every plant in
   *     that bucket; the user's custom write-in covers anything else. These are
   *     NOT regenerated per tap — stable, cached with the plant.
   */
  readiness?: {
    /** Per-plant "how do I tell if it's ready" guidance. */
    guidance?: {
      water?: string;
      fertilize?: string;
    };
    /** Static postpone chips per location bucket (reused across plants). */
    chips?: {
      /** Bucket for plants in a pot, indoors. */
      potInside?: { water?: string[]; fertilize?: string[] };
      /** Bucket for plants in a pot, outdoors. */
      potOutside?: { water?: string[]; fertilize?: string[] };
      /** Bucket for plants in the ground (assumed outdoor). */
      inGround?: { water?: string[]; fertilize?: string[] };
    };
  };
};

/**
 * INTELLIGENT GROUPING COHORT (Bekky, 2026-08-27, Chunk 2): a named group of
 * plants in ONE space that share a cadence so the user can water/fertilize a
 * whole section in one sweeping action. Cohorts are PER-ACTION and PER-SPACE —
 * a water cohort is independent of a fertilize cohort, and cohorts live on the
 * space, not the garden. The AI derives them from the space's gathered
 * per-plant care packages. The cohort carries the shared cadence; each plant
 * keeps its own small adjustment on top (`cohortAdjustment` on SavedPlantProfile).
 */
export type Cohort = {
  id: string;
  /** Human-readable AI name, e.g. "Herbs — dry side" / "Balcony — full sun". */
  name: string;
  /** Plant ids in this cohort. */
  plantIds: string[];
  /** Shared base cadence (days) for the groupable action(s) this cohort serves. */
  sharedCadence?: Partial<Record<GroupableCareAction, number>>;
  /**
   * GROUP ANCHOR (Bekky, 2026-08-30, Chunk B core §B1): the group's own
   * last-watered/last-fed date as a FIRST-CLASS FACT (local YYYY-MM-DD).
   * Written by every group watering (group pencil, Complete-all, sweep) via
   * writeGroupAnchor. This is what makes "when was this group last watered"
   * answerable without reading member plants, and what cooldown/fold-back
   * arithmetic derives from. Absent = group never jointly watered yet.
   */
  lastAnchor?: Partial<Record<GroupableCareAction, string>>;
  /** Cohort-level feedback adjustment (Bekky, 2026-08-27, Chunk 2): a signed
   *  day-delta per action from the cohort-wide wet/dry feedback ("everyone in
   *  the cohort needed water but got too much → next time they'll need less").
   *  Applied on top of sharedCadence, alongside each plant's own adjustment. */
  feedbackAdjustment?: Partial<Record<GroupableCareAction, number>>;
  /** Optional AI note, e.g. "water these together; keep the rosemary drier". */
  note?: string;
  /**
   * AI RE-LOOK DEDUPE — PER-ACTION STAMPS (Bekky, 2026-08-31, stitch 1 "split
   * the judgment stamp per chore"): water and fertilize each get their OWN
   * content-hash "already judged" note, computed from that action's facts. The
   * old single stamp was written with one action's inputs but the staleness
   * gate re-checked BOTH — a water group's fertilize check could never match,
   * so every look re-grouped forever. Absent stamp for an action (legacy or
   * first pass) = that action is judged on its next look, then settles.
   */
  lastCareHashes?: Partial<Record<GroupableCareAction, string>>;
  /**
   * COHORT LIFE-HISTORY LEDGER (Bekky, 2026-08-31, stitch 6): ledger-preserving
   * memory of THIS cohort's membership events — plants joining with their
   * date-deviation and bridge plan, plants leaving with the AI's reason.
   * Rides on the cohort; each PLANT carries the mirror copy (see
   * SavedPlantProfile.cohortHistory). Sections, not scribbles (ruling 7). */
  history?: CohortHistoryEntry[];
  createdAt: string;
  updatedAt: string;
};

/** Region → climate context derived from lat/lon or ZIP/city. */
export type RegionContext = {
  /** USDA-style hardiness zone, e.g. "9b". */
  hardinessZone?: string;
  /** Broad climate type, e.g. "temperate", "tropical", "arid". */
  climateType?: string;
  /** Human-readable region label, e.g. "Ho Chi Minh City". */
  regionLabel?: string;
  /** Latitude/longitude used (rounded per privacy). */
  latitude?: number;
  longitude?: number;
  derivedAt: string;
};

/** Current + short forecast weather snapshot (from Open-Meteo). */
export type WeatherSnapshot = {
  temperatureC: number;
  feelsLikeC?: number;
  humidityPct?: number;
  windSpeedKmh?: number;
  weatherCode: number;
  isDay?: boolean;
  /** Daily forecast for the next N days (for weather-triggered warnings). */
  daily: Array<{
    date: string;
    tempMaxC: number;
    tempMinC: number;
    precipitationMm: number;
    weatherCode: number;
    /** Relative humidity % (0-100) — feeds drying-pressure reasoning. */
    humidityPct?: number;
    /** Max wind speed km/h — feeds drying-pressure + storm/wind signals. */
    windSpeedKmh?: number;
    /** Cloud cover % (0-100) — cloudy days don't dry soil. */
    cloudCoverPct?: number;
  }>;
  /** Monthly rain normal (mm) for the CURRENT month, from 30-yr climate
   *  normals. Lets the cadence read the forecast as a DELTA from the seasonal
   *  normal (Bekky, 2026-09-01): "raining way more than normal this week →
   *  soil saturated → stretch a lot." Optional — absent when the climate
   *  fetch failed (cadence falls back to absolute rain, not delta). */
  monthlyRainNormalMm?: number;
  /** ACTUAL rain history for the past N days (Bekky, 2026-09-01): the forecast
   *  only looks forward, so it can't know the soil is already soaked from
   *  three days of rain. This is the observed precipitation for recent past
   *  days (from Open-Meteo's archive API), so the cadence can reason about
   *  CUMULATIVE + COMPOUNDING wetness — mm/day, how many days in a row it
   *  rained, and how many dry days in between. Optional — absent when the
   *  archive fetch failed (cadence reasons from forecast alone). */
  rainHistory?: Array<{
    date: string;
    precipitationMm: number;
  }>;
  fetchedAt: string;
};

/** The assembled context packet fed to the AI for care decisions. */
export type CareContextPacket = {
  plantName: string;
  scientificName?: string;
  indoorOutdoor?: string;
  environment?: string;
  setup?: string;
  placement?: string;
  region?: string;
  weather?: string;
  sunExposure?: string;
  growthStage?: string;
  careDifficulty?: string;
  /** Time owned — how long the user has had the plant (Bekky, 2026-08-27, Chunk 2).
   *  Feeds root inference: a young/just-acquired plant has a less-developed root
   *  system than one owned for years. */
  timeOwned?: string;
  /** Time since the last repot/transplant, humanized (Bekky, 2026-08-27, Chunk 2).
   *  Fresh soil holds water differently than a root-bound pot → the cadence must
   *  change after a repot. Derived from the most recent 'repotting' plant event. */
  timeSinceRepot?: string;
  /** "As above, so below" plant-size ratio (Bekky, 2026-08-27, Chunk 2). Whether
   *  the plant is small/young, mid, or large relative to its species. The AI
   *  infers this from photos when available; otherwise omitted (the model works
   *  with what it knows). Canopy size correlates with root-system extent. */
  plantSizeRatio?: string;
  /** The species' known root-type character (Bekky, 2026-08-27, Chunk 2). The AI
   *  infers this from the species: taproot vs fibrous network vs voracious vs
   *  minimal-thick. Feeds both cohort grouping and per-plant cadence. */
  rootType?: string;
  /** GARDENER CONTEXT SHELVES (Bekky, 2026-08-30 "wire the straws"): the
   *  user's own words + care signals. All optional — render only when set. */
  notes?: string;
  spaceNotes?: string;
  careWords?: string;
  lightNeeds?: string;
  treatmentPreferences?: string;
  safetyNote?: string;
  /** NEWEST 2-3 diary events (pests, yellow leaves, growth…) — terse captions. */
  diary?: string;
  /** ONE-sentence local compression of the 7-day rain/heat outlook. */
  weekAhead?: string;
  /** SEED PROFILE (Bekky, 2026-09-08): for a plant grown from seed, the rich
   *  seed identification data (germination timeline, days to germinate, seed
   *  type, planting depth, light requirement, expected outcome). Lets the AI
   *  care call guide care from day one for THIS seed's particular needs +
   *  timeline. */
  seed?: string;
};
