create or replace function sos.register_user(_email text, _password_hash text)
  returns setof sos.user
  language plpgsql
as $function$
declare
  _user_uuid uuid;
begin
  insert into sos."user" (
    user_email,
    user_password_hash
  ) values (
    _email,
    _password_hash
  ) returning user_uuid into _user_uuid;

  return query select * from sos."user" where user_uuid = _user_uuid;
end; $function$;

create or replace function sos.validate_session(_session_uuid uuid)
  returns setof sos.v_session
  language plpgsql
as $function$
begin
  return query select * from sos.v_session
    where session_uuid = _session_uuid
      and session_time_last_active + session_timeout_length > now();
end; $function$;

create or replace function sos.update_session(_session_uuid uuid)
  returns setof sos.v_session
  language plpgsql
as $function$
begin
  update sos."session"
    set session_time_last_active = now()
  where session_uuid = _session_uuid
    and now() < (select session_time_last_active + session_timeout_length);

  return query select * from sos.validate_session(_session_uuid);
end; $function$;

create or replace function sos.login_user_session(_user_uuid uuid, _timeout_length interval, _ip_addr varchar(50), _user_agent varchar(500), _referer varchar(500), _link uuid)
  returns setof sos.v_session
  language plpgsql
as $function$
declare
  _session_uuid uuid;
begin
  insert into sos."session" (
    session_user_uuid,
    session_timeout_length,
    session_ip_address,
    session_user_agent,
    session_referer,
    session_originating_link
  ) values (
    _user_uuid,
    _timeout_length,
    _ip_addr,
    _user_agent,
    _referer,
    _link
  ) returning session_uuid into _session_uuid;

  return query select * from sos.validate_session(_session_uuid);
end; $function$;

create or replace function sos.create_item(_name text, _urlslug citext, _description text, _price_cents integer, _published boolean)
  returns setof sos.v_item
  language plpgsql
as $function$
declare
  _item_uuid uuid;
begin
  insert into sos."item" (
    item_name,
    item_urlslug,
    item_description,
    item_price_cents,
    item_published
  ) values (
    _name,
    _urlslug,
    _description,
    _price_cents,
    _published
  ) returning item_uuid into _item_uuid;

  return query select * from sos.v_item where item_uuid = _item_uuid;
end; $function$;

create or replace function sos.add_image_to_item(_item_uuid uuid, _large_file bytea, _thumb_file bytea, _mime_type varchar, _uploader_uuid uuid)
  returns setof sos.v_item
  language plpgsql
as $function$
declare
  _image_uuid uuid;
begin
  insert into sos."image" (
    image_item_uuid,
    image_large_file,
    image_thumb_file,
    image_mime_type,
    image_uploader_uuid
  ) values (
    _item_uuid,
    _large_file,
    _thumb_file,
    _mime_type,
    _uploader_uuid
  ) returning image_uuid into _image_uuid;

  return query select * from sos.v_item where item_uuid = _item_uuid;
end; $function$;

create or replace function sos.set_featured_image(_item_uuid uuid, _image_uuid uuid)
  returns setof sos.v_item
  language plpgsql
as $function$
begin
  -- Un-feature all other images
  update sos."image" set
    image_featured = false
  where image_item_uuid = _item_uuid;

  update sos."image" set
    image_featured = true
  where image_uuid = _image_uuid;

  return query select * from sos.v_item where item_uuid = _item_uuid;
end; $function$;

create or replace function sos.get_image_large(_image_uuid uuid)
  returns table (image_uuid uuid, image_mime_type varchar, image_file bytea)
  language plpgsql
as $function$
begin
  return query select
      "image".image_uuid,
      "image".image_mime_type,
      "image".image_large_file as image_file
    from sos."image"
    where "image".image_uuid = _image_uuid;
end; $function$;

create or replace function sos.get_image_thumb(_image_uuid uuid)
  returns table (image_uuid uuid, image_mime_type varchar, image_file bytea)
  language plpgsql
as $function$
begin
  return query select
      "image".image_uuid,
      "image".image_mime_type,
      "image".image_thumb_file as image_file
    from sos."image"
    where "image".image_uuid = _image_uuid;
end; $function$;

create or replace function sos.create_category(_category_name text, _category_urlslug citext, _category_description text)
  returns setof sos.v_category
  language plpgsql
as $function$
declare
  _category_uuid uuid;
begin
  insert into sos."category" (
    category_name,
    category_urlslug,
    category_description
  ) values (
    _category_name,
    _category_urlslug,
    _category_description
  ) returning category_uuid into _category_uuid;

  return query select * from sos.v_category where category_uuid = _category_uuid;
end; $function$;
