'use client';

export const publicApiBase = process.env.NEXT_PUBLIC_API_URL ?? 'http://localhost:3001/api';
const STORE_KEY = 'chego-public-order-state';

export type DiscountType = 'PERCENTAGE' | 'FIXED' | 'FREE_DELIVERY';

export type StoreProductAdditional = {
  id: string;
  name: string;
  price: number | string;
};

export type StoreProductVariation = {
  id: string;
  name: string;
  price: number | string;
};

export type StoreProduct = {
  id: string;
  name: string;
  description?: string | null;
  imageUrl?: string | null;
  price: number | string;
  additionals?: StoreProductAdditional[];
  variations?: StoreProductVariation[];
};

export type StoreCategory = {
  id: string;
  name: string;
  products: StoreProduct[];
};

export type StoreCoupon = {
  id: string;
  code: string;
  type: DiscountType;
  value: number | string;
  minOrderValue?: number | string | null;
  validUntil: string;
};

export type StorePromotion = {
  id: string;
  title: string;
  description?: string | null;
  discountType: DiscountType;
  discountValue: number | string;
  endsAt: string;
};

export type Storefront = {
  id: string;
  slug: string;
  name: string;
  description?: string | null;
  city?: string | null;
  neighborhood?: string | null;
  acceptsCashOnDelivery?: boolean;
  baseDeliveryFee?: number | string | null;
  pricePerKm?: number | string | null;
  logoUrl?: string | null;
  coverImageUrl?: string | null;
  productCategories: StoreCategory[];
  activeCoupons?: StoreCoupon[];
  activePromotions?: StorePromotion[];
};

export type CartItem = {
  id: string;
  productId: string;
  name: string;
  basePrice: number;
  unitPrice: number;
  quantity: number;
  notes?: string;
  selectedVariation?: StoreProductVariation | null;
  selectedAdditionals: StoreProductAdditional[];
};

export type CheckoutProfile = {
  fullName: string;
  phone: string;
  email: string;
  street: string;
  number: string;
  complement: string;
  neighborhood: string;
  city: string;
  state: string;
  zipCode: string;
  notes: string;
  paymentMethod: 'PIX' | 'CREDIT_CARD' | 'CASH';
  couponCode: string;
};

export type PublicOrderState = {
  restaurantSlug: string;
  cart: CartItem[];
  checkout: CheckoutProfile;
  paymentIntent?: {
    provider: string;
    mode: string;
    paymentMethod: string;
    amount: number;
    currency: string;
    settlementPolicy?: {
      settlementFlow: string;
      platformReceivesAllOnlinePayments: boolean;
      restaurantPayoutDelayDays: number;
      settlementMode: string;
      defaultCashOnDeliveryEnabled: boolean;
      policyLabel: string;
    };
    pix?: {
      qrCodeText: string;
      qrCodeImageUrl: string;
      expiresAt: string;
    } | null;
    card?: {
      checkoutMode: string;
      provider: string;
      last4Preview?: string;
      checkoutUrl?: string | null;
      sandboxCheckoutUrl?: string | null;
      preferenceId?: string | null;
    } | null;
    wallet?: {
      available: boolean;
      settlement: string;
    } | null;
    cash?: {
      changeSupported: boolean;
      settlement: string;
    } | null;
  } | null;
  lastOrder?: {
    id: string;
    total: number;
    etaMinutes: number;
  } | null;
};

export type CartPricing = {
  subtotal: number;
  deliveryFee: number;
  promotionDiscount: number;
  couponDiscount: number;
  discountAmount: number;
  total: number;
  appliedPromotion: StorePromotion | null;
  appliedCoupon: StoreCoupon | null;
};

export const defaultCheckout: CheckoutProfile = {
  fullName: 'Camila Cliente',
  phone: '5511966665555',
  email: 'cliente@chego.app',
  street: '',
  number: '',
  complement: '',
  neighborhood: '',
  city: '',
  state: '',
  zipCode: '',
  notes: '',
  paymentMethod: 'PIX',
  couponCode: '',
};

export const defaultOrderState: PublicOrderState = {
  restaurantSlug: 'forno-da-esquina',
  cart: [],
  checkout: defaultCheckout,
  paymentIntent: null,
  lastOrder: null,
};

export function readOrderState(): PublicOrderState {
  if (typeof window === 'undefined') {
    return defaultOrderState;
  }

  const raw = window.localStorage.getItem(STORE_KEY);
  if (!raw) {
    return defaultOrderState;
  }

  try {
    const parsed = JSON.parse(raw) as Partial<PublicOrderState>;
    return {
      ...defaultOrderState,
      ...parsed,
      checkout: {
        ...defaultCheckout,
        ...(parsed.checkout ?? {}),
      },
      cart: Array.isArray(parsed.cart) ? parsed.cart : defaultOrderState.cart,
    };
  } catch {
    window.localStorage.removeItem(STORE_KEY);
    return defaultOrderState;
  }
}

export function writeOrderState(state: PublicOrderState) {
  window.localStorage.setItem(STORE_KEY, JSON.stringify(state));
}

export function formatCurrency(value?: number | string | null) {
  return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL' }).format(Number(value ?? 0));
}

export function buildCartItemId(input: {
  productId: string;
  notes?: string;
  selectedVariationId?: string | null;
  selectedAdditionalIds?: string[];
}) {
  return [
    input.productId,
    input.selectedVariationId ?? 'base',
    (input.selectedAdditionalIds ?? []).slice().sort().join(',') || 'none',
    input.notes?.trim() ?? '',
  ].join('|');
}

export function calculateUnitPrice(
  product: Pick<StoreProduct, 'price'>,
  selectedVariation?: Pick<StoreProductVariation, 'price'> | null,
  selectedAdditionals: Array<Pick<StoreProductAdditional, 'price'>> = [],
) {
  return Number(
    (
      Number(product.price) +
      Number(selectedVariation?.price ?? 0) +
      selectedAdditionals.reduce((sum, additional) => sum + Number(additional.price), 0)
    ).toFixed(2),
  );
}

export function calculateDiscountValue(
  discountType: DiscountType,
  baseAmount: number,
  value: number,
  deliveryFee = 0,
) {
  if (discountType === 'FREE_DELIVERY') {
    return Number(Math.min(baseAmount + deliveryFee, deliveryFee).toFixed(2));
  }
  if (discountType === 'PERCENTAGE') {
    return Number(Math.min(baseAmount, (baseAmount * value) / 100).toFixed(2));
  }
  return Number(Math.min(baseAmount, value).toFixed(2));
}

export function calculateCartPricing(state: PublicOrderState, storefront?: Storefront | null): CartPricing {
  const subtotal = Number(
    state.cart.reduce((sum, item) => sum + Number(item.unitPrice) * item.quantity, 0).toFixed(2),
  );
  const deliveryFee = subtotal > 0 ? Number(storefront?.baseDeliveryFee ?? 0) : 0;
  const activePromotions = storefront?.activePromotions ?? [];
  const activeCoupons = storefront?.activeCoupons ?? [];
  const appliedPromotion = activePromotions[0] ?? null;
  const promotionDiscount = appliedPromotion
    ? calculateDiscountValue(
        appliedPromotion.discountType,
        subtotal,
        Number(appliedPromotion.discountValue),
        deliveryFee,
      )
    : 0;

  const couponCode = (state.checkout?.couponCode ?? '').trim().toUpperCase();
  const appliedCoupon =
    activeCoupons.find((coupon) => coupon.code.toUpperCase() === couponCode) ?? null;
  const couponMinOrder = Number(appliedCoupon?.minOrderValue ?? 0);
  const couponDiscount =
    appliedCoupon && subtotal >= couponMinOrder
      ? calculateDiscountValue(
          appliedCoupon.type,
          Math.max(0, subtotal - promotionDiscount),
          Number(appliedCoupon.value),
          deliveryFee,
        )
      : 0;

  const discountAmount = Number(
    Math.min(subtotal + deliveryFee, promotionDiscount + couponDiscount).toFixed(2),
  );
  const total = Number(Math.max(0, subtotal + deliveryFee - discountAmount).toFixed(2));

  return {
    subtotal,
    deliveryFee,
    promotionDiscount,
    couponDiscount,
    discountAmount,
    total,
    appliedPromotion,
    appliedCoupon,
  };
}

export async function fetchStorefront(slug: string) {
  const response = await fetch(`${publicApiBase}/public/catalog/store/${slug}`, { cache: 'no-store' });
  const payload = await response.json().catch(() => null);
  if (!response.ok) {
    throw new Error(payload?.message ?? 'Falha ao carregar a loja publica.');
  }
  return payload as Storefront;
}

export async function createPublicOrder(state: PublicOrderState) {
  const response = await fetch(`${publicApiBase}/orders/public`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      restaurantSlug: state.restaurantSlug,
      fullName: state.checkout.fullName,
      phone: state.checkout.phone,
      email: state.checkout.email || undefined,
      street: state.checkout.street,
      number: state.checkout.number,
      complement: state.checkout.complement || undefined,
      neighborhood: state.checkout.neighborhood,
      city: state.checkout.city,
      state: state.checkout.state,
      zipCode: state.checkout.zipCode,
      notes: state.checkout.notes || undefined,
      couponCode: (state.checkout?.couponCode ?? '').trim() || undefined,
      paymentMethod: state.checkout.paymentMethod,
      items: state.cart.map((item) => ({
        productId: item.productId,
        quantity: String(item.quantity),
        notes: item.notes || undefined,
        selectedVariationId: item.selectedVariation?.id || undefined,
        selectedAdditionalIds: item.selectedAdditionals.map((additional) => additional.id),
      })),
    }),
  });

  const payload = await response.json().catch(() => null);
  if (!response.ok) {
    throw new Error(payload?.message ?? 'Falha ao criar pedido publico.');
  }
  return payload as {
    id: string;
    summary: { subtotal: number; deliveryFee: number; serviceFee: number; discountAmount: number; total: number };
    etaMinutes: number;
  };
}

export async function createPublicPaymentIntent(state: PublicOrderState, amount: number) {
  const orderId = state.lastOrder?.id;
  if (!orderId && state.checkout.paymentMethod !== 'CASH') {
    throw new Error('Pedido ainda nao foi criado para gerar a cobranca.');
  }

  const response = await fetch(`${publicApiBase}/payments/public/intent`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      orderId,
      restaurantSlug: state.restaurantSlug,
      paymentMethod: state.checkout.paymentMethod,
      amount: amount.toFixed(2),
      fullName: state.checkout.fullName,
      phone: state.checkout.phone,
      email: state.checkout.email || undefined,
    }),
  });

  const payload = await response.json().catch(() => null);
  if (!response.ok) {
    throw new Error(payload?.message ?? 'Falha ao preparar pagamento publico.');
  }
  return payload as NonNullable<PublicOrderState['paymentIntent']>;
}

export async function fetchPublicPaymentStatus(orderId: string) {
  const response = await fetch(`${publicApiBase}/payments/public/order/${orderId}/status`, {
    cache: 'no-store',
  });
  const payload = await response.json().catch(() => null);
  if (!response.ok) {
    throw new Error(payload?.message ?? 'Falha ao consultar o status do pagamento.');
  }
  return payload as {
    orderId: string;
    orderStatus: string;
    paymentStatus: string;
    approved: boolean;
    intent?: PublicOrderState['paymentIntent'] | null;
    amount: number;
  };
}
