begin;

create table if not exists analytics_sync_runs (
  id text primary key,
  workspace_id text not null,
  project_id text,
  provider text,
  date_from timestamptz not null,
  date_to timestamptz not null,
  timezone text not null,
  status text not null default 'queued'
    check (status in ('queued','running','succeeded','partial','failed','cancelled')),
  idempotency_key text not null check (char_length(idempotency_key) between 8 and 255),
  requested_by text,
  attempt_count integer not null default 0 check (attempt_count >= 0),
  next_attempt_at timestamptz,
  error_code text,
  error_message text,
  metrics_count integer not null default 0 check (metrics_count >= 0),
  created_at timestamptz not null default now(),
  started_at timestamptz,
  completed_at timestamptz,
  updated_at timestamptz not null default now(),
  constraint ck_analytics_sync_range check (date_to > date_from),
  constraint uq_analytics_sync_workspace_idempotency unique (workspace_id, idempotency_key)
);
create index if not exists ix_analytics_sync_workspace_status
  on analytics_sync_runs(workspace_id, status);
create index if not exists ix_analytics_sync_due
  on analytics_sync_runs(status, next_attempt_at);

create table if not exists analytics_metric_snapshots (
  id text primary key,
  workspace_id text not null,
  project_id text,
  social_post_id text references social_posts(id) on delete cascade,
  social_account_id text references social_accounts(id) on delete cascade,
  provider text not null,
  external_object_id text not null,
  metric_name text not null,
  metric_value double precision not null,
  bucket_start timestamptz not null,
  dimensions jsonb not null default '{}'::jsonb,
  source text not null default 'provider',
  collected_at timestamptz not null default now(),
  provider_updated_at timestamptz,
  constraint uq_analytics_metric_snapshot
    unique (workspace_id, provider, external_object_id, metric_name, bucket_start)
);
create index if not exists ix_analytics_metric_snapshots_workspace_bucket
  on analytics_metric_snapshots(workspace_id, bucket_start desc);

create table if not exists analytics_post_metrics (
  id text primary key,
  workspace_id text not null,
  project_id text,
  social_post_id text not null references social_posts(id) on delete cascade,
  social_post_target_id text not null references social_post_targets(id) on delete cascade,
  social_account_id text not null references social_accounts(id) on delete cascade,
  provider text not null,
  external_post_id text,
  metric_date timestamptz not null,
  views bigint,
  impressions bigint,
  likes bigint,
  comments bigint,
  shares bigint,
  engagement_rate double precision,
  dimensions jsonb not null default '{}'::jsonb,
  source text not null default 'provider',
  collected_at timestamptz not null default now(),
  provider_updated_at timestamptz,
  constraint ck_analytics_post_nonnegative check (
    (views is null or views >= 0) and
    (impressions is null or impressions >= 0) and
    (likes is null or likes >= 0) and
    (comments is null or comments >= 0) and
    (shares is null or shares >= 0) and
    (engagement_rate is null or engagement_rate >= 0)
  ),
  constraint uq_analytics_post_metric_bucket
    unique (workspace_id, social_post_target_id, metric_date)
);
create index if not exists ix_analytics_post_metrics_workspace_date
  on analytics_post_metrics(workspace_id, metric_date desc);
create index if not exists ix_analytics_post_metrics_project_date
  on analytics_post_metrics(workspace_id, project_id, metric_date desc);
create index if not exists ix_analytics_post_metrics_provider_date
  on analytics_post_metrics(workspace_id, provider, metric_date desc);

create table if not exists analytics_platform_metrics (
  id text primary key,
  workspace_id text not null,
  project_id text,
  social_account_id text not null references social_accounts(id) on delete cascade,
  provider text not null,
  metric_date timestamptz not null,
  posts_count integer not null default 0 check (posts_count >= 0),
  views bigint,
  impressions bigint,
  likes bigint,
  comments bigint,
  shares bigint,
  engagement_rate double precision,
  dimensions jsonb not null default '{}'::jsonb,
  source text not null default 'provider',
  collected_at timestamptz not null default now(),
  constraint uq_analytics_platform_metric_bucket
    unique (workspace_id, provider, social_account_id, metric_date)
);
create index if not exists ix_analytics_platform_metrics_workspace_date
  on analytics_platform_metrics(workspace_id, metric_date desc);

do $$
declare table_name text;
begin
  foreach table_name in array array[
    'analytics_sync_runs',
    'analytics_metric_snapshots',
    'analytics_post_metrics',
    'analytics_platform_metrics'
  ] loop
    execute format('alter table %I enable row level security', table_name);
    execute format('alter table %I force row level security', table_name);
    execute format('drop policy if exists analytics_workspace_isolation on %I', table_name);
    execute format(
      'create policy analytics_workspace_isolation on %I using (workspace_id = current_setting(''app.workspace_id'', true)) with check (workspace_id = current_setting(''app.workspace_id'', true))',
      table_name
    );
  end loop;
end $$;

commit;
