import { literal, safeSql, type SafeSqlFragment } from '@supabase/pg-meta'
import dayjs from 'dayjs'

import type { DatetimeHelper } from '../Settings/Logs/Logs.types'
import { PresetConfig, Presets, ReportFilterItem } from './Reports.types'
import { PlanId } from '@/data/subscriptions/types'

export const LAYOUT_COLUMN_COUNT = 2

export interface ReportsDatetimeHelper extends DatetimeHelper {
  availableIn: PlanId[]
}

export enum REPORT_DATERANGE_HELPER_LABELS {
  LAST_10_MINUTES = 'Last 10 minutes',
  LAST_30_MINUTES = 'Last 30 minutes',
  LAST_60_MINUTES = 'Last 60 minutes',
  LAST_3_HOURS = 'Last 3 hours',
  LAST_24_HOURS = 'Last 24 hours',
  LAST_7_DAYS = 'Last 7 days',
  LAST_14_DAYS = 'Last 14 days',
  LAST_28_DAYS = 'Last 28 days',
}

export const REPORTS_DATEPICKER_HELPERS: ReportsDatetimeHelper[] = [
  {
    text: REPORT_DATERANGE_HELPER_LABELS.LAST_10_MINUTES,
    calcFrom: () => dayjs().subtract(10, 'minute').toISOString(),
    calcTo: () => dayjs().toISOString(),
    availableIn: ['free', 'pro', 'team', 'enterprise', 'platform'],
  },
  {
    text: REPORT_DATERANGE_HELPER_LABELS.LAST_30_MINUTES,
    calcFrom: () => dayjs().subtract(30, 'minute').toISOString(),
    calcTo: () => dayjs().toISOString(),
    availableIn: ['free', 'pro', 'team', 'enterprise', 'platform'],
  },
  {
    text: REPORT_DATERANGE_HELPER_LABELS.LAST_60_MINUTES,
    calcFrom: () => dayjs().subtract(1, 'hour').toISOString(),
    calcTo: () => dayjs().toISOString(),
    default: true,
    availableIn: ['free', 'pro', 'team', 'enterprise', 'platform'],
  },
  {
    text: REPORT_DATERANGE_HELPER_LABELS.LAST_3_HOURS,
    calcFrom: () => dayjs().subtract(3, 'hour').toISOString(),
    calcTo: () => dayjs().toISOString(),
    availableIn: ['free', 'pro', 'team', 'enterprise', 'platform'],
  },
  {
    text: REPORT_DATERANGE_HELPER_LABELS.LAST_24_HOURS,
    calcFrom: () => dayjs().subtract(1, 'day').toISOString(),
    calcTo: () => dayjs().toISOString(),
    availableIn: ['free', 'pro', 'team', 'enterprise', 'platform'],
  },
  {
    text: REPORT_DATERANGE_HELPER_LABELS.LAST_7_DAYS,
    calcFrom: () => dayjs().subtract(7, 'day').toISOString(),
    calcTo: () => dayjs().toISOString(),
    availableIn: ['pro', 'team', 'enterprise'],
  },
  {
    text: REPORT_DATERANGE_HELPER_LABELS.LAST_14_DAYS,
    calcFrom: () => dayjs().subtract(14, 'day').toISOString(),
    calcTo: () => dayjs().toISOString(),
    availableIn: ['team', 'enterprise'],
  },
  {
    text: REPORT_DATERANGE_HELPER_LABELS.LAST_28_DAYS,
    calcFrom: () => dayjs().subtract(28, 'day').toISOString(),
    calcTo: () => dayjs().toISOString(),
    availableIn: ['team', 'enterprise'],
  },
]

export const DEFAULT_QUERY_PARAMS = {
  iso_timestamp_start: REPORTS_DATEPICKER_HELPERS[0].calcFrom(),
  iso_timestamp_end: REPORTS_DATEPICKER_HELPERS[0].calcTo(),
}

function rewriteWhereToAnd(sql: SafeSqlFragment): SafeSqlFragment {
  return sql.replace(/^WHERE/, 'AND') as SafeSqlFragment
}

export const generateRegexpWhere = (filters: ReportFilterItem[], prepend = true) => {
  if (filters.length === 0) return ''
  const conditions = filters
    .map((filter) => {
      const splitKey = filter.key.split('.')
      const normalizedKey = [splitKey[splitKey.length - 2], splitKey[splitKey.length - 1]].join('.')
      const filterKey = filter.key.includes('.') ? normalizedKey : filter.key

      const hasQuotes =
        filter.value.toString().includes('"') || filter.value.toString().includes("'")

      const valueIsNumber = !isNaN(Number(filter.value))
      const valueWithQuotes = !valueIsNumber && hasQuotes ? filter.value : `'${filter.value}'`
      const lowercaseValue = !valueIsNumber && String(valueWithQuotes).toLowerCase()

      const finalValue = valueIsNumber ? filter.value : lowercaseValue

      // Handle different comparison operators
      switch (filter.compare) {
        case 'matches':
          return `REGEXP_CONTAINS(${filterKey}, ${finalValue})`
        case 'is':
          return `${filterKey} = ${finalValue}`
        case '!=':
          return `${filterKey} != ${finalValue}`
        case '>=':
          return `${filterKey} >= ${finalValue}`
        case '<=':
          return `${filterKey} <= ${finalValue}`
        case '>':
          return `${filterKey} > ${finalValue}`
        case '<':
          return `${filterKey} < ${finalValue}`
        default:
          // Fallback to exact match for unknown operators
          return `${filterKey} = ${finalValue}`
      }
    })
    .filter(Boolean) // Remove any null/undefined conditions
    .join(' AND ')

  if (conditions === '') return ''

  if (prepend) {
    return 'WHERE ' + conditions
  } else {
    return 'AND ' + conditions
  }
}

export const PRESET_CONFIG: Record<Presets, PresetConfig> = {
  [Presets.API]: {
    title: 'API',
    queries: {
      totalRequests: {
        queryType: 'logs',
        sql: (filters) => `
        -- reports-api-total-requests
        select
          cast(timestamp_trunc(t.timestamp, hour) as datetime) as timestamp,
          count(t.id) as count
        FROM edge_logs t
          cross join unnest(metadata) as m
          cross join unnest(m.response) as response
          cross join unnest(m.request) as request
          cross join unnest(request.headers) as headers
          ${generateRegexpWhere(filters)}
        GROUP BY
          timestamp
        ORDER BY
          timestamp ASC`,
      },
      topRoutes: {
        queryType: 'logs',
        sql: (filters) => `
        -- reports-api-top-routes
        select
          request.path as path,
          request.method as method,
          request.search as search,
          response.status_code as status_code,
          count(t.id) as count
        from edge_logs t
          cross join unnest(metadata) as m
          cross join unnest(m.response) as response
          cross join unnest(m.request) as request
          cross join unnest(request.headers) as headers
          ${generateRegexpWhere(filters)}
        group by
          request.path, request.method, request.search, response.status_code
        order by
          count desc
        limit 10
        `,
      },
      errorCounts: {
        queryType: 'logs',
        sql: (filters) => `
        -- reports-api-error-counts
        select
          cast(timestamp_trunc(t.timestamp, hour) as datetime) as timestamp,
          count(t.id) as count
        FROM edge_logs t
          cross join unnest(metadata) as m
          cross join unnest(m.response) as response
          cross join unnest(m.request) as request
          cross join unnest(request.headers) as headers
        WHERE
          response.status_code >= 400
        ${generateRegexpWhere(filters, false)}
        GROUP BY
          timestamp
        ORDER BY
          timestamp ASC
        `,
      },
      topErrorRoutes: {
        queryType: 'logs',
        sql: (filters) => `
        -- reports-api-top-error-routes
        select
          request.path as path,
          request.method as method,
          request.search as search,
          response.status_code as status_code,
          count(t.id) as count
        from edge_logs t
          cross join unnest(metadata) as m
          cross join unnest(m.response) as response
          cross join unnest(m.request) as request
          cross join unnest(request.headers) as headers
        where
          response.status_code >= 400
        ${generateRegexpWhere(filters, false)}
        group by
          request.path, request.method, request.search, response.status_code
        order by
          count desc
        limit 10
        `,
      },
      responseSpeed: {
        queryType: 'logs',
        sql: (filters) => `
        -- reports-api-response-speed
        select
          cast(timestamp_trunc(t.timestamp, hour) as datetime) as timestamp,
          avg(response.origin_time) as avg
        FROM
          edge_logs t
          cross join unnest(metadata) as m
          cross join unnest(m.response) as response
          cross join unnest(m.request) as request
          cross join unnest(request.headers) as headers
          ${generateRegexpWhere(filters)}
        GROUP BY
          timestamp
        ORDER BY
          timestamp ASC
      `,
      },
      topSlowRoutes: {
        queryType: 'logs',
        sql: (filters) => `
        -- reports-api-top-slow-routes
        select
          request.path as path,
          request.method as method,
          request.search as search,
          response.status_code as status_code,
          count(t.id) as count,
          avg(response.origin_time) as avg
        from edge_logs t
          cross join unnest(metadata) as m
          cross join unnest(m.response) as response
          cross join unnest(m.request) as request
          cross join unnest(request.headers) as headers
        ${generateRegexpWhere(filters)}
        group by
          request.path, request.method, request.search, response.status_code
        order by
          avg desc
        limit 10
        `,
      },
      networkTraffic: {
        queryType: 'logs',
        sql: (filters) => `
        -- reports-api-network-traffic
        select
          cast(timestamp_trunc(t.timestamp, hour) as datetime) as timestamp,
          coalesce(
            safe_divide(
              sum(
                cast(coalesce(headers.content_length, "0") as int64)
              ),
              1000000
            ),
            0
          ) as ingress_mb,
          coalesce(
            safe_divide(
              sum(
                cast(coalesce(resp_headers.content_length, "0") as int64)
              ),
              1000000
            ),
            0
          ) as egress_mb,
        FROM
          edge_logs t
          cross join unnest(metadata) as m
          cross join unnest(m.response) as response
          cross join unnest(m.request) as request
          cross join unnest(request.headers) as headers
          cross join unnest(response.headers) as resp_headers
          ${generateRegexpWhere(filters)}
        GROUP BY
          timestamp
        ORDER BY
          timestamp ASC
        `,
      },
      requestsByCountry: {
        queryType: 'logs',
        sql: (filters) => `
        -- reports-api-requests-by-country
        select
          cf.country as country,
          count(t.id) as count
        from edge_logs t
          cross join unnest(metadata) as m
          cross join unnest(m.response) as response
          cross join unnest(m.request) as request
          cross join unnest(request.headers) as headers
          cross join unnest(request.cf) as cf
        where
          cf.country is not null
        ${generateRegexpWhere(filters, false)}
        group by
          cf.country
        `,
      },
    },
  },
  [Presets.AUTH]: {
    title: '',
    queries: {},
  },
  [Presets.STORAGE]: {
    title: 'Storage',
    queries: {
      cacheHitRate: {
        queryType: 'logs',
        // storage report does not perform any filtering
        sql: (filters) => `
        -- reports-storage-cache-hit-rate
SELECT
  timestamp_trunc(timestamp, hour) as timestamp,
  countif( h.cf_cache_status in ('HIT', 'STALE', 'REVALIDATED', 'UPDATING') ) as hit_count,
  countif( h.cf_cache_status in ('MISS', 'NONE/UNKNOWN', 'EXPIRED', 'BYPASS', 'DYNAMIC') ) as miss_count
from edge_logs f
  cross join unnest(f.metadata) as m
  cross join unnest(m.request) as r
  cross join unnest(m.response) as res
  cross join unnest(res.headers) as h
where starts_with(r.path, '/storage/v1/object') and r.method = 'GET'
  ${generateRegexpWhere(filters, false)}
group by timestamp
order by timestamp desc
`,
      },
      topCacheMisses: {
        queryType: 'logs',
        // storage report does not perform any filtering
        sql: (filters) => `
        -- reports-storage-top-cache-misses
SELECT
  r.path as path,
  r.search as search,
  count(id) as count
from edge_logs f
  cross join unnest(f.metadata) as m
  cross join unnest(m.request) as r
  cross join unnest(m.response) as res
  cross join unnest(res.headers) as h
where starts_with(r.path, '/storage/v1/object')
  and r.method = 'GET'
  and h.cf_cache_status in ('MISS', 'NONE/UNKNOWN', 'EXPIRED', 'BYPASS', 'DYNAMIC')
  ${generateRegexpWhere(filters, false)}
group by path, search
order by count desc
limit 12
    `,
      },
    },
  },
  [Presets.QUERY_PERFORMANCE]: {
    title: 'Query performance',
    queries: {
      mostFrequentlyInvoked: {
        queryType: 'db',
        safeSql: (
          _params,
          where,
          orderBy,
          runIndexAdvisor = false,
          _filterIndexAdvisor = false
        ) => safeSql`
        -- reports-query-performance-most-frequently-invoked
set search_path to public, extensions;

select
    auth.rolname,
    statements.query,
    statements.calls,
    -- -- Postgres 13, 14, 15
    statements.total_exec_time + statements.total_plan_time as total_time,
    statements.min_exec_time + statements.min_plan_time as min_time,
    statements.max_exec_time + statements.max_plan_time as max_time,
    statements.mean_exec_time + statements.mean_plan_time as mean_time,
    -- -- Postgres <= 12
    -- total_time,
    -- min_time,
    -- max_time,
    -- mean_time,
    coalesce(statements.rows::numeric / nullif(statements.calls, 0), 0) as avg_rows,
    statements.rows as rows_read,
    case
      when (statements.shared_blks_hit + statements.shared_blks_read) > 0
      then round(
        (statements.shared_blks_hit * 100.0) /
        (statements.shared_blks_hit + statements.shared_blks_read),
        2
      )
      else 0
    end as cache_hit_rate${
      runIndexAdvisor
        ? safeSql`,
    case
      when (lower(statements.query) like 'select%' or lower(statements.query) like 'with pgrst%')
      then (
        select json_build_object(
          'has_suggestion', array_length(index_statements, 1) > 0,
          'startup_cost_before', startup_cost_before,
          'startup_cost_after', startup_cost_after,
          'total_cost_before', total_cost_before,
          'total_cost_after', total_cost_after,
          'index_statements', index_statements
        )
        from index_advisor(statements.query)
      )
      else null
    end as index_advisor_result`
        : safeSql``
    }
  from pg_stat_statements as statements
    inner join pg_authid as auth on statements.userid = auth.oid
  -- skip queries that were never actually executed
  WHERE statements.calls > 0 ${where ? rewriteWhereToAnd(where) : safeSql``}
  ${orderBy || safeSql`order by statements.calls desc`}
  limit 20`,
      },
      mostTimeConsuming: {
        queryType: 'db',
        safeSql: (
          _,
          where,
          orderBy,
          runIndexAdvisor = false,
          _filterIndexAdvisor = false
        ) => safeSql`
        -- reports-query-performance-most-time-consuming
set search_path to public, extensions;

-- compute total time once up front so we don't need a window function over all rows
with grand_total as (
  select coalesce(nullif(sum(total_exec_time + total_plan_time), 0), 1) as v
  from pg_stat_statements where calls > 0
)
select
    auth.rolname,
    statements.query,
    statements.calls,
    statements.total_exec_time + statements.total_plan_time as total_time,
    statements.mean_exec_time + statements.mean_plan_time as mean_time,
    coalesce(
      ((statements.total_exec_time + statements.total_plan_time) /
        (select v from grand_total)) *
        100,
      0
    ) as prop_total_time${
      runIndexAdvisor
        ? safeSql`,
    case
      when (lower(statements.query) like 'select%' or lower(statements.query) like 'with pgrst%')
      then (
        select json_build_object(
          'has_suggestion', array_length(index_statements, 1) > 0,
          'startup_cost_before', startup_cost_before,
          'startup_cost_after', startup_cost_after,
          'total_cost_before', total_cost_before,
          'total_cost_after', total_cost_after,
          'index_statements', index_statements
        )
        from index_advisor(statements.query)
      )
      else null
    end as index_advisor_result`
        : safeSql``
    }
  from pg_stat_statements as statements
    inner join pg_authid as auth on statements.userid = auth.oid
  -- skip queries that were never actually executed
  WHERE statements.calls > 0 ${where ? rewriteWhereToAnd(where) : safeSql``}
  ${orderBy || safeSql`order by total_time desc`}
  limit 20`,
      },
      slowestExecutionTime: {
        queryType: 'db',
        safeSql: (
          _params,
          where,
          orderBy,
          runIndexAdvisor = false,
          _filterIndexAdvisor = false
        ) => safeSql`
        -- reports-query-performance-slowest-execution-time
set search_path to public, extensions;

select
    auth.rolname,
    statements.query,
    statements.calls,
    -- -- Postgres 13, 14, 15
    statements.total_exec_time + statements.total_plan_time as total_time,
    statements.min_exec_time + statements.min_plan_time as min_time,
    statements.max_exec_time + statements.max_plan_time as max_time,
    statements.mean_exec_time + statements.mean_plan_time as mean_time,
    -- -- Postgres <= 12
    -- total_time,
    -- min_time,
    -- max_time,
    -- mean_time,
    coalesce(statements.rows::numeric / nullif(statements.calls, 0), 0) as avg_rows${
      runIndexAdvisor
        ? safeSql`,
    case
      when (lower(statements.query) like 'select%' or lower(statements.query) like 'with pgrst%')
      then (
        select json_build_object(
          'has_suggestion', array_length(index_statements, 1) > 0,
          'startup_cost_before', startup_cost_before,
          'startup_cost_after', startup_cost_after,
          'total_cost_before', total_cost_before,
          'total_cost_after', total_cost_after,
          'index_statements', index_statements
        )
        from index_advisor(statements.query)
      )
      else null
    end as index_advisor_result`
        : safeSql``
    }
  from pg_stat_statements as statements
    inner join pg_authid as auth on statements.userid = auth.oid
  -- skip queries that were never actually executed
  WHERE statements.calls > 0 ${where ? rewriteWhereToAnd(where) : safeSql``}
  ${orderBy || safeSql`order by max_time desc`}
  limit 20`,
      },
      queryHitRate: {
        queryType: 'db',
        safeSql: (_params) => safeSql`-- reports-query-performance-cache-and-index-hit-rate
select
    'index hit rate' as name,
    (sum(idx_blks_hit)) / nullif(sum(idx_blks_hit + idx_blks_read),0) as ratio
  from pg_statio_user_indexes
  union all
  select
    'table hit rate' as name,
    sum(heap_blks_hit) / nullif(sum(heap_blks_hit) + sum(heap_blks_read),0) as ratio
  from pg_statio_user_tables;`,
      },
      unified: {
        queryType: 'db',
        safeSql: (
          _params,
          where,
          orderBy,
          runIndexAdvisor = false,
          filterIndexAdvisor = false,
          page = 1,
          pageSize = 20
        ) => {
          const offset = (page - 1) * pageSize
          // When filtering by index suggestions we need a larger scan window since we don't
          // know how many rows will match. Cap at a reasonable upper bound to avoid running
          // index_advisor() across the entire dataset on any code path where it's active.
          const INDEX_ADVISOR_SCAN_CAP = 500
          const baseScanTarget =
            filterIndexAdvisor && runIndexAdvisor ? offset + pageSize * 10 : offset + pageSize
          const baseCteLimit = runIndexAdvisor
            ? Math.min(baseScanTarget, INDEX_ADVISOR_SCAN_CAP)
            : baseScanTarget
          const baseQuery = safeSql`
        -- reports-query-performance-unified
        set search_path to public, extensions;

        -- compute total time once up front so we don't need a window function over all rows
        with grand_total as (
          select coalesce(nullif(sum(total_exec_time + total_plan_time), 0), 1) as v
          from pg_stat_statements where calls > 0
        ),
        base as (
          select
            auth.rolname,
            statements.query,
            statements.calls,
            statements.total_exec_time + statements.total_plan_time as total_time,
            statements.min_exec_time + statements.min_plan_time as min_time,
            statements.max_exec_time + statements.max_plan_time as max_time,
            statements.mean_exec_time + statements.mean_plan_time as mean_time,
            coalesce(statements.rows::numeric / nullif(statements.calls, 0), 0) as avg_rows,
            statements.rows as rows_read,
            statements.shared_blks_hit as debug_hit,
            statements.shared_blks_read as debug_read,
            case
              when (statements.shared_blks_hit + statements.shared_blks_read) > 0
              then (statements.shared_blks_hit::numeric * 100.0) /
                   (statements.shared_blks_hit + statements.shared_blks_read)
              else 0
            end as cache_hit_rate,
            coalesce(
              ((statements.total_exec_time + statements.total_plan_time) /
                (select v from grand_total)) *
                100,
              0
            ) as prop_total_time
          from pg_stat_statements as statements
            inner join pg_authid as auth on statements.userid = auth.oid
          -- skip queries that were never actually executed
          WHERE statements.calls > 0 ${where ? rewriteWhereToAnd(where) : safeSql``}
          ${orderBy || safeSql`order by total_time desc`}
          ${baseCteLimit !== null ? safeSql`limit ${literal(baseCteLimit)}` : safeSql``}
        ),
        query_results as (
          select
            base.*${
              runIndexAdvisor
                ? safeSql`,
            case
              when (lower(base.query) like 'select%' or lower(base.query) like 'with pgrst%')
              then (
                select json_build_object(
                  'has_suggestion', array_length(index_statements, 1) > 0,
                  'startup_cost_before', startup_cost_before,
                  'startup_cost_after', startup_cost_after,
                  'total_cost_before', total_cost_before,
                  'total_cost_after', total_cost_after,
                  'index_statements', index_statements
                )
                from index_advisor(base.query)
              )
              else null
            end as index_advisor_result`
                : safeSql``
            }
          from base
        )
        select *
        from query_results
        ${filterIndexAdvisor && runIndexAdvisor ? safeSql`where (index_advisor_result->>'has_suggestion')::boolean = true` : safeSql``}
        ${orderBy || safeSql`order by total_time desc`}
        limit ${literal(pageSize)} offset ${literal(offset)}`

          return baseQuery
        },
      },
      slowQueriesCount: {
        queryType: 'db',
        safeSql: () => safeSql`
        -- reports-query-performance-slow-queries-count
        set search_path to public, extensions;

        -- Count of slow queries (> 1 second average)
        SELECT count(*) as slow_queries_count
        -- alias needed to reference columns in WHERE
        FROM pg_stat_statements as statements
        -- skip never-executed queries; mean_exec_time > 1000ms = avg over 1 second
        WHERE statements.calls > 0 AND statements.mean_exec_time > 1000;`,
      },
      queryMetrics: {
        queryType: 'db',
        safeSql: (
          _params,
          where,
          orderBy,
          _runIndexAdvisor = false,
          _filterIndexAdvisor = false
        ) => safeSql`
        -- reports-query-performance-metrics
        set search_path to public, extensions;

        SELECT
          COALESCE(ROUND(AVG(statements.rows::numeric / NULLIF(statements.calls, 0)), 1), 0) as avg_rows_per_call,
          COUNT(*) FILTER (WHERE statements.total_exec_time + statements.total_plan_time > 1000) as slow_queries,
          COALESCE(
            ROUND(
              SUM(statements.shared_blks_hit) * 100.0 /
              NULLIF(SUM(statements.shared_blks_hit + statements.shared_blks_read), 0),
              2
            ), 0
          ) || '%' as cache_hit_rate
        FROM pg_stat_statements as statements
        -- skip queries that were never actually executed
        WHERE statements.calls > 0 ${where ? rewriteWhereToAnd(where) : safeSql``}
        ${orderBy || safeSql``}`,
      },
    },
  },
  [Presets.DATABASE]: {
    title: 'database',
    queries: {
      largeObjects: {
        queryType: 'db',
        safeSql: (_) => safeSql`-- reports-database-large-objects
SELECT
        SCHEMA_NAME,
        relname,
        table_size
      FROM
        (SELECT
          pg_catalog.pg_namespace.nspname AS SCHEMA_NAME,
          relname,
          pg_total_relation_size(pg_catalog.pg_class.oid) AS table_size
        FROM pg_catalog.pg_class
        JOIN pg_catalog.pg_namespace ON relnamespace = pg_catalog.pg_namespace.oid
        ) t
      WHERE SCHEMA_NAME NOT LIKE 'pg_%'
      ORDER BY table_size DESC
      LIMIT 5;`,
      },
    },
  },
}

export const DEPRECATED_REPORTS = [
  'total_realtime_ingress',
  'total_rest_options_requests',
  'total_auth_ingress',
  'total_auth_get_requests',
  'total_auth_post_requests',
  'total_auth_patch_requests',
  'total_auth_options_requests',
  'total_storage_options_requests',
  'total_storage_patch_requests',
  'total_options_requests',
  'total_rest_ingress',
  'total_rest_get_requests',
  'total_rest_post_requests',
  'total_rest_patch_requests',
  'total_rest_delete_requests',
  'total_storage_get_requests',
  'total_storage_post_requests',
  'total_storage_delete_requests',
  'total_auth_delete_requests',
  'total_get_requests',
  'total_patch_requests',
  'total_post_requests',
  'total_ingress',
  'total_delete_requests',
]

export const EDGE_FUNCTION_REGIONS = [
  {
    key: 'ap-northeast-1',
    label: 'Tokyo',
  },
  {
    key: 'ap-northeast-2',
    label: 'Seoul',
  },
  {
    key: 'ap-south-1',
    label: 'Mumbai',
  },
  {
    key: 'ap-southeast-1',
    label: 'Singapore',
  },
  {
    key: 'ap-southeast-2',
    label: 'Sydney',
  },
  {
    key: 'ca-central-1',
    label: 'Canada Central',
  },
  {
    key: 'us-east-1',
    label: 'N. Virginia',
  },
  {
    key: 'us-west-1',
    label: 'N. California',
  },
  {
    key: 'us-west-2',
    label: 'Oregon',
  },
  {
    key: 'eu-central-1',
    label: 'Frankfurt',
  },
  {
    key: 'eu-west-1',
    label: 'Ireland',
  },
  {
    key: 'eu-west-2',
    label: 'London',
  },
  {
    key: 'eu-west-3',
    label: 'Paris',
  },
  {
    key: 'sa-east-1',
    label: 'São Paulo',
  },
] as const
