import { PrismaClient, AccountStatus, UserRole, WalletType } from '@prisma/client';
import bcrypt from 'bcrypt';

const prisma = new PrismaClient();

type RestaurantSeedInput = {
  email: string;
  phone: string;
  name: string;
  slug: string;
  documentNumber: string;
  description: string;
  city: string;
  neighborhood: string;
  latitude: number;
  longitude: number;
  logoUrl: string;
  coverImageUrl: string;
  categories: Array<{
    name: string;
    description: string;
    products: Array<{
      name: string;
      description: string;
      imageUrl: string;
      price: number;
    }>;
  }>;
};

async function resetRestaurantCatalog(restaurantId: string) {
  await prisma.deliveryRoute.deleteMany({ where: { order: { restaurantId } } });
  await prisma.delivery.deleteMany({ where: { order: { restaurantId } } });
  await prisma.transaction.deleteMany({ where: { payment: { order: { restaurantId } } } });
  await prisma.payment.deleteMany({ where: { order: { restaurantId } } });
  await prisma.orderItem.deleteMany({ where: { order: { restaurantId } } });
  await prisma.order.deleteMany({ where: { restaurantId } });
  await prisma.productVariation.deleteMany({ where: { product: { restaurantId } } });
  await prisma.productAdditional.deleteMany({ where: { product: { restaurantId } } });
  await prisma.product.deleteMany({ where: { restaurantId } });
  await prisma.productCategory.deleteMany({ where: { restaurantId } });
  await prisma.restaurantCategory.deleteMany({ where: { restaurantId } });
}

async function seedRestaurantCatalog(restaurantId: string, categories: RestaurantSeedInput['categories']) {
  for (const [categoryIndex, category] of categories.entries()) {
    const productCategory = await prisma.productCategory.create({
      data: {
        restaurantId,
        name: category.name,
        sortOrder: categoryIndex + 1,
      },
    });

    await prisma.restaurantCategory.create({
      data: {
        restaurantId,
        name: category.name,
        description: category.description,
      },
    });

    for (const [productIndex, product] of category.products.entries()) {
      const createdProduct = await prisma.product.create({
        data: {
          restaurantId,
          categoryId: productCategory.id,
          name: product.name,
          description: product.description,
          imageUrl: product.imageUrl,
          price: product.price,
          isActive: true,
        },
      });

      await prisma.productVariation.create({
        data: {
          productId: createdProduct.id,
          name: productIndex === 0 ? 'Destaque' : 'Tradicional',
          price: product.price,
        },
      });
    }
  }
}

async function main() {
  const passwordHash = await bcrypt.hash('Admin@123', 12);

  const admin = await prisma.user.upsert({
    where: { email: 'admin@chego.app' },
    update: {
      phone: '5511999999999',
      passwordHash,
      role: UserRole.SUPER_ADMIN,
      status: AccountStatus.ACTIVE,
      emailVerifiedAt: new Date(),
      phoneVerifiedAt: new Date(),
    },
    create: {
      email: 'admin@chego.app',
      phone: '5511999999999',
      passwordHash,
      role: UserRole.SUPER_ADMIN,
      status: AccountStatus.ACTIVE,
      emailVerifiedAt: new Date(),
      phoneVerifiedAt: new Date(),
    },
  });

  await prisma.setting.upsert({
    where: { key: 'platform' },
    update: { value: { appName: 'Chego', commissionDefault: 12.5 } },
    create: { key: 'platform', value: { appName: 'Chego', commissionDefault: 12.5 } },
  });

  await prisma.wallet.create({ data: { userId: admin.id, type: WalletType.PLATFORM, balance: 0 } }).catch(() => undefined);

  const restaurantUser = await prisma.user.upsert({
    where: { email: 'loja@chego.app' },
    update: {
      phone: '5511988887777',
      passwordHash,
      role: UserRole.RESTAURANT,
      status: AccountStatus.ACTIVE,
      emailVerifiedAt: new Date(),
      phoneVerifiedAt: new Date(),
    },
    create: {
      email: 'loja@chego.app',
      phone: '5511988887777',
      passwordHash,
      role: UserRole.RESTAURANT,
      status: AccountStatus.ACTIVE,
      emailVerifiedAt: new Date(),
      phoneVerifiedAt: new Date(),
    },
  });

  const driverUser = await prisma.user.upsert({
    where: { email: 'entregador@chego.app' },
    update: {
      phone: '5511977776666',
      passwordHash,
      role: UserRole.DRIVER,
      status: AccountStatus.ACTIVE,
      emailVerifiedAt: new Date(),
      phoneVerifiedAt: new Date(),
    },
    create: {
      email: 'entregador@chego.app',
      phone: '5511977776666',
      passwordHash,
      role: UserRole.DRIVER,
      status: AccountStatus.ACTIVE,
      emailVerifiedAt: new Date(),
      phoneVerifiedAt: new Date(),
    },
  });

  const customerUser = await prisma.user.upsert({
    where: { email: 'cliente@chego.app' },
    update: {
      phone: '5511966665555',
      passwordHash,
      role: UserRole.CUSTOMER,
      status: AccountStatus.ACTIVE,
      emailVerifiedAt: new Date(),
      phoneVerifiedAt: new Date(),
    },
    create: {
      email: 'cliente@chego.app',
      phone: '5511966665555',
      passwordHash,
      role: UserRole.CUSTOMER,
      status: AccountStatus.ACTIVE,
      emailVerifiedAt: new Date(),
      phoneVerifiedAt: new Date(),
    },
  });

  const restaurant = await prisma.restaurant.upsert({
    where: { userId: restaurantUser.id },
    update: {
      name: 'Forno da Esquina',
      slug: 'forno-da-esquina',
      documentNumber: '12345678000199',
      description: 'Restaurante demo para validar cardapio publico, pedidos e operacao da loja.',
      city: 'Sao Paulo',
      neighborhood: 'Centro',
      latitude: -23.55052,
      longitude: -46.633308,
      logoUrl: 'https://dummyimage.com/160x160/fff7ed/f97316.png&text=Forno',
      coverImageUrl: 'https://images.unsplash.com/photo-1513104890138-7c749659a591?auto=format&fit=crop&w=1600&q=80',
      isOpen: true,
      isPaused: false,
      status: AccountStatus.ACTIVE,
    },
    create: {
      userId: restaurantUser.id,
      name: 'Forno da Esquina',
      slug: 'forno-da-esquina',
      documentNumber: '12345678000199',
      description: 'Restaurante demo para validar cardapio publico, pedidos e operacao da loja.',
      city: 'Sao Paulo',
      neighborhood: 'Centro',
      latitude: -23.55052,
      longitude: -46.633308,
      logoUrl: 'https://dummyimage.com/160x160/fff7ed/f97316.png&text=Forno',
      coverImageUrl: 'https://images.unsplash.com/photo-1513104890138-7c749659a591?auto=format&fit=crop&w=1600&q=80',
      isOpen: true,
      isPaused: false,
      status: AccountStatus.ACTIVE,
    },
  });

  const driver = await prisma.driver.upsert({
    where: { userId: driverUser.id },
    update: {
      fullName: 'Mateus Entregas',
      documentNumber: '12345678900',
      vehiclePlate: 'CHE1G01',
      vehicleModel: 'Honda CG 160',
      pixKey: 'entregador@chego.app',
      status: AccountStatus.ACTIVE,
      isOnline: true,
    },
    create: {
      userId: driverUser.id,
      fullName: 'Mateus Entregas',
      documentNumber: '12345678900',
      vehiclePlate: 'CHE1G01',
      vehicleModel: 'Honda CG 160',
      pixKey: 'entregador@chego.app',
      status: AccountStatus.ACTIVE,
      isOnline: true,
    },
  });

  const customer = await prisma.customer.upsert({
    where: { userId: customerUser.id },
    update: {
      fullName: 'Camila Cliente',
    },
    create: {
      userId: customerUser.id,
      fullName: 'Camila Cliente',
    },
  });

  await prisma.wallet.upsert({
    where: { userId: restaurantUser.id },
    update: { restaurantId: restaurant.id, type: WalletType.RESTAURANT },
    create: { userId: restaurantUser.id, restaurantId: restaurant.id, type: WalletType.RESTAURANT, balance: 0 },
  });

  await prisma.wallet.upsert({
    where: { userId: driverUser.id },
    update: { driverId: driver.id, type: WalletType.DRIVER },
    create: { userId: driverUser.id, driverId: driver.id, type: WalletType.DRIVER, balance: 0 },
  });

  await prisma.wallet.upsert({
    where: { userId: customerUser.id },
    update: { customerId: customer.id, type: WalletType.CUSTOMER },
    create: { userId: customerUser.id, customerId: customer.id, type: WalletType.CUSTOMER, balance: 0 },
  });

  await prisma.driverLocation.deleteMany({ where: { driverId: driver.id } });
  await resetRestaurantCatalog(restaurant.id);
  await prisma.address.deleteMany({ where: { userId: customerUser.id } });
  await seedRestaurantCatalog(restaurant.id, [
    {
      name: 'Pizzas',
      description: 'Massas de longa fermentacao e ingredientes frescos.',
      products: [
        {
          name: 'Pizza Burrata da Casa',
          description: 'Massa de longa fermentacao, molho rustico, burrata fresca e pesto.',
          imageUrl: 'https://images.unsplash.com/photo-1513104890138-7c749659a591?auto=format&fit=crop&w=1200&q=80',
          price: 68.9,
        },
      ],
    },
    {
      name: 'Burgers',
      description: 'Lanches de alto giro para entrega rapida.',
      products: [
        {
          name: 'Burger Smoke Cheddar',
          description: 'Blend de costela, cheddar cremoso, cebola caramelizada e pao brioche.',
          imageUrl: 'https://images.unsplash.com/photo-1568901346375-23c9450c58cd?auto=format&fit=crop&w=1200&q=80',
          price: 42.9,
        },
      ],
    },
    {
      name: 'Combos',
      description: 'Ofertas para aumentar conversao no pedido publico.',
      products: [
        {
          name: 'Combo Almoco Executivo',
          description: 'Prato principal, bebida e sobremesa de giro rapido.',
          imageUrl: 'https://images.unsplash.com/photo-1544025162-d76694265947?auto=format&fit=crop&w=1200&q=80',
          price: 36.5,
        },
      ],
    },
  ]);

  const [pizza, burger, combo] = await prisma.product.findMany({
    where: { restaurantId: restaurant.id },
    orderBy: { createdAt: 'asc' },
    take: 3,
  });

  await prisma.productAdditional.createMany({
    data: [
      { productId: pizza.id, name: 'Borda recheada', price: 8 },
      { productId: burger.id, name: 'Bacon extra', price: 5 },
      { productId: combo.id, name: 'Sobremesa do dia', price: 7.5 },
    ],
  });

  await prisma.productVariation.createMany({
    data: [
      { productId: pizza.id, name: 'Grande', price: 68.9 },
      { productId: burger.id, name: 'Duplo', price: 42.9 },
      { productId: combo.id, name: 'Completo', price: 36.5 },
    ],
  });

  const extraRestaurants: RestaurantSeedInput[] = [
    {
      email: 'sushi@chego.app',
      phone: '5511987000001',
      name: 'Sushi do Porto',
      slug: 'sushi-do-porto',
      documentNumber: '22345678000199',
      description: 'Combinados, sashimis e pratos quentes com foco em imagem de produto.',
      city: 'Sao Paulo',
      neighborhood: 'Moema',
      latitude: -23.603363,
      longitude: -46.66896,
      logoUrl: 'https://dummyimage.com/160x160/ecfeff/0f766e.png&text=Sushi',
      coverImageUrl: 'https://images.unsplash.com/photo-1579871494447-9811cf80d66c?auto=format&fit=crop&w=1600&q=80',
      categories: [
        {
          name: 'Japonesa',
          description: 'Sushis, sashimis e combinados frios.',
          products: [
            {
              name: 'Combinado Premium 24 pecas',
              description: 'Selecao de niguiris, uramakis e sashimis para compartilhar.',
              imageUrl: 'https://images.unsplash.com/photo-1579871494447-9811cf80d66c?auto=format&fit=crop&w=1200&q=80',
              price: 74.9,
            },
            {
              name: 'Poke de Salmao',
              description: 'Arroz temperado, salmao fresco, avocado e crispy.',
              imageUrl: 'https://images.unsplash.com/photo-1547592180-85f173990554?auto=format&fit=crop&w=1200&q=80',
              price: 39.9,
            },
          ],
        },
      ],
    },
    {
      email: 'acai@chego.app',
      phone: '5511987000002',
      name: 'Acai da Praia',
      slug: 'acai-da-praia',
      documentNumber: '32345678000199',
      description: 'Tigelas geladas, sobremesas e combos doces para conversao por imagem.',
      city: 'Sao Paulo',
      neighborhood: 'Santana',
      latitude: -23.497774,
      longitude: -46.62529,
      logoUrl: 'https://dummyimage.com/160x160/f5f3ff/7c3aed.png&text=Acai',
      coverImageUrl: 'https://images.unsplash.com/photo-1563805042-7684c019e1cb?auto=format&fit=crop&w=1600&q=80',
      categories: [
        {
          name: 'Acai',
          description: 'Tigelas geladas com frutas e complementos.',
          products: [
            {
              name: 'Acai Cremoso 500 ml',
              description: 'Acai batido com banana, granola e leite condensado.',
              imageUrl: 'https://images.unsplash.com/photo-1563805042-7684c019e1cb?auto=format&fit=crop&w=1200&q=80',
              price: 24.9,
            },
            {
              name: 'Copo Trufado de Morango',
              description: 'Sobremesa gelada com creme, morango e ganache.',
              imageUrl: 'https://images.unsplash.com/photo-1488477181946-6428a0291777?auto=format&fit=crop&w=1200&q=80',
              price: 19.9,
            },
          ],
        },
      ],
    },
    {
      email: 'mexicano@chego.app',
      phone: '5511987000003',
      name: 'Taco de Rua',
      slug: 'taco-de-rua',
      documentNumber: '42345678000199',
      description: 'Tacos, burritos e bowls com visual forte para vitrine mobile.',
      city: 'Sao Paulo',
      neighborhood: 'Pinheiros',
      latitude: -23.567984,
      longitude: -46.692945,
      logoUrl: 'https://dummyimage.com/160x160/fef3c7/b45309.png&text=Taco',
      coverImageUrl: 'https://images.unsplash.com/photo-1552332386-f8dd00dc2f85?auto=format&fit=crop&w=1600&q=80',
      categories: [
        {
          name: 'Mexicana',
          description: 'Tacos, burritos e pratos montados.',
          products: [
            {
              name: 'Trio de Tacos de Costela',
              description: 'Tortillas artesanais, costela desfiada, pico de gallo e cheddar.',
              imageUrl: 'https://images.unsplash.com/photo-1552332386-f8dd00dc2f85?auto=format&fit=crop&w=1200&q=80',
              price: 32.9,
            },
            {
              name: 'Burrito Bowl Apimentado',
              description: 'Arroz, feijao preto, frango, guacamole e sour cream.',
              imageUrl: 'https://images.unsplash.com/photo-1513456852971-30c0b8199d4d?auto=format&fit=crop&w=1200&q=80',
              price: 34.9,
            },
          ],
        },
      ],
    },
  ];

  for (const seed of extraRestaurants) {
    const partnerUser = await prisma.user.upsert({
      where: { email: seed.email },
      update: {
        phone: seed.phone,
        passwordHash,
        role: UserRole.RESTAURANT,
        status: AccountStatus.ACTIVE,
        emailVerifiedAt: new Date(),
        phoneVerifiedAt: new Date(),
      },
      create: {
        email: seed.email,
        phone: seed.phone,
        passwordHash,
        role: UserRole.RESTAURANT,
        status: AccountStatus.ACTIVE,
        emailVerifiedAt: new Date(),
        phoneVerifiedAt: new Date(),
      },
    });

    const partnerRestaurant = await prisma.restaurant.upsert({
      where: { userId: partnerUser.id },
      update: {
        name: seed.name,
        slug: seed.slug,
        documentNumber: seed.documentNumber,
        description: seed.description,
        city: seed.city,
        neighborhood: seed.neighborhood,
        latitude: seed.latitude,
        longitude: seed.longitude,
        logoUrl: seed.logoUrl,
        coverImageUrl: seed.coverImageUrl,
        isOpen: true,
        isPaused: false,
        status: AccountStatus.ACTIVE,
      },
      create: {
        userId: partnerUser.id,
        name: seed.name,
        slug: seed.slug,
        documentNumber: seed.documentNumber,
        description: seed.description,
        city: seed.city,
        neighborhood: seed.neighborhood,
        latitude: seed.latitude,
        longitude: seed.longitude,
        logoUrl: seed.logoUrl,
        coverImageUrl: seed.coverImageUrl,
        isOpen: true,
        isPaused: false,
        status: AccountStatus.ACTIVE,
      },
    });

    await prisma.wallet.upsert({
      where: { userId: partnerUser.id },
      update: { restaurantId: partnerRestaurant.id, type: WalletType.RESTAURANT },
      create: { userId: partnerUser.id, restaurantId: partnerRestaurant.id, type: WalletType.RESTAURANT, balance: 0 },
    });

    await resetRestaurantCatalog(partnerRestaurant.id);
    await seedRestaurantCatalog(partnerRestaurant.id, seed.categories);
  }

  const address = await prisma.address.create({
    data: {
      userId: customerUser.id,
      label: 'Casa',
      street: 'Rua Vergueiro',
      number: '1543',
      complement: 'Apto 82',
      neighborhood: 'Vila Mariana',
      city: 'Sao Paulo',
      state: 'SP',
      zipCode: '04101-000',
      latitude: -23.589742,
      longitude: -46.634496,
      isDefault: true,
    },
  });

  const now = new Date();
  const minutesAgo = (minutes: number) => new Date(now.getTime() - minutes * 60 * 1000);

  const orderDelivered = await prisma.order.create({
    data: {
      customerId: customer.id,
      restaurantId: restaurant.id,
      addressId: address.id,
      status: 'DELIVERED',
      subtotal: 111.8,
      deliveryFee: 8.9,
      serviceFee: 2.5,
      discountAmount: 0,
      total: 123.2,
      notes: 'Pedido entregue com sucesso para validar historico real.',
      createdAt: minutesAgo(180),
      items: {
        create: [
          { productId: pizza.id, quantity: 1, unitPrice: 68.9, totalPrice: 68.9, notes: 'Sem azeitona' },
          { productId: burger.id, quantity: 1, unitPrice: 42.9, totalPrice: 42.9, notes: 'Ponto da carne ao ponto' },
        ],
      },
      payment: {
        create: {
          method: 'PIX',
          status: 'PAID',
          externalReference: 'PIX-DELIVERED-001',
          amount: 123.2,
          transactions: {
            create: [{ type: 'PIX_CAPTURE', amount: 123.2, metadata: { provider: 'manual-seed' } }],
          },
        },
      },
      delivery: {
        create: {
          driverId: driver.id,
          status: 'DELIVERED',
          distanceKm: 6.4,
          etaMinutes: 29,
          baseFee: 5,
          pricePerKm: 1.5,
          deliveryFeeCustomer: 8.9,
          driverEarning: 6.4,
          platformDeliveryProfit: 2.5,
          pickedUpAt: minutesAgo(145),
          deliveredAt: minutesAgo(128),
        },
      },
      deliveryRoute: {
        create: {
          driverId: driver.id,
          restaurantLatitude: restaurant.latitude,
          restaurantLongitude: restaurant.longitude,
          customerLatitude: address.latitude,
          customerLongitude: address.longitude,
          pickupDistanceKm: 1.2,
          deliveryDistanceKm: 5.2,
          estimatedPickupTime: 6,
          estimatedDeliveryTime: 23,
          status: 'DELIVERED',
        },
      },
    },
  });

  const orderOnTheWay = await prisma.order.create({
    data: {
      customerId: customer.id,
      restaurantId: restaurant.id,
      addressId: address.id,
      status: 'ON_THE_WAY',
      subtotal: 105.4,
      deliveryFee: 7.5,
      serviceFee: 2.1,
      discountAmount: 0,
      total: 115,
      notes: 'Pedido em rota para validar tracking ao vivo.',
      createdAt: minutesAgo(52),
      items: {
        create: [
          { productId: combo.id, quantity: 2, unitPrice: 36.5, totalPrice: 73, notes: 'Com bebida zero' },
          { productId: burger.id, quantity: 1, unitPrice: 42.9, totalPrice: 42.9, notes: 'Sem cebola' },
        ],
      },
      payment: {
        create: {
          method: 'PIX',
          status: 'PAID',
          externalReference: 'PIX-ONWAY-002',
          amount: 115,
          transactions: {
            create: [{ type: 'PIX_CAPTURE', amount: 115, metadata: { provider: 'manual-seed' } }],
          },
        },
      },
      delivery: {
        create: {
          driverId: driver.id,
          status: 'ON_THE_WAY',
          distanceKm: 4.7,
          etaMinutes: 14,
          baseFee: 5,
          pricePerKm: 1.5,
          deliveryFeeCustomer: 7.5,
          driverEarning: 5.5,
          platformDeliveryProfit: 2,
          pickedUpAt: minutesAgo(12),
        },
      },
      deliveryRoute: {
        create: {
          driverId: driver.id,
          restaurantLatitude: restaurant.latitude,
          restaurantLongitude: restaurant.longitude,
          customerLatitude: address.latitude,
          customerLongitude: address.longitude,
          pickupDistanceKm: 0.8,
          deliveryDistanceKm: 3.9,
          estimatedPickupTime: 4,
          estimatedDeliveryTime: 14,
          status: 'TO_CUSTOMER',
        },
      },
    },
  });

  const orderPickup = await prisma.order.create({
    data: {
      customerId: customer.id,
      restaurantId: restaurant.id,
      addressId: address.id,
      status: 'DRIVER_ACCEPTED',
      subtotal: 68.9,
      deliveryFee: 6.9,
      serviceFee: 1.8,
      discountAmount: 0,
      total: 77.6,
      notes: 'Pedido aguardando retirada para validar fluxo da loja e do entregador.',
      createdAt: minutesAgo(18),
      items: {
        create: [{ productId: pizza.id, quantity: 1, unitPrice: 68.9, totalPrice: 68.9, notes: 'Cortar em 8 fatias' }],
      },
      payment: {
        create: {
          method: 'PIX',
          status: 'PAID',
          externalReference: 'PIX-PICKUP-003',
          amount: 77.6,
          transactions: {
            create: [{ type: 'PIX_CAPTURE', amount: 77.6, metadata: { provider: 'manual-seed' } }],
          },
        },
      },
      delivery: {
        create: {
          driverId: driver.id,
          status: 'ACCEPTED',
          distanceKm: 3.2,
          etaMinutes: 10,
          baseFee: 5,
          pricePerKm: 1.5,
          deliveryFeeCustomer: 6.9,
          driverEarning: 5,
          platformDeliveryProfit: 1.9,
        },
      },
      deliveryRoute: {
        create: {
          driverId: driver.id,
          restaurantLatitude: restaurant.latitude,
          restaurantLongitude: restaurant.longitude,
          customerLatitude: address.latitude,
          customerLongitude: address.longitude,
          pickupDistanceKm: 1.1,
          deliveryDistanceKm: 2.1,
          estimatedPickupTime: 5,
          estimatedDeliveryTime: 10,
          status: 'TO_RESTAURANT',
        },
      },
    },
  });

  await prisma.driverLocation.createMany({
    data: [
      {
        driverId: driver.id,
        orderId: orderDelivered.id,
        latitude: -23.579742,
        longitude: -46.638,
        heading: 120,
        speed: 18,
        accuracy: 6,
        createdAt: minutesAgo(132),
      },
      {
        driverId: driver.id,
        orderId: orderOnTheWay.id,
        latitude: -23.582451,
        longitude: -46.636211,
        heading: 98,
        speed: 24,
        accuracy: 5,
        createdAt: minutesAgo(4),
      },
      {
        driverId: driver.id,
        orderId: orderPickup.id,
        latitude: -23.55312,
        longitude: -46.63245,
        heading: 45,
        speed: 12,
        accuracy: 4,
        createdAt: minutesAgo(2),
      },
    ],
  });
}

main()
  .then(async () => prisma.$disconnect())
  .catch(async (error) => {
    console.error(error);
    await prisma.$disconnect();
    process.exit(1);
  });
