/**
 * @file AppContext.tsx
 * @description Gestor de Estado Global (Context API) da aplicação Web.
 */
import React, { createContext, useContext, useEffect, useState } from 'react';
import { nanoid } from 'nanoid';
import { Appointment, AppointmentStatus, Barber, BarberShop, CartItem, Order, Product, Service, User, WaitlistEntry, AppNotification } from '../types';
import { mockUsers } from '../data/mock';
import { storage } from '../lib/storage';
import { supabase } from '../lib/supabase';

type State = {
  user?: User;
  users: User[];
  shops: BarberShop[];
  shopsReady: boolean;
  appointments: Appointment[];
  orders: Order[];
  cart: CartItem[];
  favorites: string[];
  waitlists: WaitlistEntry[];
  notifications: AppNotification[];
};

type AppContextValue = State & {
  login: (email: string, password: string) => boolean;
  logout: () => void;
  register: (payload: Omit<User, 'id' | 'shopId'> & { shopName?: string }) => boolean;
  toggleFavorite: (shopId: string) => void;
  isFavorite: (shopId: string) => boolean;
  addToCart: (item: CartItem) => void;
  removeFromCart: (refId: string) => void;
  clearCart: () => void;
  createAppointment: (input: Omit<Appointment, 'id' | 'status' | 'total'>) => Promise<Appointment | null>;
  placeOrder: (customerId: string, shopId?: string) => Promise<Order | null>;
  updateAppointmentStatus: (id: string, status: Appointment['status']) => Promise<void>;
  updateOrderStatus: (id: string, status: Order['status']) => Promise<void>;
  addService: (shopId: string, service: Omit<Service, 'id'>) => Promise<void>;
  updateService: (shopId: string, service: Service) => Promise<void>;
  deleteService: (shopId: string, serviceId: string) => Promise<void>;
  addProduct: (shopId: string, product: Omit<Product, 'id'>) => Promise<void>;
  updateProduct: (shopId: string, product: Product) => Promise<void>;
  deleteProduct: (shopId: string, productId: string) => Promise<void>;
  addBarber: (shopId: string, barber: Omit<Barber, 'id'>) => Promise<void>;
  updateBarber: (shopId: string, barber: Barber) => Promise<void>;
  deleteBarber: (shopId: string, barberId: string) => Promise<void>;
  updateShopDetails: (shopId: string, payload: Partial<BarberShop>) => Promise<void>;
  submitReview: (shopId: string, appointmentId: string, rating: number, comment: string) => Promise<void>;
  joinWaitlist: (shopId: string, serviceId: string, barberId: string, date: string) => Promise<boolean>;
  markNotificationRead: (id: string) => Promise<void>;
  refreshShops: () => Promise<void>;
  shopsReady: boolean;
  toasts: { id: string; message: string; type: 'info' | 'success' }[];
  removeToast: (id: string) => void;
};

const initialState: State = {
  user: undefined,
  users: mockUsers,
  shops: [],
  shopsReady: false,
  appointments: [],
  orders: [],
  cart: [],
  favorites: [],
  waitlists: [],
  notifications: [],
};

const AppContext = createContext<AppContextValue | undefined>(undefined);

export const AppProvider = ({ children }: { children: React.ReactNode }) => {
  const [loading, setLoading] = useState(true);
  const [toasts, setToasts] = useState<{ id: string; message: string; type: 'info' | 'success' }[]>([]);

  const addToast = (message: string, type: 'info' | 'success' = 'info') => {
    const id = nanoid();
    setToasts((prev) => [...prev, { id, message, type }]);

    try {
      const audio = new Audio('https://assets.mixkit.co/active_storage/sfx/2869/2869-120.wav');
      audio.volume = 0.4;
      audio.play().catch(() => {});
    } catch (e) {}

    if ('Notification' in window && Notification.permission === 'granted') {
      new Notification('Smart Agenda', { body: message });
    }

    setTimeout(() => {
      setToasts((prev) => prev.filter((t) => t.id !== id));
    }, 6000);
  };

  const removeToast = (id: string) => {
    setToasts((prev) => prev.filter((t) => t.id !== id));
  };

  useEffect(() => {
    if ('Notification' in window && Notification.permission === 'default') {
      Notification.requestPermission();
    }
  }, []);

  const [state, setState] = useState<State>(() => {
    const stored = storage.get<Partial<State> | null>('smart-agenda', null);
    const safeStored = stored && typeof stored === 'object' ? stored : {};
    const safeUsers = Array.isArray(safeStored.users) ? safeStored.users : initialState.users;
    const safeAppointments = Array.isArray(safeStored.appointments) ? safeStored.appointments : initialState.appointments;
    const safeOrders = Array.isArray(safeStored.orders) ? safeStored.orders : initialState.orders;
    const safeCart = Array.isArray(safeStored.cart) ? safeStored.cart : initialState.cart;
    const safeFavorites = Array.isArray(safeStored.favorites) ? safeStored.favorites : initialState.favorites;
    const safeUser = safeStored.user && typeof safeStored.user === 'object' ? safeStored.user : undefined;

    return {
      ...initialState,
      ...safeStored,
      user: safeUser,
      users: safeUsers,
      shops: [],
      appointments: safeAppointments,
      orders: safeOrders,
      cart: safeCart,
      favorites: safeFavorites,
      waitlists: [],
      notifications: [],
    };
  });

  const refreshShops = async () => {
    try {
      const { data: shopsData, error: shopsError } = await supabase.from('shops').select('*');
      if (shopsError || !shopsData) {
        setState((s) => ({ ...s, shopsReady: true }));
        return;
      }

      const { data: servicesData } = await supabase.from('services').select('*');
      const { data: barbersData } = await supabase.from('barbers').select('*');
      const { data: productsData } = await supabase.from('products').select('*');
      const { data: appointmentsData } = await supabase.from('appointments').select('*');
      const { data: ordersData } = await supabase.from('orders').select('*');
      const { data: waitlistData } = await supabase.from('waitlist').select('*');
      const { data: notificationsData } = await supabase.from('notifications').select('*');
      const { data: reviewsData } = await supabase.from('reviews').select('shop_id, rating');
      const { data: profilesData } = await supabase.from('profiles').select('id, name, role, shop_id');

      const formattedUsers: User[] = (profilesData ?? []).map((u) => ({
        id: u.id,
        name: u.name || 'Cliente',
        email: '',
        password: '',
        role: (u.role === 'barbearia' ? 'barbearia' : 'cliente') as 'cliente' | 'barbearia',
        shopId: u.shop_id || undefined,
      }));

      const fetchedShops: BarberShop[] = shopsData.map((shop) => {
        const shopReviews = (reviewsData ?? []).filter(r => r.shop_id === shop.id);
        const avgRating = shopReviews.length > 0 
          ? shopReviews.reduce((sum, r) => sum + r.rating, 0) / shopReviews.length 
          : (shop.rating ?? 0);

        return {
          id: shop.id,
          name: shop.name,
          address: shop.address ?? '',
          rating: avgRating,
          imageUrl: shop.image_url ?? shop.imageUrl ?? undefined,
          schedule: shop.schedule,
          paymentMethods: shop.payment_methods,
          socialNetworks: shop.social_networks,
          contacts: shop.contacts,
          ownerId: shop.owner_id || shop.ownerId || undefined,
          services: (servicesData ?? [])
          .filter((s) => s.shop_id === shop.id)
          .map((s) => ({
            id: s.id,
            name: s.name,
            price: s.price ?? 0,
            duration: s.duration ?? 30,
            barberIds: s.barber_ids ?? [],
          })),
        products: (productsData ?? [])
          .filter((p) => p.shop_id === shop.id)
          .map((p) => ({
            id: p.id,
            name: p.name,
            price: p.price ?? 0,
            stock: p.stock ?? 0,
          })),
        barbers: (barbersData ?? [])
          .filter((b) => b.shop_id === shop.id)
          .map((b) => ({
            id: b.id,
            name: b.name,
            imageUrl: b.image_url ?? undefined,
            specialties: b.specialties ?? [],
            schedule: b.schedule ?? [],
          })),
        };
      });

      const formattedAppointments: Appointment[] = (appointmentsData ?? []).map((a) => ({
        id: a.id,
        shopId: a.shop_id,
        serviceId: a.service_id,
        barberId: a.barber_id,
        customerId: a.customer_id,
        date: a.date,
        status: a.status as AppointmentStatus,
        total: a.total,
      }));

      const formattedOrders: Order[] = (ordersData ?? []).map((o) => ({
        id: o.id,
        shopId: o.shop_id,
        customerId: o.customer_id,
        items: o.items,
        total: o.total,
        status: o.status as Order['status'],
        createdAt: o.created_at,
      }));

      const formattedWaitlists: WaitlistEntry[] = (waitlistData ?? []).map((w) => ({
        id: w.id,
        shopId: w.shop_id,
        serviceId: w.service_id,
        barberId: w.barber_id,
        customerId: w.customer_id,
        date: w.date,
        status: w.status as any,
        createdAt: w.created_at,
      }));

      const formattedNotifications: AppNotification[] = (notificationsData ?? []).map((n) => ({
        id: n.id,
        userId: n.user_id,
        message: n.message,
        read: n.read,
        createdAt: n.created_at,
      }));

      setState((s) => {
        // A BD é agora a única fonte de verdade.
        // Como o CRUD já insere na BD antes do refresh, a sobreposição com 'localVersion' foi 
        // eliminada para impedir a supressão das queries que vêm da Base de Dados.
        const mergedShops: BarberShop[] = [...fetchedShops];

        // Se a loja do utilizador NÃO está na BD (novo registo ainda não guardado),
        // adicionar apenas essa loja da memória local — SEM adicionar outras.
        const userShopId = s.user?.shopId;
        const userShopInDb = userShopId && fetchedShops.some(fs => fs.id === userShopId);
        if (userShopId && !userShopInDb) {
          const localUserShop = s.shops.find(ls => ls.id === userShopId);
          if (localUserShop) mergedShops.push(localUserShop);
        }

        // Deduplicar por ID para garantir que nunca há duas lojas iguais
        const seen = new Set<string>();
        const dedupedShops = mergedShops.filter(sh => {
          if (seen.has(sh.id)) return false;
          seen.add(sh.id);
          return true;
        });

        const mergedUsers = [...formattedUsers];
        s.users.forEach((localUser) => {
          if (!mergedUsers.some((u) => u.id === localUser.id)) {
            mergedUsers.push(localUser);
          }
        });

        return { 
          ...s, 
          users: mergedUsers,
          shops: dedupedShops, 
          appointments: formattedAppointments, 
          orders: formattedOrders, 
          waitlists: formattedWaitlists,
          notifications: formattedNotifications,
          shopsReady: true 
        };
      });
    } catch (err) {
      console.error('refreshShops error:', err);
      setState((s) => ({ ...s, shopsReady: true }));
    }
  };

  useEffect(() => {
    storage.set('smart-agenda', state);
  }, [state]);

  useEffect(() => {
    let mounted = true;

    const clearUser = () => {
      setState((s) => ({ ...s, user: undefined }));
    };

    const applyProfile = async (userId: string, email?: string | null, userMetadata?: any) => {
      const { data, error } = await supabase
        .from('profiles')
        .select('id,name,role,shop_name,shop_id')
        .eq('id', userId)
        .single();

      if (!mounted) return;
      if (error || !data) {
        clearUser();
        return;
      }

      const role = data.role === 'barbearia' ? 'barbearia' : 'cliente';
      const displayName = data.name?.trim() || (email ? email.split('@')[0] : 'Utilizador');

      let shopId: string | undefined = undefined;

      // O trigger de backend já popula a tabela profiles com o shop_id quando é barbearia
      if (role === 'barbearia') {
        shopId = data.shop_id || userId; // Fallback extremo se o trigger falhar
      }

      let needsInsert = false;
      let shopNameToInsert = '';

      setState((s) => {
        const nextUser: User = {
          id: userId,
          name: displayName,
          email: email ?? '',
          password: '',
          role,
          shopId,
        };

        const users = s.users.some((u) => u.id === userId)
          ? s.users.map((u) => (u.id === userId ? { ...u, ...nextUser } : u))
          : [...s.users, nextUser];

        let shops = s.shops;
        if (shopId) {
          const exists = shops.some((shop) => shop.id === shopId);
          if (!exists) {
            shopNameToInsert = data.shop_name?.trim() || userMetadata?.shopName?.trim() || `Barbearia de ${displayName}`;
            needsInsert = true;
            const newShop: BarberShop = {
              id: shopId,
              name: shopNameToInsert,
              address: 'Endereço a definir',
              rating: 0,
              barbers: [],
              services: [],
              products: [],
            };
            shops = [...shops, newShop];
          }
        }

        return { ...s, user: nextUser, users, shops };
      });

      // Inserir na BD se necessário (fora do setState)
      if (needsInsert && shopId) {
        const { error: insertErr } = await supabase.from('shops').upsert([{
          id: shopId,
          owner_id: userId, // Garante que fica associada ao utilizador se for fallback
          name: shopNameToInsert,
          address: 'Endereço a definir',
          rating: 0,
        }]);
        if (insertErr) {
          console.error('Erro ao inserir/atualizar shop inicial:', insertErr);
        }
      }
    };

    // Usa onAuthStateChange que dispara INITIAL_SESSION automaticamente
    // Evita duplicação com getSession() separado
    const { data: sub } = supabase.auth.onAuthStateChange((event, session) => {
      if (!mounted) return;

      // Liberta o loading imediatamente ao primeiro evento de auth
      // para não bloquear a app enquanto os dados carregam
      setLoading(false);

      if (session?.user) {
        applyProfile(session.user.id, session.user.email, session.user.user_metadata)
          .then(() => { if (mounted) refreshShops(); })
          .catch(console.error);
      } else {
        clearUser();
        refreshShops().catch(console.error);
      }
    });

    // Fallback: se o onAuthStateChange não disparar em 5s, liberta o loading
    const fallback = setTimeout(() => {
      if (mounted) setLoading(false);
    }, 5000);

    return () => {
      mounted = false;
      clearTimeout(fallback);
      sub.subscription.unsubscribe();
    };
  }, []);

  useEffect(() => {
    const channel = supabase
      .channel('db-changes')
      .on(
        'postgres_changes',
        { event: '*', schema: 'public', table: 'appointments' },
        () => {
          refreshShops();
        }
      )
      .on(
        'postgres_changes',
        { event: '*', schema: 'public', table: 'orders' },
        () => {
          refreshShops();
        }
      );

    if (state.user?.id) {
      channel.on(
        'postgres_changes',
        {
          event: 'INSERT',
          schema: 'public',
          table: 'notifications',
          filter: `user_id=eq.${state.user.id}`,
        },
        (payload) => {
          addToast(payload.new.message, 'info');
          refreshShops();
        }
      );
    }

    channel.subscribe();

    return () => {
      supabase.removeChannel(channel);
    };
  }, [state.user?.id]);

  const login = (email: string, password: string) => {
    const found = state.users.find((u) => u.email === email && u.password === password);
    if (found) {
      setState((s) => ({ ...s, user: found }));
      return true;
    }
    return false;
  };

  const logout = () => {
    setState((s) => ({ ...s, user: undefined }));
    supabase.auth.signOut().catch(console.error);
  };

  const toggleFavorite = (shopId: string) => {
    setState((s) => {
      const exists = s.favorites.includes(shopId);
      return {
        ...s,
        favorites: exists ? s.favorites.filter((id) => id !== shopId) : [...s.favorites, shopId],
      };
    });
  };

  const isFavorite = (shopId: string) => (state.favorites ?? []).includes(shopId);

  const register: AppContextValue['register'] = ({ shopName, ...payload }) => {
    const exists = state.users.some((u) => u.email === payload.email);
    if (exists) return false;

    if (payload.role === 'barbearia') {
      const userId = nanoid();
      const shopId = userId;
      const shop: BarberShop = {
        id: shopId,
        name: shopName || `Barbearia ${payload.name}`,
        address: 'Endereço a definir',
        rating: 0,
        barbers: [],
        services: [],
        products: [],
      };
      const user: User = { ...payload, id: userId, role: 'barbearia', shopId };
      setState((s) => ({ ...s, user, users: [...s.users, user], shops: [...s.shops, shop] }));
      return true;
    }

    const user: User = { ...payload, id: nanoid(), role: 'cliente' };
    setState((s) => ({ ...s, user, users: [...s.users, user] }));
    return true;
  };

  const addToCart: AppContextValue['addToCart'] = (item) => {
    if (item.type === 'product') {
      const shop = state.shops.find((shp) => shp.id === item.shopId);
      const prod = shop?.products.find((p) => p.id === item.refId);
      if (prod) {
        const maxStock = prod.stock;
        const existingItem = state.cart.find((c) => c.refId === item.refId && c.type === 'product' && c.shopId === item.shopId);
        const currentQty = existingItem ? existingItem.qty : 0;

        if (currentQty >= maxStock) {
          addToast(`Não é possível adicionar mais unidades. Apenas ${maxStock} unidades em stock.`, 'info');
          return;
        }

        if (currentQty + item.qty > maxStock) {
          const allowedQty = maxStock - currentQty;
          setState((s) => {
            const cart = [...s.cart];
            const idx = cart.findIndex((c) => c.refId === item.refId && c.type === item.type && c.shopId === item.shopId);
            if (idx >= 0) cart[idx].qty = maxStock;
            else cart.push({ ...item, qty: allowedQty });
            return { ...s, cart };
          });
          addToast(`Adicionado apenas ${allowedQty} unidades. Limite de stock atingido.`, 'info');
          return;
        }
      }
    }

    setState((s) => {
      const cart = [...s.cart];
      const idx = cart.findIndex((c) => c.refId === item.refId && c.type === item.type && c.shopId === item.shopId);
      if (idx >= 0) cart[idx].qty += item.qty;
      else cart.push(item);
      return { ...s, cart };
    });
  };

  const removeFromCart: AppContextValue['removeFromCart'] = (refId) => {
    setState((s) => ({ ...s, cart: s.cart.filter((c) => c.refId !== refId) }));
  };

  const clearCart = () => setState((s) => ({ ...s, cart: [] }));

  const createAppointment: AppContextValue['createAppointment'] = async (input) => {
    const shop = state.shops.find((s) => s.id === input.shopId);
    if (!shop) return null;
    const svc = shop.services.find((s) => s.id === input.serviceId);
    if (!svc) return null;

    const exists = state.appointments.find(
      (ap) => ap.barberId === input.barberId && ap.date === input.date && ap.status !== 'cancelado'
    );
    if (exists) return null;

    const { data: newRow, error } = await supabase.from('appointments').insert([
      {
        shop_id: input.shopId,
        service_id: input.serviceId,
        barber_id: input.barberId,
        customer_id: input.customerId,
        date: input.date,
        status: 'pendente',
        total: svc.price
      }
    ]).select().single();

    if (error || !newRow) {
      console.error("Erro ao criar marcação na BD:", error);
      return null;
    }

    const shopOwnerId = shop.ownerId || shop.id;
    const clientName = state.user?.name || 'Um cliente';
    await supabase.from('notifications').insert([
      {
        user_id: shopOwnerId,
        message: `${clientName} solicitou um novo agendamento para o dia ${input.date}!`
      }
    ]);

    await refreshShops();

    return {
      id: newRow.id,
      shopId: newRow.shop_id,
      serviceId: newRow.service_id,
      barberId: newRow.barber_id,
      customerId: newRow.customer_id,
      date: newRow.date,
      status: newRow.status as AppointmentStatus,
      total: newRow.total
    };
  };

  const placeOrder: AppContextValue['placeOrder'] = async (customerId, onlyShopId) => {
    if (!state.cart.length) return null;
    const grouped = state.cart.reduce<Record<string, CartItem[]>>((acc, item) => {
      acc[item.shopId] = acc[item.shopId] || [];
      acc[item.shopId].push(item);
      return acc;
    }, {});

    const entries = Object.entries(grouped).filter(([shopId]) => (onlyShopId ? shopId === onlyShopId : true));

    const newOrders = await Promise.all(entries.map(async ([shopId, items]) => {
      const total = items.reduce((sum, item) => {
        const shop = state.shops.find((s) => s.id === item.shopId);
        if (!shop) return sum;
        const price =
          item.type === 'service'
            ? shop.services.find((s) => s.id === item.refId)?.price ?? 0
            : shop.products.find((p) => p.id === item.refId)?.price ?? 0;
        return sum + price * item.qty;
      }, 0);

      const dbOrder = {
        shop_id: shopId,
        customer_id: customerId,
        items: items,
        total: total,
        status: 'pendente'
      };

      const { data, error } = await supabase.from('orders').insert([dbOrder]).select().single();

      if (error || !data) {
        console.error("Erro ao criar encomenda na BD:", error);
        return null;
      }

      const shop = state.shops.find((s) => s.id === shopId);
      if (shop) {
        const shopOwnerId = shop.ownerId || shop.id;
        const clientName = state.user?.name || 'Um cliente';
        await supabase.from('notifications').insert([
          {
            user_id: shopOwnerId,
            message: `${clientName} fez um novo pedido de produto no valor de €${total.toFixed(2)}!`
          }
        ]);
      }

      return {
        id: data.id,
        shopId: data.shop_id,
        customerId: data.customer_id,
        items: data.items,
        total: data.total,
        status: data.status,
        createdAt: data.created_at
      } as Order;
    }));

    const successfulOrders = newOrders.filter((o): o is Order => o !== null);

    if (successfulOrders.length > 0) {
      await refreshShops(); // Refresh app state to include new orders
      setState((s) => ({ ...s, cart: [] }));
      return successfulOrders[0];
    }

    return null;
  };

  const updateAppointmentStatus: AppContextValue['updateAppointmentStatus'] = async (id, status) => {
    const apt = state.appointments.find(a => a.id === id);
    const { error } = await supabase.from('appointments').update({ status }).eq('id', id);
    if (error) {
      console.error("Erro ao atualizar status da marcação:", error);
      return;
    }

    if (status === 'cancelado' && apt) {
      const waitlistDate = apt.date.split(' ')[0]; // Extract YYYY-MM-DD
      const waitingUsers = state.waitlists.filter(w => w.barberId === apt.barberId && w.date === waitlistDate && w.status === 'pending');
      
      if (waitingUsers.length > 0) {
        const notificationsToInsert = waitingUsers.map(w => ({
          user_id: w.customerId,
          message: `Surgiu uma vaga no horário que pretendia a ${waitlistDate} às ${apt.date.split(' ')[1]}! Corra para fazer a reserva.`
        }));
        
        await supabase.from('notifications').insert(notificationsToInsert);
        
        const waitlistIds = waitingUsers.map(w => w.id);
        await supabase.from('waitlist').update({ status: 'notified' }).in('id', waitlistIds);
      }
    }
    
    await refreshShops();
  };

  const updateOrderStatus: AppContextValue['updateOrderStatus'] = async (id, status) => {
    const { error } = await supabase.from('orders').update({ status }).eq('id', id);
    if (error) {
      console.error("Erro ao atualizar status da encomenda:", error);
      return;
    }
    await refreshShops();
  };

  const addService: AppContextValue['addService'] = async (shopId, service) => {
    const { error } = await supabase.from('services').insert([
      { shop_id: shopId, name: service.name, price: service.price, duration: service.duration }
    ]);
    if (error) {
      console.error("Erro addService:", error);
      alert(`Erro ao guardar serviço: ${error.message}`);
    } else await refreshShops();
  };

  const updateService: AppContextValue['updateService'] = async (shopId, service) => {
    const { error } = await supabase.from('services').update({
      name: service.name, price: service.price, duration: service.duration
    }).eq('id', service.id);
    if (error) console.error("Erro updateService:", error);
    else await refreshShops();
  };

  const deleteService: AppContextValue['deleteService'] = async (shopId, serviceId) => {
    const { error } = await supabase.from('services').delete().eq('id', serviceId);
    if (error) console.error("Erro deleteService:", error);
    else await refreshShops();
  };

  const addProduct: AppContextValue['addProduct'] = async (shopId, product) => {
    const { error } = await supabase.from('products').insert([
      { shop_id: shopId, name: product.name, price: product.price, stock: product.stock }
    ]);
    if (error) {
      console.error("Erro addProduct:", error);
      alert(`Erro ao guardar produto: ${error.message}`);
    } else await refreshShops();
  };

  const updateProduct: AppContextValue['updateProduct'] = async (shopId, product) => {
    const { error } = await supabase.from('products').update({
      name: product.name, price: product.price, stock: product.stock
    }).eq('id', product.id);
    if (error) console.error("Erro updateProduct:", error);
    else await refreshShops();
  };

  const deleteProduct: AppContextValue['deleteProduct'] = async (shopId, productId) => {
    const { error } = await supabase.from('products').delete().eq('id', productId);
    if (error) console.error("Erro deleteProduct:", error);
    else await refreshShops();
  };

  const addBarber: AppContextValue['addBarber'] = async (shopId, barber) => {
    const { error } = await supabase.from('barbers').insert([
      { shop_id: shopId, name: barber.name, specialties: barber.specialties, image_url: barber.imageUrl }
    ]);
    if (error) {
      console.error("Erro addBarber:", error);
      alert(`Erro ao guardar barbeiro: ${error.message}`);
    } else await refreshShops();
  };

  const updateBarber: AppContextValue['updateBarber'] = async (shopId, barber) => {
    const { error } = await supabase.from('barbers').update({
      name: barber.name, specialties: barber.specialties, image_url: barber.imageUrl
    }).eq('id', barber.id);
    if (error) console.error("Erro updateBarber:", error);
    else await refreshShops();
  };

  const deleteBarber: AppContextValue['deleteBarber'] = async (shopId, barberId) => {
    const { error } = await supabase.from('barbers').delete().eq('id', barberId);
    if (error) console.error("Erro deleteBarber:", error);
    else await refreshShops();
  };

  const updateShopDetails: AppContextValue['updateShopDetails'] = async (shopId, payload) => {
    const { services, products, barbers, id: _id, imageUrl, paymentMethods, socialNetworks, ...dbPayload } = payload as any;

    // Usar upsert em vez de update para contornar a política de RLS que bloqueia UPDATEs.
    // Incluir os dados existentes da loja para não sobrescrever campos com null.
    const currentShop = state.shops.find(s => s.id === shopId);

    // O backend usa image_url, não imageUrl. Se existir novo no payload usa, senão fallback para o atual.
    const resolvedImageUrl = imageUrl ?? currentShop?.imageUrl;

    const updateData: Record<string, any> = { ...dbPayload };
    if (resolvedImageUrl !== undefined) updateData.image_url = resolvedImageUrl;
    if (paymentMethods !== undefined) updateData.payment_methods = paymentMethods;
    if (socialNetworks !== undefined) updateData.social_networks = socialNetworks;
    if (!updateData.name) updateData.name = currentShop?.name || 'Barbearia';
    if (!updateData.address && dbPayload.address !== undefined) updateData.address = dbPayload.address;

    const { error } = await supabase.from('shops').update(updateData).eq('id', shopId);

    if (error) {
      console.error('ERRO SUPABASE updateShopDetails:', error);
      alert(`Erro na gravação (Supabase): ${error.message}`);
    } else if (payload.name) {
      // Sincroniza o nome com a tabela profiles
      const { error: profileError } = await supabase.from('profiles').update({ shop_name: payload.name }).eq('id', shopId);
      if (profileError) {
        console.error('ERRO PERFIL updateShopDetails:', profileError);
      }
    }

    // Sempre atualiza o estado local também
    setState((s) => ({
      ...s,
      shops: s.shops.map((shop) => (shop.id === shopId ? { ...shop, ...payload } : shop)),
    }));
  };

  const joinWaitlist: AppContextValue['joinWaitlist'] = async (shopId, serviceId, barberId, date) => {
    if (!state.user) return false;
    const { error } = await supabase.from('waitlist').insert([{
      shop_id: shopId,
      service_id: serviceId,
      barber_id: barberId,
      customer_id: state.user.id,
      date,
      status: 'pending'
    }]);
    if (error) {
      console.error('Erro ao entrar na lista de espera:', error);
      return false;
    }
    await refreshShops();
    return true;
  };

  const markNotificationRead: AppContextValue['markNotificationRead'] = async (id) => {
    const { error } = await supabase.from('notifications').update({ read: true }).eq('id', id);
    if (error) console.error("Erro ao marcar notificação como lida:", error);
    else await refreshShops();
  };

  const submitReview = async (shopId: string, appointmentId: string, rating: number, comment: string) => {
    const { data: authData } = await supabase.auth.getUser();
    const customerId = authData?.user?.id;
    if (!customerId) { alert('Sess\u00e3o expirada. Faz login novamente.'); return; }

    const { error } = await supabase.from('reviews').insert([{
      shop_id: shopId,
      customer_id: customerId,
      appointment_id: appointmentId,
      rating,
      comment: comment.trim() || null,
    }]);

    if (error) {
      console.error('Erro submitReview:', error);
      throw new Error(error.message);
    }
    await refreshShops();
  };

  const value: AppContextValue = {
    ...state,
    login,
    logout,
    toggleFavorite,
    isFavorite,
    register,
    addToCart,
    removeFromCart,
    clearCart,
    createAppointment,
    placeOrder,
    updateAppointmentStatus,
    updateOrderStatus,
    addService,
    updateService,
    deleteService,
    addProduct,
    updateProduct,
    deleteProduct,
    addBarber,
    updateBarber,
    deleteBarber,
    updateShopDetails,
    submitReview,
    joinWaitlist,
    markNotificationRead,
    refreshShops,
    toasts,
    removeToast,
  };

  if (loading) {
    return (
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: '100vh', background: '#f8fafc' }}>
        <div style={{ textAlign: 'center' }}>
          <div style={{
            width: 48, height: 48, border: '4px solid #e2e8f0', borderTopColor: '#6366f1',
            borderRadius: '50%', animation: 'spin 0.8s linear infinite', margin: '0 auto 16px'
          }} />
          <p style={{ color: '#64748b', fontSize: 14 }}>A carregar...</p>
        </div>
        <style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>
      </div>
    );
  }

  return <AppContext.Provider value={value}>{children}</AppContext.Provider>;
};

export const useApp = () => {
  const ctx = useContext(AppContext);
  if (!ctx) throw new Error('useApp deve ser usado dentro de AppProvider');
  return ctx;
};
