import type { LocationContext, PlantType } from '../../types/plantScan';
import type { PlantReferenceSource } from '../plantReference/types';

export type PlantIdentificationProviderName = 'plant.id' | 'xiaomi-mimo' | 'claude' | 'unknown';

export type PlantScanPhotoRole = 'whole' | 'leaf' | 'flower' | 'fruit' | 'bark' | 'cutting' | 'plant' | 'habitat';

export type PlantScanPhoto = {
  role: PlantScanPhotoRole;
  uri: string;
  width?: number;
  height?: number;
};

export type PlantIdentificationErrorCode =
  | 'NO_IMAGE'
  | 'MISSING_API_KEY'
  | 'NETWORK_FAILURE'
  | 'AUTH_FAILURE'
  | 'NO_CONFIDENT_RESULT'
  | 'PROVIDER_UNAVAILABLE';

export type PlantIdentificationInput = {
  photoUri: string;
  photoUris?: string[];
  photos?: PlantScanPhoto[];
  /** Scan mode — 'plant' (default), 'fungus', or 'seed'. Drives the AI prompt + result shape. */
  mode?: 'plant' | 'fungus' | 'seed';
  /** What the user is scanning in fungus mode: mushroom/bracket/lichen/moss/unsure. */
  fungusKind?: 'mushroom' | 'bracket' | 'lichen' | 'moss' | 'unsure';
  /** What the user is scanning in seed mode: packet/fruit/pod/wild. Shapes the prompt + photo slots. */
  seedKind?: 'packet' | 'fruit' | 'pod' | 'wild';
  /** Forced refinement of the seed path (Phase 1B, 2026-09-07): the user must
   *  pick a refinement chip before a fruit/pod/wild scan can proceed, so the AI
   *  has the context it needs instead of guessing. */
  seedRefinement?: 'store_bought' | 'wild' | 'unsure' | 'tree' | 'shrub' | 'herb_vine' | 'attached' | 'loose';
  /** Free-text plant context for the unknown-wild-seed path (Phase 1B): what
   *  plant the seed was attached to / what the plant looked like. */
  seedPlantContext?: string;
  /** Plant type refinement for the unknown-wild-seed 'attached' path (Phase 1C,
   *  2026-09-07): tree / bush / vine / unsure. A third chip row shown only when
   *  seedKind === 'wild' && seedRefinement === 'attached'. */
  seedPlantType?: 'tree' | 'bush' | 'vine' | 'unsure';
  /** Free-text surrounding-plant context for the unknown-wild-seed path (Phase
   *  1C, 2026-09-07): other plants the user saw growing around the seed. Some
   *  plants grow near companions/indicator species, which helps the AI. */
  seedSurroundingPlants?: string;
  optionalKnownName?: string;
  plantType: PlantType;
  locationContext: LocationContext;
  approximateLocationText?: string;
  /** Saved ZIP/city from app Settings – pre-filled for convenience */
  savedApproximateLocationText?: string;
  /** Real-time GPS data collected when user selects precise mode */
  gpsLocation?: {
    latitude: number;
    longitude: number;
    heading?: number;
    altitude?: number;
  };
  notes?: string;
  /** User's care preferences (organic-first, pet-safe, edible caution) — refine
   *  identification/advice. Optional; not all matter for ID but pet-safe and
   *  edible caution help prioritize safety-relevant info. */
  carePreferences?: {
    organicFirst?: boolean;
    petSafeCaution?: boolean;
    ediblePlantCaution?: boolean;
    shoppingStyle?: 'diy_first' | 'store_bought' | 'either';
  };
};

export type PlantSuggestionTaxonomy = {
  kingdom?: string;
  phylum?: string;
  class?: string;
  order?: string;
  family?: string;
  genus?: string;
  [key: string]: string | undefined;
};

export type PlantIdentificationSuggestion = {
  id?: string;
  name: string;
  commonName?: string;
  scientificName?: string;
  confidence: number;
  commonNames: string[];
  taxonomy?: PlantSuggestionTaxonomy;
  description?: string;
  sourceUrl?: string;
  imageUrl?: string;
};

/**
 * SEED IDENTIFICATION RESULT (Bekky, 2026-09-07, seed-intake feature).
 * The rich, honest seed-saving + germination profile the AI returns for a
 * seed scan (mode='seed'). Grounded in real horticulture — see the design doc
 * section 7 for the verified seed science. All fields optional where sensible
 * so a low-confidence wild-seed scan can still return a partial profile.
 */
export type SeedIdentificationResult = {
  // Identification
  commonName?: string;
  scientificName?: string;
  confidence?: number;
  alternates?: string[];
  /** Seed type — can it be dried & stored? 'orthodox' = yes; 'recalcitrant' =
   *  must plant fresh (dies if dried, e.g. mangosteen); 'unknown' = not sure. */
  seedType?: 'orthodox' | 'recalcitrant' | 'unknown';
  /** Does it produce the same fruit/plant from seed? Many fruit trees do NOT
   *  come true (apples are heterozygous, grafted clones). 'unknown' = not sure. */
  comesTrueFromSeed?: boolean | 'unknown';
  /** Honest explanation of comesTrueFromSeed (e.g. "This apple seed will grow
   *  a wild tree, not the same apple you ate"). */
  comesTrueNote?: string;
  /** Can the seed be saved at all? */
  canSaveSeed?: boolean;
  /** How to clean + save (fermentation vs washing, drying, storage). */
  savingMethod?: string;
  /** How to store (airtight, cool, dry; or "must plant fresh"). */
  storageMethod?: string;
  /** How long the seed stays viable. */
  storageDuration?: string;
  /** Cold treatment (e.g. apple 70-80d @40-41°F). */
  stratification?: { needed: boolean; method: string; duration: string };
  /** Hard-coat treatment (nicking/sandpaper/hot water). */
  scarification?: { needed: boolean; method: string };
  plantingDepth?: string;
  lightRequirement?: 'light' | 'dark' | 'either';
  temperatureRange?: string;
  moisture?: string;
  daysToGerminate?: string;
  /** Expected germination rate (Bekky, 2026-09-08) — what % of seeds typically
   *  sprout (e.g. "60-80%"). Some seeds have low germination rates; the user
   *  should know before planting, and care logic can use it to judge a dud. */
  germinationRate?: string;
  germinationSteps?: string[];
  /** Seed propagation best methods (NOT cutting propagation — this is seed). */
  propagationMethods?: { method: string; difficulty: string; instructions: string[]; timeframe: string }[];
  /** How long to reach maturity. */
  timeToGrow?: string;
  /** How long to bear fruit (e.g. mangosteen 7-20yr). Fruit trees only — NOT
   *  all seeds bear fruit. Optional; use timeToHarvest for non-fruiting plants. */
  timeToFruit?: string;
  /** How long until harvest/maturity — plant-type-agnostic (Phase 1B, 2026-09-07).
   *  For a carrot ~70 days, for an oak decades. Covers flowers/herbs/plants/
   *  bushes/trees/roots/tubers, not just fruit trees. */
  timeToHarvest?: string;
  /** What the seed grows into (honest) — flower / herb / plant / bush / tree /
   *  root / tuber. NOT all seeds bear fruit: a carrot seed → a carrot root, a
   *  potato → a tuber, a sunflower → a flower, a basil seed → an herb. */
  expectedOutcome?: string;
  /** How much yard space required. */
  spaceNeeded?: string;
};

export type PlantIdentificationResult = {
  id: string;
  imageUri: string;
  imageUris?: string[];
  createdAt: string;
  provider: PlantIdentificationProviderName;
  providerRequestId?: string;
  mode: 'plant' | 'fungus' | 'seed';
  topSuggestion?: PlantIdentificationSuggestion;
  suggestions: PlantIdentificationSuggestion[];
  confidence: number;
  scientificName?: string;
  commonNames: string[];
  taxonomy?: PlantSuggestionTaxonomy;
  description?: string;
  sourceUrl?: string;
  referenceUrl?: string;
  referenceTitle?: string;
  referenceSource?: PlantReferenceSource;
  rawResponse?: unknown;
  userProvidedName?: string;
  plantType: PlantType;
  locationContext: LocationContext;
  nearbyCityOrZip?: string;
  notes?: string;
  addedToGarden: boolean;
  addedToWishlist: boolean;
  linkedPlantId?: string;
  /** Pet-safety classification from the AI: 'safe' | 'caution' | 'toxic' | 'unknown'. */
  petSafety?: 'safe' | 'caution' | 'toxic' | 'unknown';
  /** Fungus classification (mode='fungus'): what kind of organism this is. */
  kingdom?: 'mushroom' | 'bracket_fungus' | 'slime_mold' | 'lichen' | 'moss' | 'plant' | 'other';
  /** Fungus edibility — mushrooms only. ALWAYS paired with the edibility disclaimer in UI. */
  edibility?: 'edible' | 'poisonous' | 'unknown';
  /** Can this species be cultivated (grown deliberately), for any purpose (food/ornamental). */
  cultivable?: boolean;
  /** What it grows on when cultivated (oyster → straw, shiitake → hardwood logs, etc). */
  substrate?: string;
  /** Rich seed-saving + germination profile (mode='seed'). Present only for seed scans. */
  seed?: SeedIdentificationResult;
  propagation?: {
    canPropagate: boolean;
    methods: { method: string; difficulty: string; instructions?: string[]; timeframe: string; successRate: string; risks?: string; warning?: string | null }[];
    notRecommended: { method: string; reason: string }[];
    generalNote?: string;
  };
};

export class PlantIdentificationError extends Error {
  code: PlantIdentificationErrorCode;
  status?: number;
  devMessage?: string;

  constructor(code: PlantIdentificationErrorCode, message: string, status?: number, devMessage?: string) {
    super(message);
    Object.setPrototypeOf(this, PlantIdentificationError.prototype);
    this.name = 'PlantIdentificationError';
    this.code = code;
    if (status !== undefined) this.status = status;
    if (devMessage !== undefined) this.devMessage = devMessage;
  }
}
