-- ============================================
-- Gunbuilder / AvantLink Schema DDL
-- ============================================

-- Enable extension for UUID generation (if not already enabled)
CREATE EXTENSION IF NOT EXISTS pgcrypto;

-- ============================================
-- 1. merchants
-- ============================================
CREATE TABLE merchants (
    id               SERIAL PRIMARY KEY,
    name             TEXT NOT NULL,
    avantlink_mid    TEXT NOT NULL UNIQUE,  -- AvantLink merchant ID
    feed_url         TEXT NOT NULL,         -- Product datafeed URL
    is_active        BOOLEAN NOT NULL DEFAULT TRUE,
    created_at       TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at       TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_merchants_active ON merchants (is_active);


-- ============================================
-- 2. part_categories
-- Your internal Gunbuilder categories
-- ============================================
CREATE TABLE part_categories (
    id               SERIAL PRIMARY KEY,
    slug             TEXT NOT NULL UNIQUE,  -- 'lower', 'upper', 'barrel', etc.
    name             TEXT NOT NULL,         -- 'Lower Receiver'
    description      TEXT
);


-- ============================================
-- 3. brands
-- ============================================
CREATE TABLE brands (
    id               SERIAL PRIMARY KEY,
    name             TEXT NOT NULL UNIQUE,  -- 'Aero Precision'
    website          TEXT,
    created_at       TIMESTAMPTZ NOT NULL DEFAULT NOW()
);


-- ============================================
-- 4. products
-- Canonical parts, independent of merchants
-- ============================================
CREATE TABLE products (
    id                          UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    brand_id                    INTEGER REFERENCES brands(id),
    part_category_id            INTEGER NOT NULL REFERENCES part_categories(id),

    name                        TEXT NOT NULL,
    slug                        TEXT NOT NULL UNIQUE,
    description                 TEXT,
    caliber                     TEXT,
    barrel_length_mm            INTEGER,
    gas_system                  TEXT,
    handguard_length_mm         INTEGER,
    image_url                   TEXT,
    spec_sheet_url              TEXT,

    msrp                        NUMERIC(10,2),
    current_lowest_price        NUMERIC(10,2),
    current_lowest_merchant_id  INTEGER REFERENCES merchants(id),

    is_active                   BOOLEAN NOT NULL DEFAULT TRUE,
    created_at                  TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at                  TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_products_category ON products (part_category_id);
CREATE INDEX idx_products_brand ON products (brand_id);
CREATE INDEX idx_products_active ON products (is_active);
CREATE INDEX idx_products_lowest_price ON products (current_lowest_price);


-- Optional: a "natural-ish" uniqueness constraint if you want it
-- (Can be relaxed later if needed)
CREATE UNIQUE INDEX uniq_products_brand_name_cat
ON products (brand_id, name, part_category_id);


-- ============================================
-- 5. product_offers
-- Merchant-specific offers for a product
-- ============================================
CREATE TABLE product_offers (
    id                      UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    product_id              UUID NOT NULL REFERENCES products(id) ON DELETE CASCADE,
    merchant_id             INTEGER NOT NULL REFERENCES merchants(id),
    avantlink_product_id    TEXT NOT NULL,
    sku                     TEXT,
    upc                     TEXT,
    buy_url                 TEXT NOT NULL,

    price                   NUMERIC(10,2) NOT NULL,
    original_price          NUMERIC(10,2),
    currency                TEXT NOT NULL DEFAULT 'USD',
    in_stock                BOOLEAN NOT NULL DEFAULT TRUE,

    last_seen_at            TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    first_seen_at           TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- Each merchant + avantlink_product_id combination must be unique
CREATE UNIQUE INDEX uniq_product_offers_merchant_product
ON product_offers (merchant_id, avantlink_product_id);

CREATE INDEX idx_product_offers_product ON product_offers (product_id);
CREATE INDEX idx_product_offers_merchant ON product_offers (merchant_id);
CREATE INDEX idx_product_offers_in_stock ON product_offers (in_stock);
CREATE INDEX idx_product_offers_price ON product_offers (price);


-- ============================================
-- 6. price_history
-- For tracking price changes over time
-- ============================================
CREATE TABLE price_history (
    id                  BIGSERIAL PRIMARY KEY,
    product_offer_id    UUID NOT NULL REFERENCES product_offers(id) ON DELETE CASCADE,
    price               NUMERIC(10,2) NOT NULL,
    recorded_at         TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX idx_price_history_offer ON price_history (product_offer_id);
CREATE INDEX idx_price_history_recorded_at ON price_history (recorded_at);


-- ============================================
-- 7. category_mappings
-- Map raw AvantLink categories to internal part_categories
-- ============================================
CREATE TABLE category_mappings (
    id                  SERIAL PRIMARY KEY,
    merchant_id         INTEGER NOT NULL REFERENCES merchants(id),
    raw_category_path   TEXT NOT NULL,  -- e.g. 'Firearms > AR-15 Parts > Lower Receivers'
    part_category_id    INTEGER NOT NULL REFERENCES part_categories(id),
    created_at          TIMESTAMPTZ NOT NULL DEFAULT NOW(),

    UNIQUE (merchant_id, raw_category_path)
);

CREATE INDEX idx_category_mappings_merchant ON category_mappings (merchant_id);
CREATE INDEX idx_category_mappings_part_category ON category_mappings (part_category_id);


-- ============================================
-- 8. feed_imports
-- Track each feed import run for observability
-- ============================================
CREATE TABLE feed_imports (
    id               BIGSERIAL PRIMARY KEY,
    merchant_id      INTEGER NOT NULL REFERENCES merchants(id),
    started_at       TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    finished_at      TIMESTAMPTZ,
    rows_total       INTEGER,
    rows_processed   INTEGER,
    rows_new         INTEGER,
    rows_updated     INTEGER,
    status           TEXT NOT NULL DEFAULT 'running',  -- 'running','success','error'
    error_message    TEXT
);

CREATE INDEX idx_feed_imports_merchant ON feed_imports (merchant_id);
CREATE INDEX idx_feed_imports_status ON feed_imports (status);
CREATE INDEX idx_feed_imports_started_at ON feed_imports (started_at);


-- ============================================
-- 9. Helpful seed data (optional)
-- ============================================

-- Part categories seed (adjust as needed)
INSERT INTO part_categories (slug, name) VALUES
  ('lower', 'Lower Receiver'),
  ('upper', 'Upper Receiver'),
  ('barrel', 'Barrel'),
  ('handguard', 'Handguard'),
  ('stock', 'Stock'),
  ('optic', 'Optic')
ON CONFLICT (slug) DO NOTHING;

-- Example merchant skeleton (fill real datafeed URL + AvantLink MID)
-- INSERT INTO merchants (name, avantlink_mid, feed_url)
-- VALUES ('Example Merchant', '12345', 'https://www.avantlink.com/api/...');