-- Meshkee CMS — shopping cart and orders

-- ---------------------------------------------------------------------------
-- enums
-- ---------------------------------------------------------------------------
DO $$ BEGIN
  CREATE TYPE order_status AS ENUM (
    'pending',
    'confirmed',
    'processing',
    'shipped',
    'delivered',
    'cancelled'
  );
EXCEPTION
  WHEN duplicate_object THEN NULL;
END $$;

DO $$ BEGIN
  CREATE TYPE order_source AS ENUM ('website', 'admin');
EXCEPTION
  WHEN duplicate_object THEN NULL;
END $$;

-- ---------------------------------------------------------------------------
-- carts (one per customer per business)
-- ---------------------------------------------------------------------------
CREATE TABLE carts (
  id          BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  business_id BIGINT NOT NULL,
  user_id     BIGINT NOT NULL,
  created_at  TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at  TIMESTAMPTZ NOT NULL DEFAULT NOW(),

  CONSTRAINT carts_business_id_fkey
    FOREIGN KEY (business_id) REFERENCES businesses (id) ON DELETE CASCADE,
  CONSTRAINT carts_user_id_fkey
    FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE,
  CONSTRAINT carts_business_user_unique UNIQUE (business_id, user_id)
);

CREATE INDEX idx_carts_business_id ON carts (business_id);
CREATE INDEX idx_carts_user_id ON carts (user_id);

CREATE TRIGGER carts_set_updated_at
  BEFORE UPDATE ON carts
  FOR EACH ROW
  EXECUTE FUNCTION set_updated_at();

-- ---------------------------------------------------------------------------
-- cart items (product variants in cart)
-- ---------------------------------------------------------------------------
CREATE TABLE cart_items (
  id         BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  cart_id    BIGINT NOT NULL,
  variant_id BIGINT NOT NULL,
  quantity   INT NOT NULL DEFAULT 1,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),

  CONSTRAINT cart_items_cart_id_fkey
    FOREIGN KEY (cart_id) REFERENCES carts (id) ON DELETE CASCADE,
  CONSTRAINT cart_items_variant_id_fkey
    FOREIGN KEY (variant_id) REFERENCES product_variants (id) ON DELETE CASCADE,
  CONSTRAINT cart_items_cart_variant_unique UNIQUE (cart_id, variant_id),
  CONSTRAINT cart_items_quantity_positive CHECK (quantity > 0)
);

CREATE INDEX idx_cart_items_cart_id ON cart_items (cart_id);
CREATE INDEX idx_cart_items_variant_id ON cart_items (variant_id);

CREATE TRIGGER cart_items_set_updated_at
  BEFORE UPDATE ON cart_items
  FOR EACH ROW
  EXECUTE FUNCTION set_updated_at();

-- ---------------------------------------------------------------------------
-- orders
-- ---------------------------------------------------------------------------
CREATE TABLE orders (
  id                BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  business_id       BIGINT NOT NULL,
  user_id           BIGINT NOT NULL,
  order_number      VARCHAR(30) NOT NULL,
  status            order_status NOT NULL DEFAULT 'pending',
  source            order_source NOT NULL DEFAULT 'website',
  subtotal          NUMERIC(12, 2) NOT NULL DEFAULT 0,
  shipping_total    NUMERIC(12, 2) NOT NULL DEFAULT 0,
  discount_total    NUMERIC(12, 2) NOT NULL DEFAULT 0,
  total             NUMERIC(12, 2) NOT NULL DEFAULT 0,
  shipping_address  JSONB NOT NULL DEFAULT '{}',
  address_id        BIGINT,
  customer_notes    TEXT,
  admin_notes       TEXT,
  created_by        BIGINT,
  created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),

  CONSTRAINT orders_business_id_fkey
    FOREIGN KEY (business_id) REFERENCES businesses (id) ON DELETE CASCADE,
  CONSTRAINT orders_user_id_fkey
    FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE RESTRICT,
  CONSTRAINT orders_address_id_fkey
    FOREIGN KEY (address_id) REFERENCES addresses (id) ON DELETE SET NULL,
  CONSTRAINT orders_created_by_fkey
    FOREIGN KEY (created_by) REFERENCES users (id) ON DELETE SET NULL,
  CONSTRAINT orders_business_order_number_unique UNIQUE (business_id, order_number),
  CONSTRAINT orders_subtotal_non_negative CHECK (subtotal >= 0),
  CONSTRAINT orders_shipping_total_non_negative CHECK (shipping_total >= 0),
  CONSTRAINT orders_discount_total_non_negative CHECK (discount_total >= 0),
  CONSTRAINT orders_total_non_negative CHECK (total >= 0)
);

CREATE INDEX idx_orders_business_created
  ON orders (business_id, created_at DESC);

CREATE INDEX idx_orders_business_user
  ON orders (business_id, user_id, created_at DESC);

CREATE INDEX idx_orders_business_status
  ON orders (business_id, status, created_at DESC);

CREATE TRIGGER orders_set_updated_at
  BEFORE UPDATE ON orders
  FOR EACH ROW
  EXECUTE FUNCTION set_updated_at();

-- ---------------------------------------------------------------------------
-- order items (line items with price snapshots)
-- ---------------------------------------------------------------------------
CREATE TABLE order_items (
  id                  BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  order_id            BIGINT NOT NULL,
  variant_id          BIGINT,
  product_id          BIGINT NOT NULL,
  product_title       VARCHAR(255) NOT NULL,
  variant_sku         VARCHAR(100),
  unit_price          NUMERIC(12, 2) NOT NULL,
  compare_at_price    NUMERIC(12, 2),
  quantity            INT NOT NULL,
  line_total          NUMERIC(12, 2) NOT NULL,
  selections_snapshot JSONB NOT NULL DEFAULT '[]',
  created_at          TIMESTAMPTZ NOT NULL DEFAULT NOW(),

  CONSTRAINT order_items_order_id_fkey
    FOREIGN KEY (order_id) REFERENCES orders (id) ON DELETE CASCADE,
  CONSTRAINT order_items_variant_id_fkey
    FOREIGN KEY (variant_id) REFERENCES product_variants (id) ON DELETE SET NULL,
  CONSTRAINT order_items_product_id_fkey
    FOREIGN KEY (product_id) REFERENCES products (id) ON DELETE RESTRICT,
  CONSTRAINT order_items_quantity_positive CHECK (quantity > 0),
  CONSTRAINT order_items_unit_price_non_negative CHECK (unit_price >= 0),
  CONSTRAINT order_items_line_total_non_negative CHECK (line_total >= 0)
);

CREATE INDEX idx_order_items_order_id ON order_items (order_id);
CREATE INDEX idx_order_items_variant_id ON order_items (variant_id);

-- ---------------------------------------------------------------------------
-- permissions
-- ---------------------------------------------------------------------------
INSERT INTO permissions (name, slug, group_name, description) VALUES
  ('Create orders', 'orders.create', 'orders', 'Create orders on behalf of customers'),
  ('Update orders', 'orders.update', 'orders', 'Update order status and admin notes')
ON CONFLICT (slug) DO NOTHING;

-- business_owner
INSERT INTO role_permissions (role_id, permission_id)
SELECT r.id, p.id
FROM roles r
JOIN permissions p ON p.slug IN ('orders.read', 'orders.create', 'orders.update')
WHERE r.slug = 'business_owner'
ON CONFLICT DO NOTHING;

-- owner (legacy global role)
INSERT INTO role_permissions (role_id, permission_id)
SELECT r.id, p.id
FROM roles r
JOIN permissions p ON p.slug IN ('orders.read', 'orders.create', 'orders.update')
WHERE r.slug = 'owner'
ON CONFLICT DO NOTHING;

-- admin
INSERT INTO role_permissions (role_id, permission_id)
SELECT r.id, p.id
FROM roles r
JOIN permissions p ON p.slug IN ('orders.read', 'orders.create', 'orders.update')
WHERE r.slug = 'admin'
ON CONFLICT DO NOTHING;

-- editor: read + update status
INSERT INTO role_permissions (role_id, permission_id)
SELECT r.id, p.id
FROM roles r
JOIN permissions p ON p.slug IN ('orders.read', 'orders.update')
WHERE r.slug = 'editor'
ON CONFLICT DO NOTHING;

-- viewer: read only
INSERT INTO role_permissions (role_id, permission_id)
SELECT r.id, p.id
FROM roles r
JOIN permissions p ON p.slug = 'orders.read'
WHERE r.slug = 'viewer'
ON CONFLICT DO NOTHING;
