import bcrypt from "bcryptjs";
import { connectDb, disconnectDb } from "../src/db/mongoose";
import { createId } from "../src/db/ids";
import {
  User,
  City,
  Property,
  PropertyUpdate,
  Booking,
  Review,
  Favorite,
  Notification,
  ExchangeRate,
  AppSetting,
} from "../src/db/models";
import type { Role } from "../src/db/types";
import { TUNISIA_CITIES } from "../src/data/tunisiaCities";

import { stayImage } from "../src/data/localMedia";

const IMAGE_POOL = [
  stayImage(0),
  stayImage(1),
  stayImage(2),
  stayImage(3),
  stayImage(0),
  stayImage(1),
  stayImage(2),
  stayImage(3),
];

const NEIGHBORHOODS: Record<string, { en: string[]; ar: string[] }> = {
  tunis: { en: ["Lac 2", "Mutuelleville", "Centre Ville"], ar: ["البحيرة 2", "الموتويلفيل", "وسط المدينة"] },
  "la-marsa": { en: ["Corniche", "Plage"], ar: ["الكورنيش", "الشاطئ"] },
  gammarth: { en: ["Beach road"], ar: ["طريق الشاطئ"] },
  hammamet: { en: ["Yasmine", "Medina"], ar: ["الياسمين", "المدينة العتيقة"] },
  nabeul: { en: ["Centre"], ar: ["الوسط"] },
  sousse: { en: ["Port El Kantaoui", "Boujaafar"], ar: ["القنطاوي", "بوجعفر"] },
  monastir: { en: ["Corniche"], ar: ["الكورنيش"] },
  mahdia: { en: ["Corniche"], ar: ["الكورنيش"] },
  sfax: { en: ["Sidi Mansour"], ar: ["سيدي منصور"] },
  djerba: { en: ["Houmt Souk", "Midoun"], ar: ["حومة السوق", "ميدون"] },
  tozeur: { en: ["Palm grove"], ar: ["واحة النخيل"] },
  bizerte: { en: ["Old Port"], ar: ["الميناء القديم"] },
  kairouan: { en: ["Medina"], ar: ["المدينة العتيقة"] },
  tabarka: { en: ["Port"], ar: ["الميناء"] },
};

async function main() {
  console.log("Seeding database...");
  await connectDb();
  const passwordHash = await bcrypt.hash("Password123!", 10);
  const adminPasswordHash = await bcrypt.hash("19992000", 10);

  const mongoose = (await import("mongoose")).default;
  const db = mongoose.connection.db;
  if (db) {
    const collections = await db.listCollections().toArray();
    for (const col of collections) {
      await db.collection(col.name).drop().catch(() => undefined);
    }
  }

  const admin = await User.create({
    email: "admin@safarlibya.com",
    fullName: "Safar Libya Admin",
    passwordHash: adminPasswordHash,
    role: "SUPER_ADMIN",
    status: "ACTIVE",
    locale: "ar",
    emailVerifiedAt: new Date(),
  });

  const owners: any[] = [];
  for (let i = 1; i <= 10; i++) {
    owners.push(
      await User.create({
        email: `owner${i}@safarlibya.com`,
        fullName: `Tunisia Host ${i}`,
        passwordHash,
        role: "OWNER" as Role,
        status: "ACTIVE",
        locale: i % 2 === 0 ? "en" : "ar",
        emailVerifiedAt: new Date(),
        phone: `+21620${String(100000 + i).slice(-6)}`,
      }),
    );
  }

  await User.updateOne(
    { _id: owners[0]._id },
    { $set: { email: "owner@safarlibya.com", fullName: "Tunisia Host" } },
  );
  owners[0].email = "owner@safarlibya.com";

  const customers: any[] = [];
  for (let i = 1; i <= 100; i++) {
    customers.push(
      await User.create({
        email: i === 1 ? "customer@safarlibya.com" : `customer${i}@safarlibya.com`,
        fullName: i === 1 ? "Libya Traveler" : `Customer ${i}`,
        passwordHash,
        role: "CUSTOMER",
        status: "ACTIVE",
        locale: i % 3 === 0 ? "en" : "ar",
        emailVerifiedAt: new Date(),
      }),
    );
  }

  const cities: any[] = [];
  for (const def of TUNISIA_CITIES) {
    cities.push(
      await City.create({
        nameEn: def.nameEn,
        nameAr: def.nameAr,
        slug: def.slug,
        country: "Tunisia",
        region: def.region,
        isTourist: def.isTourist,
        aliases: def.aliases,
        blurbEn: def.blurbEn,
        blurbAr: def.blurbAr,
        imageUrl: def.imageUrl,
      }),
    );
  }

  await ExchangeRate.create({
    fromCurrency: "TND",
    toCurrency: "LYD",
    rate: 1.52,
    updatedById: admin._id,
  });

  await AppSetting.create({
    key: "platform",
    value: { name: "Safar Libya", defaultLocale: "ar", supportEmail: "support@safarlibya.com" },
  });

  await AppSetting.findOneAndUpdate(
    { key: "commerce" },
    {
      $set: {
        value: {
          walletEnabled: true,
          loyaltyEnabled: true,
          couponsEnabled: true,
          pointsPerLyd: 1,
          tndPerPoint: 0.01,
          minRedeemPoints: 100,
          maxRedeemPercentOfSubtotal: 20,
          ownerRejectRefundPercent: 100,
          refundTiers: [
            { hoursBeforeCheckIn: 48, refundPercent: 100 },
            { hoursBeforeCheckIn: 24, refundPercent: 50 },
            { hoursBeforeCheckIn: 0, refundPercent: 0 },
          ],
        },
      },
    },
    { upsert: true },
  );

  const properties: any[] = [];
  for (let i = 1; i <= 56; i++) {
    const city = cities[(i - 1) % cities.length];
    const owner = owners[(i - 1) % owners.length];
    const bedrooms = (i % 3) + 1;
    const price = 120 + (i % 15) * 20;
    const hoods = NEIGHBORHOODS[city.slug] || { en: ["Centre"], ar: ["الوسط"] };
    const hoodEn = hoods.en[(i - 1) % hoods.en.length];
    const hoodAr = hoods.ar[(i - 1) % hoods.ar.length];
    const cityMeta = TUNISIA_CITIES.find((c) => c.slug === city.slug);
    const property = await Property.create({
      ownerId: owner._id,
      cityId: city._id,
      titleEn: `${bedrooms}-bedroom apartment in ${hoodEn}, ${city.nameEn}`,
      titleAr: `شقة ${
        bedrooms === 1 ? "غرفة واحدة" : bedrooms === 2 ? "غرفتان" : `${bedrooms} غرف`
      } في ${hoodAr}، ${city.nameAr}`,
      slug: `${city.slug}-stay-${i}`,
      descriptionEn: `Furnished ${bedrooms}-bedroom apartment in ${hoodEn}, ${city.nameEn}. Reliable Wi‑Fi, full kitchen, and AC — ideal for Libyan travelers on medical, study, or leisure trips. Close to shops and local transport.`,
      descriptionAr: `شقة مفروشة ${
        bedrooms === 1 ? "من غرفة نوم واحدة" : bedrooms === 2 ? "من غرفتي نوم" : `من ${bedrooms} غرف نوم`
      } في ${hoodAr}، ${city.nameAr}. واي فاي ومطبخ كامل وتكييف — مثالية للمسافرين الليبيين للعلاج أو الدراسة أو السياحة. قريبة من المحلات والمواصلات.`,
      address: `${10 + i} Rue ${hoodEn}, ${city.nameEn}, Tunisia`,
      latitude: (cityMeta?.lat ?? 36.8) + (i % 10) * 0.01,
      longitude: (cityMeta?.lng ?? 10.1) + (i % 10) * 0.01,
      status: "PUBLISHED",
      bedrooms,
      bathrooms: Math.max(1, bedrooms - 1),
      maxGuests: bedrooms * 2,
      wifi: true,
      parking: i % 2 === 0,
      airConditioning: true,
      kitchen: true,
      hospitalNearby: i % 3 === 0,
      universityNearby: i % 4 === 0,
      petFriendly: i % 5 === 0,
      instantBooking: i % 2 === 0,
      basePriceTnd: price,
      cleaningFeeTnd: 30 + (i % 5) * 5,
      cancellationPolicy: "Free cancellation within 48 hours of booking.",
      houseRules: "No smoking. No parties. Respect neighbors.",
      featured: i <= 8,
      images: [
        { _id: createId(), url: IMAGE_POOL[i % IMAGE_POOL.length], sortOrder: 0, createdAt: new Date() },
        {
          _id: createId(),
          url: IMAGE_POOL[(i + 1) % IMAGE_POOL.length],
          sortOrder: 1,
          createdAt: new Date(),
        },
        {
          _id: createId(),
          url: IMAGE_POOL[(i + 2) % IMAGE_POOL.length],
          sortOrder: 2,
          createdAt: new Date(),
        },
      ],
      videos:
        i % 7 === 0
          ? [
              {
                _id: createId(),
                url: "https://res.cloudinary.com/demo/video/upload/dog.mp4",
                sortOrder: 0,
                createdAt: new Date(),
              },
            ]
          : [],
    });
    properties.push(property);

    if (i <= 12) {
      await PropertyUpdate.create({
        propertyId: property._id,
        ownerId: owner._id,
        titleEn: "Host note for upcoming guests",
        titleAr: "ملاحظة المضيف للضيوف القادمين",
        bodyEn: `Check-in from 15:00 in ${hoodEn}. Supermarket and pharmacy are within a 5-minute walk. Message us for airport transfer tips.`,
        bodyAr: `تسجيل الوصول من الساعة 15:00 في ${hoodAr}. سوبرماركت وصيدلية على بعد 5 دقائق سيراً. راسلونا لنصائح النقل من المطار.`,
      });
    }
  }

  for (let i = 0; i < 20; i++) {
    const property = properties[i];
    const customer = customers[i % customers.length];
    const checkIn = new Date();
    checkIn.setDate(checkIn.getDate() + 7 + i);
    const checkOut = new Date(checkIn);
    checkOut.setDate(checkOut.getDate() + 3);
    const nights = 3;
    const subtotal = Number(property.basePriceTnd) * nights;
    const cleaning = Number(property.cleaningFeeTnd);
    const platform = Math.round((subtotal + cleaning) * 0.12 * 100) / 100;
    const taxes = Math.round((subtotal + cleaning) * 0.1 * 100) / 100;
    const totalTnd = Math.round((subtotal + cleaning + platform + taxes) * 100) / 100;
    const totalLyd = Math.round(totalTnd * 1.52 * 100) / 100;
    const status =
      i % 4 === 0
        ? "WAITING_OWNER"
        : i % 4 === 1
          ? "CONFIRMED"
          : i % 4 === 2
            ? "COMPLETED"
            : "PENDING_PAYMENT";

    const booking = await Booking.create({
      propertyId: property._id,
      customerId: customer._id,
      ownerId: property.ownerId,
      checkIn,
      checkOut,
      guests: 2,
      nights,
      status,
      exchangeRateRate: 1.52,
      exchangeRateLockedAt: new Date(),
      exchangeRateExpiresAt: new Date(Date.now() + 15 * 60 * 1000),
      subtotalTnd: subtotal,
      cleaningFeeTnd: cleaning,
      platformFeeTnd: platform,
      taxesTnd: taxes,
      discountTnd: 0,
      totalTnd,
      totalLyd,
      ownerPayoutTnd: subtotal + cleaning - platform,
      payment: {
        _id: createId(),
        provider: "DEMO",
        status: status === "PENDING_PAYMENT" ? "PENDING" : "PAID",
        amount: totalLyd,
        currency: "LYD",
        paidAt: status === "PENDING_PAYMENT" ? undefined : new Date(),
        createdAt: new Date(),
        updatedAt: new Date(),
      },
      invoice:
        status === "PENDING_PAYMENT"
          ? undefined
          : {
              _id: createId(),
              invoiceNumber: `INV-${new Date().getFullYear()}-${String(i + 1).padStart(5, "0")}`,
              total: totalLyd,
              currency: "LYD",
              issuedAt: new Date(),
              createdAt: new Date(),
              bookingId: undefined,
              guestName: customer.fullName,
              guestEmail: customer.email,
              guestPhone: customer.phone,
              propertyTitleAr: property.titleAr,
              propertyTitleEn: property.titleEn,
              propertyAddress: property.address,
              cityNameAr: undefined,
              cityNameEn: undefined,
              checkIn,
              checkOut,
              nights,
              guests: 2,
              nightlyRateTnd: Math.round((subtotal / nights) * 100) / 100,
              subtotalTnd: subtotal,
              cleaningFeeTnd: cleaning,
              platformFeeTnd: platform,
              taxesTnd: taxes,
              discountTnd: 0,
              totalTnd,
              totalLyd,
              exchangeRateRate: 1.52,
              paymentStatus: "PAID",
              paymentProvider: "DEMO",
              bookingStatus: status,
            },
    });

    if (status === "COMPLETED") {
      await Review.create({
        bookingId: booking._id,
        propertyId: property._id,
        authorId: customer._id,
        rating: 4 + (i % 2),
        comment: "Clean apartment, smooth booking experience with Safar Libya.",
      });
    }

    try {
      await Favorite.create({
        userId: customer._id,
        propertyId: properties[(i + 3) % properties.length]._id,
      });
    } catch {
      // ignore unique conflicts
    }

    await Notification.create({
      userId: customer._id,
      titleAr: "مرحباً بك في سفر ليبيا",
      titleEn: "Welcome to Safar Libya",
      messageAr: "حسابك جاهز للحجز والدفع بالدينار الليبي.",
      messageEn: "Your account is ready to book and pay in LYD.",
      link: "/dashboard/customer",
    });
  }

  console.log("Seed complete:", {
    admin: admin.email,
    adminPassword: "19992000",
    owners: owners.length,
    customers: customers.length,
    cities: cities.length,
    properties: properties.length,
    password: "Password123!",
  });
}

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