import type { CSSProperties } from "react";
import type { ButtonStyles, ModalStyles, PrimeStyleClassNames, MatchDetail as MatchDetailType, SizingResult as SizingResultType, SizeGuideField as SizeGuideFieldType, NormalizedSection } from "../types";
export type BodyType = "slim" | "athletic" | "average" | "stocky" | "plus";
export type ChestProfile = "narrow" | "average" | "broad";
export type MidsectionProfile = "flat" | "average" | "round";
export type HipProfile = "narrow" | "average" | "full";
export type MatchDetail = MatchDetailType;
export type SizingResult = SizingResultType;
export type SizeGuideField = SizeGuideFieldType;
/** Full body measurements computed by the LLM (cm or in based on measurementsUnit) */
export interface ProfileMeasurements {
    chest?: number;
    bust?: number;
    waist?: number;
    hips?: number;
    shoulderWidth?: number;
    sleeveLength?: number;
    inseam?: number;
    neckCircumference?: number;
    thighCircumference?: number;
    wristCircumference?: number;
    footLengthCm?: number;
    height?: number;
    /** Allow other fields the backend may return */
    [key: string]: number | undefined;
}
/** A cached size recommendation for a specific product */
export interface SizeHistoryEntry {
    productId: string;
    productTitle: string;
    productImage?: string;
    recommendedSize: string;
    confidence?: string;
    /** For multi-section products: { "Jacket Size": "50", "Pants": "34", ... } */
    sections?: Record<string, string>;
    /** Full per-section data (size/length/availableSizes/...) — preserved so
     *  cached recommendations carry the same detail as a fresh API response. */
    sectionsFull?: Record<string, {
        recommendedSize: string;
        size?: string;
        length?: string;
        availableSizes?: string[];
        availableLengths?: string[];
    }>;
    /** Top-level recommended length (single-piece products that have a separate
     *  length axis like Regular / Long / Short). */
    recommendedLength?: string;
    savedAt: number;
}
export interface Profile {
    id: string;
    name: string;
    gender: "male" | "female";
    height?: number;
    weight?: number;
    age?: number;
    /** @deprecated Use `height` */ heightCm?: number;
    /** @deprecated Use `weight` */ weightKg?: number;
    chestProfile?: ChestProfile;
    midsectionProfile?: MidsectionProfile;
    hipProfile?: HipProfile;
    bandSize?: string;
    cupSize?: string;
    braSizeRegion?: string;
    photoBase64?: string;
    /** Optional uploaded profile photo URL/data URL used by remote profile sync. */
    photoUrl?: string;
    measurements?: ProfileMeasurements;
    measurementsUnit?: "cm" | "in";
    sizeHistory?: SizeHistoryEntry[];
    chest?: number;
    bust?: number;
    waist?: number;
    hips?: number;
    shoulderWidth?: number;
    sleeveLength?: number;
    inseam?: number;
    neckCircumference?: number;
    footLengthCm?: number;
    shoeEU?: string;
    shoeUS?: string;
    shoeUK?: string;
    fitPreference?: string;
    country?: string;
    sizingUnit?: string;
    heightUnit?: string;
    weightUnit?: string;
    customMeasurements?: Record<string, number>;
    createdAt?: number;
    lastUsedAt?: number;
    /** Bumped any time measurements/answers change — used to invalidate sizeHistory cache */
    lastEditedAt?: number;
}
export interface ProfileCompletionDraft {
    source?: "size-result" | string;
    createdAt?: number;
    productId?: string;
    productTitle?: string;
    gender?: "male" | "female";
    height?: number;
    weight?: number;
    heightUnit?: "cm" | "in" | "ft" | string;
    weightUnit?: "kg" | "lbs" | string;
    sizingUnit?: "cm" | "in" | string;
    age?: number;
    chestProfile?: ChestProfile;
    midsectionProfile?: MidsectionProfile;
    hipProfile?: HipProfile;
    bandSize?: string;
    cupSize?: string;
    braSizeRegion?: string;
    photoBase64?: string;
    photoUrl?: string;
    measurements?: ProfileMeasurements;
    measurementsUnit?: "cm" | "in";
    customMeasurements?: Record<string, number>;
}
export interface HistoryEntry {
    id: string;
    productId?: string;
    productTitle?: string;
    productUrl?: string;
    jobId?: string;
    productImage?: string;
    productImages?: string[];
    productCarouselItems?: Array<{
        image: string;
        title?: string;
        href?: string;
    }>;
    resultImageUrl?: string;
    recommendedSize?: string;
    confidence?: string;
    reasoning?: string;
    internationalSizes?: Record<string, string>;
    matchDetails?: MatchDetail[];
    profileName?: string;
    date: number;
    /** Full sizing result for restoring the result view */
    sizingResult?: SizingResultType | null;
    /** Size guide snapshot for restoring charts & multi-section layout */
    sizeGuide?: {
        found: boolean;
        title?: string;
        headers?: string[];
        rows?: string[][];
        sections?: Record<string, NormalizedSection>;
        sectionImages?: Record<string, string>;
    } | null;
    /** Snapshot of the inputs/estimates needed to complete a fit profile from a restored result. */
    profileCompletionDraft?: ProfileCompletionDraft;
    /** True when the user's model photo for this entry is stored as a Blob in
     *  IndexedDB (key = entry.id). Restored as a File on history click so the
     *  user does not need to re-upload before clicking Try On. Photos live in
     *  IndexedDB rather than in this localStorage object to avoid the ~5–10 MB
     *  quota. Old entries without a photo set this false/undefined. */
    hasPhoto?: boolean;
    /** True when the try-on RESULT image is stored as a Blob in IndexedDB
     *  (key = `result-<entry.id>`). Restored as an object URL on history
     *  click so the result survives even if the original URL (Cloudinary
     *  / data:) expired or was lost. */
    hasResult?: boolean;
    /** What the user actually selected when they ran the try-on (per section). */
    selectedSizes?: Array<{
        sectionName: string;
        selectedSize: string;
        selectedLength?: string;
        displayLabel: string;
        isOverride: boolean;
    }>;
}
export interface PrimeStyleAddToBagPayload {
    productId?: string;
    productTitle?: string;
    productUrl?: string;
    recommendedSize?: string;
    sizingResult?: SizingResultType | null;
    resultImageUrl?: string | null;
    historyEntryId?: string;
    selectedSizes?: HistoryEntry["selectedSizes"];
}
export interface SizeGuide {
    found: boolean;
    title?: string;
    headers?: string[];
    rows?: string[][];
    requiredFields?: SizeGuideField[];
    sections?: Record<string, NormalizedSection>;
    /** Mapping of section name → product image URL (classified by AI) */
    sectionImages?: Record<string, string>;
}
export type ViewState = "idle" | "welcome" | "body-profile" | "estimation-review" | "size-result" | "upload" | "photo-guide" | "processing" | "result" | "error" | "no-chart" | "profiles";
export type DrawerType = "profiles" | "history" | null;
export interface PrimeStyleTryonProps {
    productImage: string;
    /** Optional gallery of product photos for the active color/variant.
     *
     *  - Shown as an auto-cycling carousel on the single-garment
     *    SizeResultView while the try-on image is being generated.
     *  - At try-on time the SDK runs MediaPipe BlazePose on every entry in
     *    parallel and forwards the highest-scoring "model wearing the
     *    garment" shot to Gemini as image 2. Flat-lays / close-up details
     *    score ~0 and are skipped. The first image still shows in the UI
     *    unchanged. */
    productImages?: string[];
    /** Optional carousel items shown in the size-result card.
     *  Used for "complete the look" recommendations. Falls back to productImages. */
    productCarouselItems?: Array<{
        image: string;
        title?: string;
        href?: string;
    }>;
    /** Optional explicit override — if you already know which image in the
     *  gallery is the model-wearing-the-garment shot, pass it here and the
     *  SDK skips the MediaPipe-based auto-pick. Falls through to auto-pick
     *  (or to `productImage`) when omitted. */
    garmentReferenceImage?: string;
    /** Optional clean product/detail image. When omitted, the backend picker
     *  selects one from productImages and sends it as Gemini's extra design reference. */
    garmentDetailImage?: string;
    productTitle?: string;
    /** Absolute product page URL, used by restored history results to continue shopping. */
    productUrl?: string;
    /** Stable product identifier — used to cache size recommendations per (profile, product) */
    productId?: string;
    /** Optional product category metadata used to select the correct sizing flow. */
    productCategory?: string;
    /** Optional target product gender metadata. Prevents AI fallback when the host already knows it. */
    productGender?: string;
    /** Optional product subcategory metadata used to select accessory flows like belts, hats, and eyewear. */
    productSubcategory?: string;
    /** Merchant/product-type label used before keyword fallback. */
    productType?: string;
    /** Optional product vendor/brand metadata forwarded to backend context. */
    productVendor?: string;
    /** Explicit fit category override, e.g. apparel, belt, shoe, hat, sunglasses. */
    productFitType?: string;
    /** Product tags used as sizing-flow detection signals. */
    productTags?: string[] | string;
    /** Alias for productTags for hosts that already use a `tags` property. */
    tags?: string[] | string;
    /** Free-text product description (e.g. "Brown slip maxi dress with spaghetti straps").
     *  Forwarded to the backend try-on prompt so Gemini knows the garment context. */
    productDescription?: string;
    /** Material / fabric composition (e.g. "60% Recycled Polyester / 40% Polyester",
     *  "100% Cotton", "Wool blend"). Forwarded to the prompt so Gemini drapes
     *  the fabric correctly without guessing from the image alone. */
    productMaterial?: string;
    buttonText?: string;
    /** When true, a completed try-on for this product turns the storefront button into a saved fit result. */
    limitOneColorTryOnPerProduct?: boolean;
    apiUrl?: string;
    showPoweredBy?: boolean;
    /** Show the default camera icon in the button. Defaults to true. Set to false to hide it. */
    showIcon?: boolean;
    /** Custom icon element to replace the default camera icon. Pass any React node (e.g. an <svg> or <img>). */
    buttonIcon?: React.ReactNode;
    /** BCP-47 locale tag for UI translations (e.g. "en", "ja", "pt-BR"). Auto-detects from browser if omitted. */
    locale?: string;
    buttonStyles?: ButtonStyles;
    modalStyles?: ModalStyles;
    classNames?: PrimeStyleClassNames;
    className?: string;
    style?: CSSProperties;
    /** Optional portal target for modal/dropdown overlays. */
    portalContainer?: Element | DocumentFragment | null;
    /** Optional Microsoft Clarity project id. Defaults to PrimeStyleAI's SDK replay project. */
    clarityProjectId?: string;
    onOpen?: () => void;
    onClose?: () => void;
    onUpload?: (file: File) => void;
    onProcessing?: (jobId: string) => void;
    onComplete?: (result: {
        jobId: string;
        imageUrl: string;
    }) => void;
    onError?: (error: {
        message: string;
        code?: string;
    }) => void;
    /** Called when the shopper clicks Add to Bag on the SDK result screen. */
    onAddToBag?: (payload: PrimeStyleAddToBagPayload) => void | Promise<void>;
    /** Optional result-screen CTA label overrides. */
    addToBagLabel?: string;
    continueShoppingLabel?: string;
    backToProductPageLabel?: string;
    /** Size guide data — pass as-is, any format (JSON object, array, HTML). Structured formats are parsed instantly client-side; unrecognised formats fall back to AI. */
    sizeGuideData?: unknown;
}
