import AsyncStorage from '@react-native-async-storage/async-storage';
import { create } from 'zustand';
import { createJSONStorage, persist } from 'zustand/middleware';
import { API_URL } from '../runtime-config';

export type StoreProduct = {
  id: string;
  name: string;
  description?: string | null;
  imageUrl?: string | null;
  price: number | string;
};

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

export type Storefront = {
  id: string;
  slug: string;
  name: string;
  description?: string | null;
  street?: string | null;
  number?: string | null;
  zipCode?: string | null;
  city?: string | null;
  neighborhood?: string | null;
  logoUrl?: string | null;
  coverImageUrl?: string | null;
  acceptsCashOnDelivery?: boolean;
  baseDeliveryFee?: number | string | null;
  pricePerKm?: number | string | null;
  activeCoupons?: Array<{
    id: string;
    code: string;
    type: 'PERCENTAGE' | 'FIXED' | 'FREE_DELIVERY';
    value: number;
    minOrderValue?: number | null;
    validUntil: string;
  }>;
  productCategories: StoreCategory[];
};

export type StoreSummary = {
  id: string;
  slug: string;
  name: string;
  description?: string | null;
  street?: string | null;
  number?: string | null;
  zipCode?: string | null;
  city?: string | null;
  neighborhood?: string | null;
  categories?: string[];
  logoUrl?: string | null;
  coverImageUrl?: string | null;
  acceptsCashOnDelivery?: boolean;
  baseDeliveryFee?: number | string | null;
  pricePerKm?: number | string | null;
  featuredProducts?: Array<{
    name: string;
    imageUrl?: string | null;
    description?: string | null;
  }>;
};

export type CartItem = {
  productId: string;
  name: string;
  price: number;
  quantity: number;
  notes?: string;
};

type PublicPaymentIntent = {
  provider: string;
  mode: string;
  paymentMethod: string;
  amount: number;
  currency: 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;
  cash?: {
    changeSupported: boolean;
    settlement: string;
  } | null;
};

type CreatedOrder = {
  id: string;
  summary: {
    subtotal: number;
    deliveryFee: number;
    serviceFee: number;
    discountAmount?: number;
    total: number;
  };
  etaMinutes: number;
};

type PaymentMethod = 'PIX' | 'CREDIT_CARD' | 'CASH';

interface CustomerOrderState {
  stores: StoreSummary[];
  selectedStoreSlug: string;
  storefront: Storefront | null;
  cart: CartItem[];
  couponCode: string;
  paymentMethod: PaymentMethod;
  lastOrder: CreatedOrder | null;
  paymentIntent: PublicPaymentIntent | null;
  loading: boolean;
  saving: boolean;
  error: string;
  loadStores: (filters?: { search?: string; category?: string }) => Promise<void>;
  loadStorefront: (slug?: string) => Promise<void>;
  selectStore: (slug: string) => void;
  addToCart: (item: { productId: string; name: string; price: number; notes?: string }) => void;
  updateQuantity: (productId: string, quantity: number) => void;
  removeItem: (productId: string) => void;
  setCouponCode: (value: string) => void;
  setPaymentMethod: (method: PaymentMethod) => void;
  clearCart: () => void;
  clearError: () => void;
  createOrder: (checkout: {
    fullName: string;
    phone: string;
    email: string;
    street: string;
    number: string;
    complement: string;
    neighborhood: string;
    city: string;
    state: string;
    zipCode: string;
  }) => Promise<void>;
}

function toNumber(value?: number | string | null) {
  const parsed = Number(value ?? 0);
  return Number.isFinite(parsed) ? parsed : 0;
}

function toMessage(error: unknown) {
  if (error instanceof Error) {
    return error.message;
  }

  return 'Falha ao carregar o fluxo de pedido.';
}

async function requestJson<T>(path: string, init?: RequestInit) {
  const response = await fetch(`${API_URL}${path}`, {
    ...init,
    headers: {
      'Content-Type': 'application/json',
      ...(init?.headers ?? {}),
    },
  });

  const payload = await response.json().catch(() => null);
  if (!response.ok) {
    throw new Error(payload?.message ?? `Falha ao acessar ${path}.`);
  }

  return payload as T;
}

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

export const useCustomerOrder = create<CustomerOrderState>()(persist((set, get) => ({
  stores: [],
  selectedStoreSlug: 'forno-da-esquina',
  storefront: null,
  cart: [],
  couponCode: '',
  paymentMethod: 'PIX',
  lastOrder: null,
  paymentIntent: null,
  loading: false,
  saving: false,
  error: '',
  loadStores: async (filters) => {
    set({ loading: true, error: '' });
    try {
      const params = new URLSearchParams();
      if (filters?.search?.trim()) {
        params.set('search', filters.search.trim());
      }
      if (filters?.category?.trim()) {
        params.set('category', filters.category.trim());
      }
      const query = params.toString();
      const stores = await requestJson<StoreSummary[]>(`/public/catalog/stores${query ? `?${query}` : ''}`);
      const selectedStoreSlug = get().selectedStoreSlug || stores[0]?.slug || 'forno-da-esquina';
      set({ stores, selectedStoreSlug, loading: false });
    } catch (error) {
      set({ error: toMessage(error), loading: false });
    }
  },
  loadStorefront: async (slug) => {
    const selectedStoreSlug = slug ?? get().selectedStoreSlug;
    set({ loading: true, error: '' });
    try {
      const storefront = await requestJson<Storefront>(`/public/catalog/store/${selectedStoreSlug}`);
      set({ storefront, selectedStoreSlug: storefront.slug, loading: false });
    } catch (error) {
      set({ error: toMessage(error), loading: false });
    }
  },
  selectStore: (slug) => set({ selectedStoreSlug: slug }),
  addToCart: (item) =>
    set((state) => {
      const current = state.cart.find((entry) => entry.productId === item.productId);
      const cart = current
        ? state.cart.map((entry) =>
            entry.productId === item.productId
              ? { ...entry, quantity: entry.quantity + 1, notes: item.notes ?? entry.notes }
              : entry,
          )
        : [...state.cart, { ...item, quantity: 1 }];
      return { cart };
    }),
  updateQuantity: (productId, quantity) =>
    set((state) => ({
      cart: quantity <= 0
        ? state.cart.filter((item) => item.productId !== productId)
        : state.cart.map((item) => (item.productId === productId ? { ...item, quantity } : item)),
    })),
  removeItem: (productId) => set((state) => ({ cart: state.cart.filter((item) => item.productId !== productId) })),
  setCouponCode: (couponCode) => set({ couponCode: couponCode.toUpperCase() }),
  setPaymentMethod: (paymentMethod) => set({ paymentMethod }),
  clearCart: () => set({ cart: [], couponCode: '', lastOrder: null, paymentIntent: null }),
  clearError: () => set({ error: '' }),
  createOrder: async (checkout) => {
    const { selectedStoreSlug, cart, paymentMethod, couponCode } = get();
    if (!cart.length) {
      set({ error: 'Adicione pelo menos um item ao carrinho.' });
      return;
    }

    set({ saving: true, error: '' });
    try {
      const createdOrder = await requestJson<CreatedOrder>('/orders/public', {
        method: 'POST',
        body: JSON.stringify({
          restaurantSlug: selectedStoreSlug,
          fullName: checkout.fullName,
          phone: checkout.phone,
          email: checkout.email || undefined,
          street: checkout.street,
          number: checkout.number,
          complement: checkout.complement || undefined,
          neighborhood: checkout.neighborhood,
          city: checkout.city,
          state: checkout.state,
          zipCode: checkout.zipCode,
          couponCode: couponCode.trim() || undefined,
          paymentMethod,
          items: cart.map((item) => ({
            productId: item.productId,
            quantity: String(item.quantity),
            notes: item.notes || undefined,
          })),
        }),
      });

      const paymentIntent = await requestJson<PublicPaymentIntent>('/payments/public/intent', {
        method: 'POST',
        body: JSON.stringify({
          orderId: createdOrder.id,
          restaurantSlug: selectedStoreSlug,
          paymentMethod,
          amount: createdOrder.summary.total.toFixed(2),
          fullName: checkout.fullName,
          phone: checkout.phone,
          email: checkout.email || undefined,
        }),
      });

      set({
        lastOrder: createdOrder,
        paymentIntent,
        cart: [],
        couponCode: '',
        saving: false,
      });
    } catch (error) {
      set({ error: toMessage(error), saving: false });
    }
  },
}), {
  name: 'chego-mobile-customer-order',
  storage: createJSONStorage(() => AsyncStorage),
  partialize: (state) => ({
    selectedStoreSlug: state.selectedStoreSlug,
    cart: state.cart,
    couponCode: state.couponCode,
    paymentMethod: state.paymentMethod,
    lastOrder: state.lastOrder,
    paymentIntent: state.paymentIntent,
  }),
}));
