# Dev seed data for testing pagination.
#
#     mix run priv/repo/dev_seeds.exs
#
# Creates enough records to exercise pagination in every admin and shop view.
# Safe to run multiple times — skips if data already exists.

alias Berrypod.Repo
alias Berrypod.Products
alias Berrypod.Products.{Product, ProductImage, ProductVariant, ProviderConnection}
alias Berrypod.Orders
alias Berrypod.Orders.{Order, OrderItem}
alias Berrypod.Media.Image
alias Berrypod.Newsletter
alias Berrypod.Redirects
alias Berrypod.Redirects.{Redirect, BrokenUrl}

import Ecto.Query

# ── Helpers ──

defmodule DevSeeds do
  @adj ~w[rustic vintage modern classic artisan handmade organic natural premium deluxe]
  @noun ~w[mug poster print tote hoodie tee cap sticker notebook candle]
  @colour ~w[crimson slate sage coral midnight forest amber ivory charcoal dusty-rose]
  @size ~w[XS S M L XL 2XL]

  @first_names ~w[Alice Bob Charlie Diana Ethan Fiona George Hannah Ivan Julia
                   Kevin Laura Mike Nora Oscar Penny Quinn Rosa Sam Tina]
  @last_names ~w[Smith Jones Brown Taylor Wilson Davies Evans Thomas Roberts Johnson
                  Walker White Harris Martin Thompson Garcia Martinez Robinson Clark Lewis]
  @domains ~w[gmail.com outlook.com yahoo.co.uk hotmail.com protonmail.com icloud.com]

  @campaign_subjects [
    "New arrivals just dropped",
    "Spring sale — 20% off everything",
    "Your exclusive early access",
    "Back in stock: fan favourites",
    "Free shipping this weekend only",
    "Our story so far",
    "Last chance: sale ends tonight",
    "Meet the maker",
    "Gift guide for every budget",
    "Something special is coming"
  ]

  def product_title(i) do
    adj = Enum.at(@adj, rem(i, length(@adj)))
    noun = Enum.at(@noun, rem(div(i, length(@adj)), length(@noun)))
    "#{String.capitalize(adj)} #{noun}"
  end

  def category(i) do
    cats = ["Apparel", "Homeware", "Stationery", "Accessories", "Art Prints"]
    Enum.at(cats, rem(i, length(cats)))
  end

  def colour(i), do: Enum.at(@colour, rem(i, length(@colour)))
  def size(i), do: Enum.at(@size, rem(i, length(@size)))

  def customer_email(i) do
    first = Enum.at(@first_names, rem(i, length(@first_names)))
    last = Enum.at(@last_names, rem(div(i, length(@first_names)), length(@last_names)))
    domain = Enum.at(@domains, rem(i, length(@domains)))
    "#{String.downcase(first)}.#{String.downcase(last)}@#{domain}"
  end

  def subscriber_email(i) do
    first = Enum.at(@first_names, rem(i, length(@first_names)))
    last = Enum.at(@last_names, rem(div(i + 3, length(@first_names)), length(@last_names)))
    domain = Enum.at(@domains, rem(i + 2, length(@domains)))
    "#{String.downcase(first)}.#{String.downcase(last)}+news@#{domain}"
  end

  def campaign_subject(i) do
    base = Enum.at(@campaign_subjects, rem(i, length(@campaign_subjects)))
    if i >= length(@campaign_subjects), do: "#{base} (#{div(i, length(@campaign_subjects)) + 1})", else: base
  end

  def random_price, do: Enum.random(999..4999)
  def random_cost(price), do: div(price, 2)
end

# ── Guard: skip if data already exists ──

existing_products = Repo.aggregate(Product, :count)

if existing_products >= 60 do
  IO.puts("Already have #{existing_products} products — skipping dev seeds.")
else
  # ── 1. Provider connection ──

  IO.puts("Creating provider connection...")

  conn =
    case Products.get_provider_connection_by_type("printify") do
      nil ->
        {:ok, c} =
          Products.create_provider_connection(%{
            provider_type: "printify",
            name: "Dev Printify Shop",
            api_key: "dev_test_key_123",
            config: %{"shop_id" => "dev_shop"}
          })
        c

      existing ->
        existing
    end

  # ── 2. Products (60 — enough for 3 pages at 25/page in admin, 3 pages at 24/page in shop) ──

  IO.puts("Creating 60 products with variants...")

  # Tiny placeholder image (1x1 white pixel WebP)
  pixel_webp =
    <<82, 73, 70, 70, 36, 0, 0, 0, 87, 69, 66, 80, 86, 80, 56, 32,
      16, 0, 0, 0, 48, 1, 0, 157, 1, 42, 1, 0, 1, 0, 1, 0, 52, 37,
      164, 0, 3, 112, 0, 254, 251, 148, 0, 0>>

  for i <- 0..59 do
    title = DevSeeds.product_title(i)
    slug = Slug.slugify(title) <> "-#{i}"
    price = DevSeeds.random_price()
    on_sale = rem(i, 7) == 0

    {:ok, product} =
      Products.create_product(%{
        provider_connection_id: conn.id,
        provider_product_id: "dev_prod_#{i}",
        title: title,
        description: "A lovely #{String.downcase(title)} for your collection. Hand-picked and quality-checked.",
        slug: slug,
        status: "active",
        visible: true,
        category: DevSeeds.category(i),
        cheapest_price: price,
        compare_at_price: if(on_sale, do: price + Enum.random(500..1500), else: nil),
        on_sale: on_sale,
        in_stock: rem(i, 20) != 0,
        provider_data: %{
          "options" => [
            %{"type" => "color", "name" => "Colour", "values" => [
              %{"title" => DevSeeds.colour(i), "colors" => ["#666"]},
              %{"title" => DevSeeds.colour(i + 1), "colors" => ["#999"]}
            ]},
            %{"type" => "size", "name" => "Size", "values" => [
              %{"title" => "S"}, %{"title" => "M"}, %{"title" => "L"}
            ]}
          ]
        }
      })

    # Create a product image (using a stored Image record)
    {:ok, img} =
      %Image{}
      |> Image.changeset(%{
        image_type: "product",
        filename: "#{slug}.webp",
        content_type: "image/webp",
        file_size: byte_size(pixel_webp),
        data: pixel_webp,
        source_width: 1,
        source_height: 1,
        variants_status: "complete",
        alt: title
      })
      |> Repo.insert()

    Products.create_product_image(%{
      product_id: product.id,
      src: "/images/#{img.id}/original",
      image_id: img.id,
      position: 0,
      alt: title
    })

    # Create 3 variants per product
    for size_idx <- 0..2 do
      size = DevSeeds.size(size_idx + 1)
      colour = DevSeeds.colour(i)
      variant_price = price + size_idx * 200

      Products.create_product_variant(%{
        product_id: product.id,
        provider_variant_id: "dev_var_#{i}_#{size_idx}",
        title: "#{size} / #{colour}",
        sku: "DEV-#{String.upcase(String.slice(slug, 0..5))}-#{size}",
        price: variant_price,
        compare_at_price: if(on_sale, do: variant_price + Enum.random(500..1500), else: nil),
        cost: DevSeeds.random_cost(variant_price),
        options: %{"Size" => size, "Colour" => colour},
        is_enabled: true,
        is_available: rem(i, 20) != 0
      })
    end

    if rem(i + 1, 20) == 0, do: IO.puts("  #{i + 1}/60 products...")
  end

  IO.puts("  60/60 products done.")

  # ── 3. Extra media images (enough to fill 2+ pages at 36/page = 80 total, minus the 60 product images) ──

  IO.puts("Creating 30 extra media images...")

  for i <- 0..29 do
    %Image{}
    |> Image.changeset(%{
      image_type: Enum.at(["media", "header", "icon"], rem(i, 3)),
      filename: "media-image-#{i}.webp",
      content_type: "image/webp",
      file_size: byte_size(pixel_webp),
      data: pixel_webp,
      source_width: 1,
      source_height: 1,
      variants_status: "complete",
      alt: "Media image #{i + 1}",
      tags: Enum.at(["banner", "promo", "lifestyle", "texture"], rem(i, 4))
    })
    |> Repo.insert!()
  end

  # ── 4. Orders (60 — enough for 3 pages at 25/page) ──

  IO.puts("Creating 60 orders...")

  statuses = ["paid", "paid", "paid", "pending", "failed", "refunded"]
  fulfilment_statuses = ["unfulfilled", "submitted", "processing", "shipped", "delivered"]

  for i <- 0..59 do
    email = DevSeeds.customer_email(i)
    price = DevSeeds.random_price()
    qty = Enum.random(1..3)
    subtotal = price * qty
    payment_status = Enum.at(statuses, rem(i, length(statuses)))

    now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second)
    # Spread orders over the last 90 days
    days_ago = 90 - div(i * 90, 60)
    inserted_at = NaiveDateTime.add(now, -days_ago * 86400, :second)

    order_attrs = %{
      order_number: "SS-260#{String.pad_leading("#{rem(200 + i, 300)}", 3, "0")}01-#{String.pad_leading("#{1000 + i}", 4, "0")}",
      subtotal: subtotal,
      shipping_cost: if(subtotal > 3000, do: 0, else: 399),
      total: subtotal + if(subtotal > 3000, do: 0, else: 399),
      currency: "gbp",
      customer_email: email,
      payment_status: payment_status,
      shipping_address: %{
        "name" => String.split(email, [".", "@"]) |> Enum.take(2) |> Enum.map(&String.capitalize/1) |> Enum.join(" "),
        "line1" => "#{Enum.random(1..200)} #{Enum.at(~w[High Oak Elm Mill Church Park], rem(i, 6))} Street",
        "city" => Enum.at(~w[London Manchester Bristol Edinburgh Cardiff Leeds], rem(i, 6)),
        "postal_code" => "#{Enum.at(~w[SW1A EC2R BS1 EH1 CF10 LS1], rem(i, 6))} #{Enum.random(1..9)}#{Enum.at(~w[AA AB BA BB], rem(i, 4))}",
        "country" => "GB"
      },
      fulfilment_status:
        if(payment_status == "paid",
          do: Enum.at(fulfilment_statuses, rem(i, length(fulfilment_statuses))),
          else: "unfulfilled"),
      inserted_at: inserted_at,
      updated_at: inserted_at
    }

    {:ok, order} =
      %Order{}
      |> Order.changeset(order_attrs)
      |> Repo.insert()

    # Create 1-2 line items
    for j <- 0..(qty - 1) do
      prod_idx = rem(i + j, 60)

      %OrderItem{}
      |> OrderItem.changeset(%{
        order_id: order.id,
        variant_id: "dev_var_#{prod_idx}_0",
        product_id: "dev_prod_#{prod_idx}",
        product_name: DevSeeds.product_title(prod_idx),
        variant_title: "M / #{DevSeeds.colour(prod_idx)}",
        quantity: 1,
        unit_price: price
      })
      |> Repo.insert!()
    end

    if rem(i + 1, 20) == 0, do: IO.puts("  #{i + 1}/60 orders...")
  end

  IO.puts("  60/60 orders done.")

  # ── 5. Newsletter subscribers (60 — enough for 3 pages at 25/page) ──

  IO.puts("Creating 60 newsletter subscribers...")

  now = DateTime.utc_now() |> DateTime.truncate(:second)

  for i <- 0..59 do
    email = DevSeeds.subscriber_email(i)
    status = Enum.at(["confirmed", "confirmed", "confirmed", "pending", "unsubscribed"], rem(i, 5))

    %Newsletter.Subscriber{}
    |> Newsletter.Subscriber.changeset(%{
      email: email,
      status: status,
      confirmed_at: if(status == "confirmed", do: now, else: nil),
      unsubscribed_at: if(status == "unsubscribed", do: now, else: nil),
      consent_text: "Signed up via dev seeds",
      source: Enum.at(["website", "checkout", "import"], rem(i, 3))
    })
    |> Repo.insert!()
  end

  # ── 6. Newsletter campaigns (30 — enough for 2 pages at 25/page) ──

  IO.puts("Creating 30 newsletter campaigns...")

  for i <- 0..29 do
    status = Enum.at(["draft", "sent", "sent", "sent", "scheduled"], rem(i, 5))

    %Newsletter.Campaign{}
    |> Newsletter.Campaign.changeset(%{
      subject: DevSeeds.campaign_subject(i),
      body: """
      Hi there!

      #{DevSeeds.campaign_subject(i)} — check out what's new in the shop.

      Visit us at https://example.com

      Unsubscribe: {{unsubscribe_url}}
      """,
      status: status,
      sent_at: if(status == "sent", do: now, else: nil),
      sent_count: if(status == "sent", do: Enum.random(20..55), else: 0),
      failed_count: if(status == "sent", do: Enum.random(0..3), else: 0),
      scheduled_at: if(status == "scheduled", do: DateTime.add(now, 7, :day), else: nil)
    })
    |> Repo.insert!()
  end

  # ── 7. Redirects (30 — enough for 2 pages at 25/page) ──

  IO.puts("Creating 30 redirects...")

  Redirects.create_table()

  for i <- 0..29 do
    source = Enum.at(["auto_slug_change", "admin", "auto_product_deleted", "analytics_auto_resolved"], rem(i, 4))
    old_slug = "old-product-#{i}-#{:rand.uniform(9999)}"
    new_slug = "new-product-#{i}"

    %Redirect{}
    |> Redirect.changeset(%{
      from_path: "/products/#{old_slug}",
      to_path: "/products/#{new_slug}",
      status_code: if(rem(i, 5) == 0, do: 302, else: 301),
      source: source,
      hit_count: Enum.random(0..150)
    })
    |> Repo.insert!()
  end

  # ── 8. Broken URLs (30 — enough for 2 pages at 25/page) ──

  IO.puts("Creating 30 broken URLs...")

  for i <- 0..29 do
    days_ago = Enum.random(1..60)
    first_seen = DateTime.add(now, -days_ago * 86400, :second)

    %BrokenUrl{}
    |> BrokenUrl.changeset(%{
      path: "/products/missing-item-#{i}-#{:rand.uniform(9999)}",
      prior_analytics_hits: Enum.random(0..500),
      recent_404_count: Enum.random(1..50),
      first_seen_at: first_seen,
      last_seen_at: DateTime.add(first_seen, Enum.random(0..days_ago) * 86400, :second),
      status: "pending"
    })
    |> Repo.insert!()
  end

  # Warm the redirects cache so they show up immediately
  Redirects.warm_cache()

  IO.puts("")
  IO.puts("Dev seed data created:")
  IO.puts("  60 products (with variants + images)")
  IO.puts("  90 media images (60 product + 30 extra)")
  IO.puts("  60 orders")
  IO.puts("  60 newsletter subscribers")
  IO.puts("  30 newsletter campaigns")
  IO.puts("  30 redirects")
  IO.puts("  30 broken URLs")
  IO.puts("")
  IO.puts("All views should now show pagination controls.")
end
