import type { Id } from "../_generated/dataModel";
import type { QueryCtx } from "../_generated/server";

// ─── Cart Item Issues (discriminated union) ─────────────────────────────────

export type CartItemIssue =
  | { type: "out_of_stock"; variantId: Id<"productVariants">; requested: number; available: number }
  | { type: "insufficient_stock"; variantId: Id<"productVariants">; requested: number; available: number }
  | { type: "variant_inactive"; variantId: Id<"productVariants"> }
  | { type: "variant_not_found"; variantId: Id<"productVariants"> }
  | { type: "product_not_found"; productId: Id<"products"> }
  | { type: "price_changed"; variantId: Id<"productVariants">; oldPrice: number; newPrice: number };

// ─── Validated & Enriched Cart Item ─────────────────────────────────────────

export type ValidatedCartItem = {
  variantId: Id<"productVariants">;
  productId: Id<"products">;
  quantity: number;
  unitPrice: number;
  originalPrice: number;
  productName: string;
  variantName: string;
  sku: string;
  imageUrl: string | undefined;
  stockQuantity: number;

  weight: number;
  weightUnit: "g" | "kg" | "lb" | "oz";
  length: number | undefined;
  width: number | undefined;
  height: number | undefined;
  dimensionUnit: "cm" | "in" | undefined;

  productSlug: string;
  parentCategorySlug: string;
  childCategorySlug: string;
};

// ─── Validation Result ──────────────────────────────────────────────────────

export type CartValidationResult = {
  valid: boolean;
  items: ValidatedCartItem[];
  issues: CartItemIssue[];
  subtotal: number;
};

// ─── Validation & Enrichment Helper ─────────────────────────────────────────

/**
 * Validates every cart line item (stock, active status, price drift) and
 * enriches each with weight/dimensions for downstream shipping-rate lookups.
 *
 * Price-change issues are warnings — they do NOT block checkout.
 * Stock/missing/inactive issues ARE blocking.
 */
export async function validateAndEnrichCart(
  ctx: Pick<QueryCtx, "db">,
  items: { productId: Id<"products">; variantId?: Id<"productVariants">; quantity: number; price: number }[]
): Promise<CartValidationResult> {
  const validatedItems: ValidatedCartItem[] = [];
  const issues: CartItemIssue[] = [];
  const blockingVariantIds = new Set<Id<"productVariants">>();

  for (const item of items) {
    if (!item.variantId) continue;
    const variantId = item.variantId;

    const variant = await ctx.db.get(variantId);
    if (!variant) {
      issues.push({ type: "variant_not_found" as const, variantId });
      continue;
    }
    if (!variant.isActive) {
      issues.push({ type: "variant_inactive" as const, variantId });
      continue;
    }

    const product = await ctx.db.get(variant.productId);
    if (!product || product.status !== "active") {
      issues.push({ type: "product_not_found" as const, productId: item.productId });
      continue;
    }

    if (variant.stockQuantity === 0) {
      issues.push({
        type: "out_of_stock" as const,
        variantId,
        requested: item.quantity,
        available: 0,
      });
      blockingVariantIds.add(variantId);
    } else if (variant.stockQuantity < item.quantity) {
      issues.push({
        type: "insufficient_stock" as const,
        variantId,
        requested: item.quantity,
        available: variant.stockQuantity,
      });
      blockingVariantIds.add(variantId);
    }

    if (variant.price !== item.price) {
      issues.push({
        type: "price_changed" as const,
        variantId,
        oldPrice: item.price,
        newPrice: variant.price,
      });
    }

    const images = await ctx.db
      .query("productImages")
      .withIndex("by_product", (q) => q.eq("productId", variant.productId))
      .collect();
    images.sort((a, b) => a.position - b.position);

    validatedItems.push({
      variantId,
      productId: variant.productId,
      quantity: item.quantity,
      unitPrice: variant.price,
      originalPrice: item.price,
      productName: product.name,
      variantName: variant.name,
      sku: variant.sku,
      imageUrl: images[0]?.url,
      stockQuantity: variant.stockQuantity,
      weight: variant.weight,
      weightUnit: variant.weightUnit,
      length: variant.length,
      width: variant.width,
      height: variant.height,
      dimensionUnit: variant.dimensionUnit,
      productSlug: product.slug,
      parentCategorySlug: product.parentCategorySlug,
      childCategorySlug: product.childCategorySlug,
    });
  }

  const blockingIssues = issues.filter(i => i.type !== "price_changed");
  const valid = blockingIssues.length === 0;

  const subtotal = validatedItems
    .filter(item => !blockingVariantIds.has(item.variantId))
    .reduce((sum, item) => sum + item.unitPrice * item.quantity, 0);

  return { valid, items: validatedItems, issues, subtotal };
}

// ─── Shippo Shipping Rate Types ──────────────────────────────────────────────

export type ShippoRate = {
  objectId: string;
  provider: string;
  servicelevelName: string;
  servicelevelToken: string;
  amount: string;
  currency: string;
  estimatedDays: number | null;
  durationTerms: string;
  arrivesBy: string | null;
  carrierAccount: string;
};

export type SelectedShippingRate = {
  provider: string;
  serviceName: string;
  serviceToken: string;
  amount: number;
  currency: string;
  estimatedDays: number | null;
  durationTerms: string;
  carrierAccount: string;
};

export type ShippingRateResult = {
  shipmentObjectId: string;
  selectedRate: SelectedShippingRate;
  alternativeRates: SelectedShippingRate[];
  cartSubtotal: number;
  shippingTotal: number;
  orderTotal: number;
};

// ─── Checkout Session Types (Stripe) ─────────────────────────────────────────

export type CreateCheckoutSessionInput = {
  addressId: Id<"addresses">;
  shipmentObjectId: string;
  shippingRate: {
    provider: string;
    serviceName: string;
    serviceToken: string;
    amount: number;
    currency: string;
    estimatedDays: number | null;
    durationTerms: string;
    carrierAccount: string;
  };
  sessionId: string | undefined;
};

export type CheckoutSessionResult = {
  clientSecret: string;
};

export type CheckoutSessionStatus = {
  status: "complete" | "expired" | "open";
  paymentStatus: string;
  customerEmail: string | null;
};

// ─── Shippo Address Validation Types ─────────────────────────────────────────

export type ShippoConfidenceScore = "high" | "medium" | "low";
export type ShippoValidationValue = "valid" | "partially_valid" | "invalid";
export type ShippoAddressType =
  | "residential"
  | "commercial"
  | "unknown"
  | "po_box"
  | "military";

export type ShippoValidationReason = {
  code: string;
  description: string;
};

export type RecommendedAddress = {
  addressLine1: string;
  additionalInformation?: string;
  city: string;
  postalCode: string;
  country: string;
  completeAddress?: string;
  confidenceScore: ShippoConfidenceScore;
  confidenceCode: string;
  confidenceDescription: string;
};

export type AddressValidationResult = {
  isValid: boolean;
  validationValue: ShippoValidationValue;
  reasons: ShippoValidationReason[];
  addressType: ShippoAddressType;
  changedAttributes: string[];
  recommendedAddress?: RecommendedAddress;
  originalAddress: {
    addressLine1: string;
    additionalInformation?: string;
    city: string;
    postalCode: string;
    country: string;
  };
};
