import type { SeedIdentificationResult } from '../services/plantIdentification/types';
import type { CareSchedule, GroupableCareAction, RegionContext } from './care';
import type { CohortHistoryEntry } from './cohortHistory';
import type { GardenContextPhoto, PlantEvent } from './garden';
import type {
  PlantEnrichmentData,
  PropagationInfo,
  RootingMethod,
} from './propagation';

export type PlantType = 'houseplant' | 'tree' | 'garden' | 'crop' | 'garden_crop' | 'cutting' | 'unsure';

export type PlantCareDifficulty = 'easy' | 'medium' | 'fussy' | 'unsure';

export type TreatmentPreference =
  | 'strictly_organic'
  | 'diy_first'
  | 'store_bought_organic'
  | 'chemical_escalation_opt_in';

/** Legacy booleans and current tri-state values accepted by persisted profiles. */
export type YesNoUnsure = boolean | 'yes' | 'no' | 'unsure';

export type ScanMode = 'plant' | 'fungus' | 'seed';
export type SeedKind = 'packet' | 'fruit' | 'pod' | 'wild';
export type ScanKingdom =
  | 'mushroom'
  | 'bracket_fungus'
  | 'slime_mold'
  | 'lichen'
  | 'moss'
  | 'plant'
  | 'other';
export type ScanEdibility = 'edible' | 'poisonous' | 'unknown';

export type LocationContext =
  | 'indoor'
  | 'outdoor'
  | 'public_park_trail'
  | 'garden_yard'
  | 'public_spaces'
  | 'street_tree'
  | 'nursery_store'
  | 'home'
  | 'unsure';

/** Unit-free proximity scale for placement (Bekky, 2026-08-22). Three levels —
 * no feet/metric, so it reads the same in every country. */
export type PlacementProximityLevel = 'right_next_to' | 'nearby' | 'across_room' | 'unsure';

/** Per-plant distance to the sources of light & air in its space. A key is only
 * present when that source exists in the room (window, or a climate device the
 * room actually has) AND the user answered. */
export type PlacementProximity = Partial<Record<
  'window' | 'airCon' | 'heater' | 'fan' | 'humidifier',
  PlacementProximityLevel
>>;

export type {
  PlantIdentificationInput as PlantScanInput,
  PlantIdentificationResult,
  PlantIdentificationSuggestion,
  PlantSuggestionTaxonomy,
  SeedIdentificationResult,
} from '../services/plantIdentification/types';

export type SavedPlantIdentificationSuggestion = {
  name: string;
  commonName?: string;
  scientificName?: string;
  confidence?: number;
};

export type SavedPlantIdentificationDetails = {
  scanResultId?: string;
  provider?: string;
  providerRequestId?: string;
  identifiedAt?: string;
  imageUri?: string;
  imageUris?: string[];
  commonName?: string;
  scientificName?: string;
  confidence?: number;
  suggestions: SavedPlantIdentificationSuggestion[];
  description?: string;
  sourceUrl?: string;
  referenceUrl?: string;
  referenceTitle?: string;
  referenceSource?: string;
  notes?: string;
};

export type PlantGrowthStage =
  | 'cutting'
  | 'rooted_cutting'
  | 'seedling'
  | 'sapling'
  | 'young_plant'
  | 'mature_plant'
  | 'established_plant'
  | 'unsure';

export type PlantTimeOwned =
  | 'less_than_1_month'
  | 'one_to_six_months'
  | 'six_to_twelve_months'
  | 'one_to_three_years'
  | 'three_plus_years'
  | 'unsure';

export type SavedPlantProfile = {
  id: string;
  photoUri: string;
  image?: string;
  name?: string;
  commonName: string;
  scientificName: string;
  confidence: number;
  alternatives: string[];
  scanResultId?: string;
  scanProvider?: string;
  scanProviderRequestId?: string;
  scanSourceUrl?: string;
  identification?: SavedPlantIdentificationDetails;
  category?: PlantType;
  plantType: PlantType;
  growthStage?: PlantGrowthStage;
  timeOwned?: PlantTimeOwned;
  locationContext: LocationContext;
  approximateLocationText?: string;
  /** Precise GPS captured at scan time (Bekky, 2026-09-08) — where the plant
   *  was scanned / where it came from. Only set when the user's GPS precision
   *  is 'precise'. Drives the "Where I'm from" + Open in Google Maps link. */
  gpsLocation?: { latitude: number; longitude: number };
  spaceId?: string | null;
  assignedSpaceId?: string;
  spaceName?: string;
  space?: string;
  location?: string;
  careDifficulty?: PlantCareDifficulty;
  wateringSchedule?: string;
  lightNeeds?: string;
  plantingMedium?: string[] | string;
  treatmentPreferences?: TreatmentPreference[];
  isEdible?: YesNoUnsure;
  petChildCaution?: YesNoUnsure;
  careGoals?: string[];
  commonIssues?: string[];
  tags?: string[];
  notes?: string;
  manualNotes?: string;
  /** Fungus scan fields (Bekky, 2026-08-25) — set for fungus scans so the plant
   *  detail keeps the kingdom classification + edibility + disclaimer. */
  scanMode?: ScanMode;
  kingdom?: ScanKingdom;
  edibility?: ScanEdibility;
  cultivable?: boolean;
  substrate?: string;
  /** Seed scan fields (Bekky, 2026-09-07, seed-intake feature) — set for seed
   *  scans so the plant detail keeps the rich seed-saving + germination profile
   *  and the seedKind that shaped the intake. */
  seed?: SeedIdentificationResult;
  seedKind?: SeedKind;
  /** Expiry date for a saved seed (Bekky, 2026-09-08): for recalcitrant seeds
   *  that can only be stored a short time, the date by which it must be planted
   *  or it's no longer viable. ISO string. */
  expiresAt?: string;
  setupCompleted?: boolean;
  careSummary: string;
  toxicityWarning: string;
  placementDescription?: string;
  placementPhoto?: string;
  /** Phase: up to 3 placement photos. The first (or legacy placementPhoto) is the cover. */
  placementPhotos?: GardenContextPhoto[];
  /** Where this plant sits relative to the sources of light & air in its space
   * (Bekky, 2026-08-22, placement pass). Per-device proximity to the window +
   * climate devices the room actually has. 'unsure' = the user didn't answer.
   * Unit-free three-level scale (global app — no feet vs metric). */
  placementProximity?: PlacementProximity;
  /** Plants physically near this one in the SAME space (Bekky, 2026-08-27, Chunk 1
   * neighbor tagging). SYMMETRIC — if A lists B, B lists A. Powers outbreak
   * awareness (in-ground plants can't be quarantined) + intelligent watering
   * grouping. Space-scoped: a plant can only neighbor plants in its own space.
   * Optional — never a gate. */
  neighborPlantIds?: string[];
  /** Per-action cohort membership (Bekky, 2026-08-27, Chunk 2): which cohort this
   *  plant belongs to FOR EACH groupable action. A plant can be in a water cohort
   *  and a DIFFERENT fertilize cohort (they're independent). A missing action key
   *  = the plant is standalone for that action (NOT grouped — e.g. a plant with
   *  unique fertilize needs keeps its own per-plant fertilize cadence). */
  cohortIds?: Partial<Record<GroupableCareAction, string>>;
  /** Per-action nuance within a cohort (Bekky, 2026-08-27, Q3): the cohort carries
   *  the shared cadence; this plant carries its own small delta on top. e.g.
   *  "rosemary: less water, keep dry" / "sage A: more perlite → dries faster, a
   *  bit more water". Moves with the plant across cohort reshuffles. */
  cohortAdjustment?: Partial<Record<GroupableCareAction, string>>;
  /** Per-action divergence counter (Bekky, 2026-09-07, cohort-engine Gap 3): how
   *  many CONSECUTIVE group care rounds this plant's own due date landed OUTSIDE
   *  the group's shared window (>1 day tolerance). +1 per consecutive miss;
   *  reset to 0 on rejoin. Diverging = >= 2 (the "nudge twice → deviate" rule).
   *  Weather-deferred rounds do NOT increment (weather is temporary + cohort-wide).
   *  Drives the hasDeviating state: 1 → individual (AI fold-in vs exit); 2+ same
   *  direction → cadence nudge (median drift first, AI on repeat); 2+ mixed or
   *  majority → full regroup. */
  deviationCount?: Partial<Record<GroupableCareAction, number>>;
  /** Per-action exception flag (Bekky, 2026-08-27): a plant needing special care
   *  within its cohort while it recovers (e.g. a sick plant kept in the cohort but
   *  treated differently, NOT pulled out entirely). */
  cohortException?: Partial<Record<GroupableCareAction, boolean>>;
  /**
   * COHORT LIFE-HISTORY LEDGER (Bekky, 2026-08-31, stitches 5–7): the plant's
   * clearly-named SECTION of its group life — ledger-preserving entries
   * (types/cohortHistory.ts CohortHistoryEntry) for every cohort it has
   * belonged to (past + present), with join/leave dates, its own date
   * deviation at join, the AI bridge plan, and WHY it left each group.
   * SUITCASE RULE: rides on the plant — leaving any group takes the history
   * along. The plant-normalizer's spread preserves it through every save/load
   * (gardenStorage.ts normalizeSavedPlantProfile). NOT rewritten by care
   * passes; only membership events touch it. Future clipping (ruling, NOT this
   * build) may deprecate old entries; until then, append-only.
   */
  cohortHistory?: CohortHistoryEntry[];
  /** SHARED CONTAINER (Bekky, 2026-09-04): a UUID shared by every plant in the
   *  same pot/container. Plants with the same id are roommates — they cannot be
   *  watered/fertilized independently (water one, you water both). A shared
   *  container is a FORCED cohort (water + fertilize shared, hard rule). A
   *  `sharedContainerId` can exist with a pending roommate slot (the roommate
   *  isn't in the app yet — "Haven't added yet" / "Not in my garden yet").
   *  Absent = standalone plant. Symmetric: adding B to A's pot gives both the
   *  same id. */
  sharedContainerId?: string;
  /** SHARED-CONTAINER CONFLICT NOTE (Bekky, 2026-09-04): the one-time AI
   *  assessment of how well this plant's species pairs with its roommates'
   *  species in a shared pot. Generated once with the initial enrichment packet,
   *  NEVER refetched on open — EXCEPT when the roommate set changes (add/remove
   *  a roommate), which makes the pairing stale and forces a refetch. Carries
   *  the pairing quality (good/neutral/bad) for the color-coded display box. */
  sharedContainerNote?: {
    quality: 'good' | 'neutral' | 'bad';
    text: string;
    /** The roommate-set this note was computed against (plant ids, sorted) —
     *  used to detect when the pairing changed and the note must refetch. */
    roommateIds: string[];
    generatedAt: string;
  };
  placementSummary?: string;
  /** @deprecated Future-only. Generated watercolor plant artwork is excluded from launch UI. */
  watercolorIconUri?: string;
  /** @deprecated Future-only. Generated watercolor plant artwork is excluded from launch UI. */
  watercolorIconPrompt?: string;
  /** @deprecated Future-only. Generated watercolor plant artwork is excluded from launch UI. */
  watercolorIconCreatedAt?: string;
  /** @deprecated Future-only. Generated watercolor plant artwork is excluded from launch UI. */
  watercolorIconSource?: 'mock_dev' | 'plant_artwork_provider' | 'generated_backend';
  /** @deprecated Future-only. Generated watercolor plant artwork is excluded from launch UI. */
  watercolorIconProvider?: string;
  enrichmentData?: PlantEnrichmentData;
  propagationInfo?: PropagationInfo;
  /** Set when enrichment was STARTED but not yet completed (expert review
   *  2026-09-03, Fix 3). Lets the app recover a plant whose enrichment was
   *  interrupted by a mid-flight close — re-enqueue on next load. Cleared on
   *  completion. This is TARGETED recovery, NOT the blanket startup backfill
   *  Bekky disabled on 2026-08-15 (that was for existing plants that never had
   *  enrichment; this only re-runs a pass that was already in flight). */
  pendingEnrichment?: boolean;
  rootingMedium?: RootingMethod;
  /** Structured AI care schedule (Class 1 scheduled + Class 3 observation). */
  careSchedule?: CareSchedule;
  /** Region → climate context (hardiness zone, climate type). */
  regionContext?: RegionContext;
  /** Parent plant link — the specific plant a cutting was taken from. Persists as the cutting grows into a plant. */
  parentPlantId?: string;
  parentPlantName?: string;
  /** Sections the user has collapsed on this plant's detail page (Bekky, 2026-08-13). Persists across restarts. */
  collapsedSections?: string[];
  /** Care-guidance detail rows the user has collapsed (water/fertilize/inspect)
   *  on this plant's detail page (Bekky, 2026-08-23). Persists across restarts. */
  careGuidanceCollapsed?: string[];
  /** Change-detection fingerprint of the AI context (environment/setup/placement).
   * Set when "Save and refresh Pixie Intelligence" fires; on the next tap, if the
   * fingerprint is unchanged the AI call is SKIPPED (nothing changed). Additive —
   * absent on plants never refreshed. */
  contextFingerprint?: string;
  /** The species key (name|scientificName) that the bio/basics enrichment was
   * generated for. Lets the app detect a SPECIES change (re-identify / rename)
   * and refetch the annual bio snapshot — while NOT refetching on mere context
   * change (weather/setup), which would clobber the static bio. Additive —
   * absent on plants enriched before this field existed. */
  enrichedSpeciesKey?: string;
  /** Change-detection fingerprint of the context PHOTOS (environment + setup +
   * placement). Set when "Save and refresh Pixie Intelligence" fires; if the photo
   * set is unchanged the photo analysis is SKIPPED (only new/changed photos get
   * re-analyzed). Additive — absent on plants never refreshed. */
  contextPhotoFingerprint?: string;
  /** Per-section change-detection fingerprints of the AI context TEXT (the
   * chips/choices the user picked for environment/setup/placement). Lets the UI
   * show "Pixie is learning from your setup" when only that section's choices
   * changed. Additive — absent on plants never refreshed. */
  contextSectionFingerprints?: { environment?: string; setup?: string; placement?: string };
  /** Per-section change-detection fingerprints of the context PHOTOS. Lets the
   * UI show "Pixie is learning from your setup and photos" when both the
   * choices and the photos of a section changed. Additive. */
  contextSectionPhotoFingerprints?: { environment?: string; setup?: string; placement?: string };
  createdAt: string;
  updatedAt?: string;
  source: 'plant_scan' | 'manual_garden' | 'wishlist' | 'field_diary';
  events?: PlantEvent[];
  plantEvents?: PlantEvent[];
};
