// The response side of cookies — FastAPI's `response.set_cookie` and
// `delete_cookie`. `Context::cookie` already reads what a request carries; this
// is what writes one back.
//
// The cookie itself is `moonhttp`'s, header and all; what is here is putting one
// on a response. They are functions over a response rather than methods on it
// because `@moonasgi.Response` belongs to another package, and each returns a new
// response with one more `Set-Cookie` header. That is also the correct wire
// shape: two cookies are two headers, never one merged field, since `Set-Cookie`
// is the one header a proxy may not fold on commas.

///|
pub using @cookie {type SameSite, type Cookie}

///|
/// Add a `Set-Cookie` header to `resp` (← FastAPI's `response.set_cookie`),
/// returning the response that carries it; the original is untouched, so a
/// handler can hand the same base response to two callers.
///
/// `max_age` is the lifetime in seconds and `expires` the moment it dies; giving
/// neither makes it a session cookie. `path` defaults to `/`, and `None` omits
/// the attribute so the cookie scopes to the request's own directory.
/// `http_only` keeps it away from scripts, `secure` keeps it off plaintext
/// connections, and `same_site` defaults to `Lax` — the browser default, and the
/// one that stops a cross-site form post from carrying a session.
pub fn set_cookie(
  resp : @moonasgi.Response,
  name : String,
  value : String,
  max_age? : Int,
  expires? : @moondate.Moment,
  path? : String? = Some("/"),
  domain? : String,
  secure? : Bool = false,
  http_only? : Bool = false,
  same_site? : @cookie.SameSite? = Some(Lax),
) -> @moonasgi.Response {
  let cookie = @cookie.Cookie::new(
    name,
    value,
    max_age?,
    expires?,
    domain?,
    path~,
    secure~,
    http_only~,
    same_site~,
  )
  @moonasgi.Response::new(
    resp.status,
    [..resp.headers, ("set-cookie", cookie.encode())],
    resp.body,
  )
}

///|
/// Expire the cookie named `name` (← FastAPI's `response.delete_cookie`): an
/// empty value with `Max-Age=0` and a date in the past, so a browser that honours
/// only one of the two still drops it.
///
/// A cookie is identified by name, domain and path together, so `path` and
/// `domain` must match what set it — otherwise this writes a second, differently
/// scoped cookie and the original survives.
pub fn delete_cookie(
  resp : @moonasgi.Response,
  name : String,
  path? : String? = Some("/"),
  domain? : String,
  secure? : Bool = false,
  http_only? : Bool = false,
  same_site? : @cookie.SameSite? = Some(Lax),
) -> @moonasgi.Response {
  set_cookie(
    resp,
    name,
    "",
    max_age=0,
    expires=@moondate.Moment::of_epoch(0L),
    path~,
    domain?,
    secure~,
    http_only~,
    same_site~,
  )
}