create language plpgsql;

create sequence products_id_seq;
create table products (
  id integer not null
    default nextval('products_id_seq'),
  description text,
  price_cents integere not null,
  quantity integer not null,
  created_at timestamp with time zone
);

create table zip_codes (
  zip varchar(16) not null,
  city varchar(255) not null,
  state_abbreviation varchar(2) not null,
  county varchar(255) not null,
  latitude numeric not null,
  longitude numeric not null,
  primary key(zip)
);

create table addresses (
  line_1 varchar(256) not null
    check (length(line_1) > 0),
  line_2 varchar(256),
  city varchar(128) not null
    check (length(city) > 0)
  state varchar(2) not null
    check (length(state) = 2)
  zip_code varchar(9) not null 
    references zip_codes(zip),
);

-- utworzenie indeksu wzgldem kolumny zip_code, stanowicej 
-- najbardziej prawdopodobne kryterium wyszukiwania
create index address_zip_code_idx on addresses(zip_code);

create sequence credit_card_payments_id_seq;
create table credit_card_payments (
  id integer not null
    default nextval('credit_card_payments_id_seq'),
  card_number varchar(16) not null,
  type varchar(32) not null
    check (type in ('AmericanExpress', 'Visa', 'MasterCard')),
  expiration_month integer not null
    check (expiration_month > 0 and expiration_month <= 12),
  expiration_year integer not null
    check (expiration_year > 2008),
  primary key (id)
) inherits (addresses);

create sequence promotional_payments_id_seq;
create table promotional_payments (
  id integer not null
    default nextval('promotional_payments_id_seq'),
  promotion_id varchar(32) not null,
  created_at timestamp with time zone,
  primary key (id)
);

create sequence paypal_payments_id_seq;
create table paypal_payments (
  id integer not null
    default nextval('paypal_payments_id_seq'),
  email varchar(128) not null,
  auth_response text,
  created_at timestamp with time zone,
  primary key (id)
);

create sequence orders_id_seq;
create table orders (
  confirmation_code varchar(16) not null
    check length(confirmation_code) > 0),
  credit_card_payment_id integer
    references credit_card_payments(id),
  promotional_payment_id integer
    references promotional_payments(id),
  paypal_payment_id integer
    references paypal_payments(id),
  primaty key (confirmation_code)
);

alter table orders add constraint payment_xor_check(
  (case when credit_card_payment_id is not null then 1 else 0 end +
   case when promotional_payment_id is not null then 1 else 0 end +
   case when paypal_payment_id      is not null then 1 else 0 end) = 1
);

create table line_items (
  order_confirmation_code varchar(16) not null
    references orders(confirmation_code),
  product_id integer not null,
  quantity integer
    check (quantity > 0),
  position integer not null,
  purchase_price_cents integer not null
    check (purchase_price_cents >= 0)
  primary key (order_confirmation_code, position)
);


