import type { PlantEvent, PlantSetupProfile, RoomProfile } from '../../types/garden';
import type {
  PlantKnowledgeCategory,
  PlantKnowledgeItem,
  PlantKnowledgeSummary,
  PlantIntelligenceSummary,
  SamplePlant,
} from '../../types/appTypes';
import type { SavedPlantProfile } from '../../types/plantScan';
import {
  isSpaceEnvironmentComplete,
  maxContextPhotos,
  normalizeContextPhotos,
} from '../contextPhotoHelpers';
import { isOutdoorSpaceType } from '../formatters/spaceFormatters';
import { firstValidDateString } from './dateParsing';
import { getSavedPlantEvents } from './plantMemoryHelpers';

function nonBlankString(value: unknown): string | undefined {
  if (typeof value !== 'string') return undefined;
  const clean = value.trim();
  return clean || undefined;
}

function finiteNumber(value: unknown): number | undefined {
  return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
}

function positiveFiniteNumber(value: unknown): number | undefined {
  const number = finiteNumber(value);
  return number != null && number > 0 ? number : undefined;
}

function meaningfulValues(values: unknown[]): string[] {
  const seen = new Set<string>();
  const result: string[] = [];
  for (const value of values) {
    const clean = nonBlankString(value);
    if (!clean || clean === 'unsure' || seen.has(clean)) continue;
    seen.add(clean);
    result.push(clean);
  }
  return result;
}

function arrayValues(value: unknown): unknown[] {
  return Array.isArray(value) ? value : [];
}

function hasMeaningfulIdentificationObject(value: unknown): boolean {
  if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
  const ignoredKeys = new Set(['provider', 'source', 'model', 'imageUrl', 'photoUri']);
  return Object.entries(value as Record<string, unknown>).some(([key, entry]) => {
    if (ignoredKeys.has(key)) return false;
    if (nonBlankString(entry)) return true;
    if (Array.isArray(entry)) return entry.some(item => nonBlankString(item));
    return false;
  });
}

function getProgressPhotoUris(plant?: SavedPlantProfile): string[] {
  if (!plant) return [];
  const extended = plant as SavedPlantProfile & {
    progressPhotoUris?: unknown;
    progressPhotos?: unknown;
  };
  return meaningfulValues([
    ...arrayValues(extended.progressPhotoUris),
    ...arrayValues(extended.progressPhotos),
  ]);
}

function eventHasPhoto(event: PlantEvent): boolean {
  return Boolean(nonBlankString(event.photoUri));
}

function hasMeaningfulPhotoReference(value: unknown): boolean {
  if (nonBlankString(value)) return true;
  if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
  const record = value as Record<string, unknown>;
  return Boolean(
    nonBlankString(record.uri)
    || nonBlankString(record.url)
    || nonBlankString(record.photoUri),
  );
}

function normalizedCount(value: number): number {
  return Number.isFinite(value) ? Math.max(0, Math.trunc(value)) : 0;
}

export function buildPlantIntelligenceSummary({
  plant,
  samplePlant,
  setup,
  room,
  linkedKitCount,
}: {
  plant?: SavedPlantProfile;
  samplePlant?: SamplePlant;
  setup?: PlantSetupProfile | null;
  room?: RoomProfile | null;
  linkedKitCount: number;
}): PlantIntelligenceSummary {
  const sampleScientificName = nonBlankString((samplePlant as unknown as Record<string, unknown> | undefined)?.scientificName);
  const hasIdentification = Boolean(
    nonBlankString(plant?.name)
    || nonBlankString(plant?.commonName)
    || nonBlankString(plant?.scientificName)
    || hasMeaningfulIdentificationObject(plant?.identification)
    || nonBlankString(samplePlant?.name),
  );
  const hasScientificName = Boolean(
    nonBlankString(plant?.scientificName)
    || nonBlankString(plant?.identification?.scientificName)
    || sampleScientificName,
  );

  const identificationConfidence = finiteNumber(plant?.identification?.confidence);
  const scanConfidence = plant?.source === 'plant_scan' ? finiteNumber(plant.confidence) : undefined;
  const confidence = identificationConfidence ?? scanConfidence;
  const hasIdentificationConfidence = confidence != null;
  const confidenceNeedsReview = confidence != null && confidence < 70;

  const setupMediums = meaningfulValues([
    ...arrayValues(setup?.mediumTypes),
    setup?.mediumType,
    ...arrayValues(setup?.customMediumComponents),
    setup?.customMedium,
  ]);
  const hasContainerType = Boolean(nonBlankString(setup?.potType) && setup?.potType !== 'unsure');
  const hasPlantingMode = Boolean(nonBlankString(setup?.plantedIn) && setup?.plantedIn !== 'unsure');
  const hasSpecialPlantingDetails = Boolean(
    (nonBlankString(setup?.inGroundKind) && setup?.inGroundKind !== 'unsure')
    || (nonBlankString(setup?.hydroSetup) && setup?.hydroSetup !== 'unsure'),
  );
  const hasMedium = setupMediums.length > 0;
  const hasSetupDetails = Boolean(setup && (hasPlantingMode || hasSpecialPlantingDetails || hasContainerType || hasMedium));

  const hasAssignedSpace = Boolean(room);
  const hasEnvironmentDetails = isSpaceEnvironmentComplete(room);
  const setupPhotoCount = normalizeContextPhotos(setup?.setupPhotos, [setup?.setupPhotoUri, setup?.photoUris]).length;
  const environmentPhotoCount = normalizeContextPhotos(room?.environmentPhotos, [room?.environmentPhotoUri, room?.photoUri]).length;
  const hasSetupPhoto = setupPhotoCount > 0;
  const hasEnvironmentPhoto = environmentPhotoCount > 0;

  const wateringMethods = meaningfulValues([
    ...arrayValues(setup?.wateringMethods),
    setup?.wateringMethod,
  ]);
  const hasWateringMethod = wateringMethods.length > 0;

  const dedicatedLightTypes = meaningfulValues(arrayValues(setup?.dedicatedArtificialLightTypes));
  const hasDedicatedLightDetails = dedicatedLightTypes.length > 0
    || positiveFiniteNumber(setup?.dedicatedArtificialLightHoursPerDay) != null
    || Boolean(nonBlankString(setup?.dedicatedArtificialLightDistance));
  const hasDedicatedLightInfo = Boolean(
    setup
    && (typeof setup.usesDedicatedArtificialLight === 'boolean' || hasDedicatedLightDetails),
  );
  const usesDedicatedLight = setup?.usesDedicatedArtificialLight === true
    || (setup?.usesDedicatedArtificialLight == null && hasDedicatedLightDetails);

  const hasGrowthStage = Boolean(nonBlankString(plant?.growthStage) && plant?.growthStage !== 'unsure');
  const hasTimeOwned = Boolean(nonBlankString(plant?.timeOwned) && plant?.timeOwned !== 'unsure');
  const progressPhotoUris = getProgressPhotoUris(plant);
  const sortedPlantEvents = getSavedPlantEvents(plant);
  const hasProgressPhotos = progressPhotoUris.length > 0
    || sortedPlantEvents.some(event => event.type === 'progress_photo' && eventHasPhoto(event));
  const hasProgressHistory = progressPhotoUris.length > 0 || sortedPlantEvents.length > 0;
  const safeLinkedKitCount = normalizedCount(linkedKitCount);

  const identity: PlantKnowledgeCategory = { known: [], missing: [] };
  const environment: PlantKnowledgeCategory = { known: [], missing: [] };
  const setupKnowledge: PlantKnowledgeCategory = { known: [], missing: [] };
  const history: PlantKnowledgeCategory = { known: [], missing: [] };
  const optionalResources: PlantKnowledgeCategory = { known: [], missing: [] };
  const missingEssentialContext: PlantKnowledgeItem[] = [];
  const helpfulContext: PlantKnowledgeItem[] = [];
  const optionalEnhancements: PlantKnowledgeItem[] = [];

  const addEssential = (item: PlantKnowledgeItem): void => { missingEssentialContext.push(item); };
  const addHelpful = (item: PlantKnowledgeItem): void => { helpfulContext.push(item); };
  const addOptional = (item: PlantKnowledgeItem): void => { optionalEnhancements.push(item); };

  if (!hasIdentification) {
    const item = {
      key: 'identification',
      label: 'Plant identity',
      why: 'Add identity details so Pixie knows which plant this is.',
      action: 'review_identification' as const,
    };
    identity.missing.push(item);
    addEssential({ ...item, label: 'Review or add plant identification' });
  } else if (confidenceNeedsReview) {
    identity.known.push({ key: 'identification', label: 'Identified' });
    addHelpful({
      key: 'review_identification',
      label: 'Review identification if unsure',
      why: 'A quick review helps Pixie trust the plant identity.',
      action: 'review_identification',
    });
  } else {
    identity.known.push({ key: 'identification', label: 'Identified' });
  }

  if (hasScientificName) identity.known.push({ key: 'scientific_name', label: 'Scientific name' });
  else identity.missing.push({ key: 'scientific_name', label: 'Scientific name' });
  if (hasIdentificationConfidence) identity.known.push({ key: 'confidence', label: 'Identification confidence' });

  if (!room) {
    const item = {
      key: 'assigned_space',
      label: 'Assigned space',
      why: 'Assign a space so Pixie knows where this plant lives.',
      action: 'assign_space' as const,
    };
    environment.missing.push(item);
    addEssential({ ...item, label: 'Assign this plant to a space' });
  } else {
    environment.known.push({ key: 'assigned_space', label: 'Space assigned' });
    environment.known.push({
      key: 'indoor_outdoor',
      label: isOutdoorSpaceType(room.spaceType) ? 'Outdoor setting' : 'Indoor setting',
    });
  }

  if (hasEnvironmentDetails) environment.known.push({ key: 'light_profile', label: 'Light profile' });
  else if (room) {
    const item = {
      key: 'space_light',
      label: 'Environment light details',
      why: "Add light details so Pixie understands this plant's growing environment.",
      action: 'complete_environment' as const,
    };
    environment.missing.push(item);
    addEssential({ ...item, label: 'Set space light details' });
  }

  if (hasEnvironmentPhoto) {
    environment.known.push({
      key: 'environment_photo',
      label: `${environmentPhotoCount} environment ${environmentPhotoCount === 1 ? 'photo' : 'photos'}`,
    });
    if (environmentPhotoCount < maxContextPhotos) {
      addHelpful({
        key: 'additional_environment_photo',
        label: 'Add another environment photo',
        why: 'Another angle can help Pixie understand light and placement later.',
        action: 'add_environment_photo',
      });
    }
  } else if (room) {
    const item = {
      key: 'environment_photo',
      label: 'Environment photos',
      why: 'Add an environment photo so Pixie can better understand lighting and placement.',
      action: 'add_environment_photo' as const,
    };
    environment.missing.push(item);
    addEssential({ ...item, label: 'Add environment photo' });
  }

  const hasPlacement = Boolean(
    nonBlankString(plant?.placementDescription)
    || hasMeaningfulPhotoReference(plant?.placementPhoto),
  );
  if (hasPlacement) {
    environment.known.push({ key: 'placement', label: 'Placement location' });
  } else if (room) {
    addHelpful({
      key: 'placement',
      label: 'Add a placement photo',
      why: 'A placement photo helps Pixie understand where this plant sits within the space.',
      action: 'add_environment_photo',
    });
  }

  if (!hasSetupDetails) {
    const item = {
      key: 'setup_details',
      label: 'Basic setup details',
      why: 'Add setup details so Pixie understands the container and growing medium.',
      action: 'add_setup_details' as const,
    };
    setupKnowledge.missing.push(item);
    addEssential({ ...item, label: 'Add setup details' });
  } else {
    setupKnowledge.known.push({ key: 'setup_details', label: 'Basic setup added' });
  }

  if (hasContainerType) setupKnowledge.known.push({ key: 'container_type', label: 'Container type' });
  else setupKnowledge.missing.push({ key: 'container_type', label: 'Container type' });
  if (hasMedium) setupKnowledge.known.push({ key: 'medium', label: 'Growing medium' });
  else setupKnowledge.missing.push({ key: 'medium', label: 'Growing medium' });

  if (hasWateringMethod) setupKnowledge.known.push({ key: 'watering_method', label: 'Watering method' });
  else if (setup) {
    const item = {
      key: 'watering_method',
      label: 'Watering method',
      why: 'Add the watering method so Pixie understands how this plant is usually watered.',
      action: 'add_watering_method' as const,
    };
    setupKnowledge.missing.push(item);
    addHelpful(item);
  }

  if (hasDedicatedLightInfo) {
    setupKnowledge.known.push({
      key: 'dedicated_light',
      label: usesDedicatedLight
        ? 'Dedicated plant light noted'
        : 'Dedicated plant light status',
    });
  } else if (setup) {
    const item = {
      key: 'dedicated_light',
      label: 'Dedicated plant light',
      why: 'Add plant light details if this plant uses a focused grow light.',
      action: 'add_dedicated_light' as const,
    };
    setupKnowledge.missing.push(item);
    addHelpful(item);
  }

  if (hasSetupPhoto) {
    setupKnowledge.known.push({
      key: 'setup_photo',
      label: `${setupPhotoCount} setup ${setupPhotoCount === 1 ? 'photo' : 'photos'}`,
    });
    if (setupPhotoCount < maxContextPhotos) {
      addHelpful({
        key: 'additional_setup_photo',
        label: 'Add another setup photo',
        why: 'Another setup angle can help Pixie understand the pot, soil, or support later.',
        action: 'add_setup_photo',
      });
    }
  } else {
    const item = {
      key: 'setup_photo',
      label: 'Setup photos',
      why: 'Add a setup photo so Pixie can better understand the pot, soil, and drainage setup.',
      action: 'add_setup_photo' as const,
    };
    setupKnowledge.missing.push(item);
    addEssential({ ...item, label: 'Add setup photo' });
  }

  if (hasGrowthStage) identity.known.push({ key: 'growth_stage', label: 'Growth stage' });
  else if (plant) {
    addHelpful({
      key: 'growth_stage',
      label: 'Add growth stage',
      why: 'Growth stage gives Pixie helpful context without being required.',
      action: 'review_identification',
    });
  }

  if (hasTimeOwned) identity.known.push({ key: 'time_owned', label: 'Time owned' });
  else if (plant) {
    addHelpful({
      key: 'time_owned',
      label: 'Add time owned',
      why: 'Knowing how long this plant has been with you adds useful context.',
      action: 'review_identification',
    });
  }

  if (hasProgressHistory) history.known.push({ key: 'progress_history', label: 'Progress history started' });
  else history.missing.push({ key: 'progress_history', label: 'Progress history' });

  if (safeLinkedKitCount > 0) {
    optionalResources.known.push({
      key: 'linked_kit',
      label: `${safeLinkedKitCount} linked Kit ${safeLinkedKitCount === 1 ? 'item' : 'items'}`,
    });
  } else {
    const item = {
      key: 'linked_kit',
      label: 'Link Kit items',
      why: 'Link products only if you want Pixie to understand supplies used with this plant later.',
      action: 'add_linked_kit' as const,
    };
    optionalResources.missing.push(item);
    addOptional(item);
  }

  const priority = [
    'setup_photo',
    'environment_photo',
    'assigned_space',
    'setup_details',
    'space_light',
    'identification',
  ] as const;

  const prioritizedCandidates = priority.flatMap(key =>
    missingEssentialContext.filter(item => item.key === key && item.action),
  );
  const nextBestStep = prioritizedCandidates.find(item => !item.comingSoon)
    || missingEssentialContext.find(item => item.action && !item.comingSoon)
    || prioritizedCandidates[0]
    || missingEssentialContext.find(item => item.action)
    || missingEssentialContext[0];

  const isAllSet = missingEssentialContext.length === 0;
  const nextBestAction = nextBestStep?.why
    || (isAllSet
      ? "Pixie's all set for now. If anything changes, remember to update this plant's profile. In the meantime, sharing memories will help Pixie keep learning 🌱"
      : 'Add the remaining plant context so Pixie can finish this profile.');
  const nextBestActionKey = nextBestStep?.action;
  const nextBestActionComingSoon = Boolean(nextBestStep?.comingSoon);

  const compactKnown: PlantKnowledgeItem[] = [
    hasIdentification ? { key: 'identified', label: 'Identified' } : undefined,
    hasAssignedSpace ? { key: 'space_assigned', label: 'Space assigned' } : undefined,
    hasSetupDetails ? { key: 'setup_added', label: 'Setup added' } : undefined,
    hasSetupPhoto ? { key: 'setup_photos_added', label: 'Setup photos added' } : undefined,
    hasEnvironmentPhoto ? { key: 'environment_photos_added', label: 'Environment photos added' } : undefined,
  ].filter((item): item is PlantKnowledgeItem => Boolean(item)).slice(0, 5);

  const latestEvent = sortedPlantEvents[0];
  const knowledgeSummary: PlantKnowledgeSummary = {
    identity,
    environment,
    setup: setupKnowledge,
    history,
    optionalResources,
    historyContext: {
      hasProgressPhotos,
      eventCount: sortedPlantEvents.length,
      latestEventDate: latestEvent
        ? firstValidDateString(latestEvent.eventDate, latestEvent.createdAt)
        : undefined,
    },
    compactKnown,
    missingEssentialContext,
    helpfulContext,
    optionalEnhancements,
    nextBestStep,
  };

  return {
    isAllSet,
    hasIdentification,
    hasScientificName,
    hasAssignedSpace,
    hasEnvironmentDetails,
    hasEnvironmentPhoto,
    hasPlacement,
    hasSetupDetails,
    hasSetupPhoto,
    hasDedicatedLightInfo,
    hasProgressHistory,
    linkedKitCount: safeLinkedKitCount,
    knowledgeSummary,
    missingContext: missingEssentialContext,
    helpfulContext,
    optionalEnhancements,
    nextBestAction,
    nextBestActionKey,
    nextBestActionComingSoon,
  };
}
