

-- Cleanup schema public first.

---DROP SCHEMA IF EXISTS public CASCADE;

-- Recreate schema public.

CREATE SCHEMA public if not exists;

-- Set ownership to meta_user
ALTER SCHEMA public OWNER TO meta_user;

-- ============================================================================
-- EXTENSIONS
-- ============================================================================
-- Create TimescaleDB extension if it doesn't exist
-- This provides time_bucket() and other time-series functions

--CREATE EXTENSION IF NOT EXISTS timescaledb;

-- ============================================================================
-- METADATA TABLE
-- ============================================================================
-- This table stores account mappings and identifiers
-- Data is loaded from metadata.yaml file


CREATE TABLE IF NOT EXISTS public.account_metadata (
    id SERIAL PRIMARY KEY,
    label VARCHAR(255) NOT NULL,
    meta_account_id VARCHAR(100),
    google_account_id VARCHAR(100),
    alpinebits_hotel_code VARCHAR(100),
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),

    -- Ensure at least one account ID is provided
    CONSTRAINT at_least_one_account_id CHECK (
        meta_account_id IS NOT NULL OR
        google_account_id IS NOT NULL OR
        alpinebits_hotel_code IS NOT NULL
    )
);

-- ============================================================================
-- GEOTARGETS TABLE
-- ============================================================================
-- This table stores Google Ads geotarget metadata for location targeting
-- Data is loaded from geotargets CSV file

CREATE TABLE IF NOT EXISTS public.geotargets (
    criteria_id INTEGER PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    canonical_name VARCHAR(500),
    parent_id INTEGER,
    country_code VARCHAR(2),
    target_type VARCHAR(50),
    status VARCHAR(20),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- Permission grants for Grafana user

GRANT USAGE ON SCHEMA public TO grafana;

-- Grant SELECT on all existing tables and views in the schema
GRANT SELECT ON ALL TABLES IN SCHEMA public TO grafana;

-- Grant SELECT on all future tables and views in the schema
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO grafana;



-- ============================================================================
-- VIEWS
-- ============================================================================
-- All views below reference data in separate schemas (meta, google, etc.)
-- Add your view definitions here...



DROP VIEW IF EXISTS campaign_insights CASCADE;

-- general campaign insights view

CREATE  VIEW campaign_insights AS
 SELECT date_start AS "time",
    account_id AS account_id,
    campaign_id,
	campaign_name,
	objective,
    impressions,
    clicks,
    spend,
    reach,
    ctr,
    cpc,
    cpm,
    cpp,
    frequency,
    ( SELECT (jsonb_array_elements.value ->> 'value'::text)::numeric AS "numeric"
           FROM jsonb_array_elements(customcampaign_insights.actions) jsonb_array_elements(value)
          WHERE (jsonb_array_elements.value ->> 'action_type'::text) = 'link_click'::text) AS link_click,
    ( SELECT (jsonb_array_elements.value ->> 'value'::text)::numeric AS "numeric"
           FROM jsonb_array_elements(customcampaign_insights.actions) jsonb_array_elements(value)
          WHERE (jsonb_array_elements.value ->> 'action_type'::text) = 'landing_page_view'::text) AS landing_page_view,
    ( SELECT (jsonb_array_elements.value ->> 'value'::text)::numeric AS "numeric"
           FROM jsonb_array_elements(customcampaign_insights.actions) jsonb_array_elements(value)
          WHERE (jsonb_array_elements.value ->> 'action_type'::text) = 'lead'::text) AS lead
   FROM meta.customcampaign_insights;

-- age and gender


DROP MATERIALIZED VIEW IF EXISTS campaign_insights_by_gender_and_age CASCADE;

CREATE MATERIALIZED VIEW campaign_insights_by_gender_and_age AS
SELECT date_start AS "time",
    account_id AS account_id,
    campaign_id,
    campaign_name,
    gender,
	age,
    impressions,
    clicks,
    spend,
    reach,
    frequency,
    ctr,
    cpc,
    cpm,
    (SELECT (value->>'value')::numeric
     FROM jsonb_array_elements(actions)
     WHERE value->>'action_type' = 'link_click') AS link_click,
    (SELECT (value->>'value')::numeric
     FROM jsonb_array_elements(actions)
     WHERE value->>'action_type' = 'landing_page_view') AS landing_page_view,
    (SELECT (value->>'value')::numeric
     FROM jsonb_array_elements(actions)
     WHERE value->>'action_type' = 'lead') AS lead

   FROM meta.custom_campaign_gender;

-- Create indexes for efficient querying
CREATE INDEX idx_campaign_insights_by_gender_and_age_date
    ON campaign_insights_by_gender_and_age(time);

CREATE UNIQUE INDEX idx_campaign_insights_by_gender_and_age_unique
    ON campaign_insights_by_gender_and_age(time, campaign_id, gender, age);

REFRESH MATERIALIZED VIEW CONCURRENTLY campaign_insights_by_gender_and_age;


DROP VIEW IF EXISTS campaign_insights_by_gender CASCADE;

create view campaign_insights_by_gender as 
Select time, 
sum(clicks) as clicks, 
sum(link_click) as link_click,
sum(lead) as lead,
sum(landing_page_view) as landing_page_view,
sum(spend) as spend, 
sum(reach) as reach, 
sum(impressions) as impressions, 
gender,
campaign_id,
    campaign_name,
account_id 
from campaign_insights_by_gender_and_age 
group by time, gender, account_id, campaign_id, campaign_name;

DROP VIEW IF EXISTS campaign_insights_by_age CASCADE;

create view campaign_insights_by_age as 
Select time, 
sum(clicks) as clicks, 
sum(link_click) as link_click,
sum(lead) as lead,
sum(landing_page_view) as landing_page_view,
sum(spend) as spend, 
sum(reach) as reach, 
sum(impressions) as impressions, 
age,
campaign_id,
    campaign_name,
account_id 
from campaign_insights_by_gender_and_age 
group by time, age, account_id, campaign_id, campaign_name;


-- device

DROP  VIEW IF EXISTS campaign_insights_by_device_flattened CASCADE;

CREATE VIEW campaign_insights_by_device_flattened AS
SELECT date_start AS "time",
    account_id AS account_id,
    campaign_id,
    device_platform,
    impressions,
    clicks,
    spend,
    reach,
    frequency,

    (SELECT (value->>'value')::numeric
     FROM jsonb_array_elements(actions)
     WHERE value->>'action_type' = 'link_click') AS link_click,
    (SELECT (value->>'value')::numeric
     FROM jsonb_array_elements(actions)
     WHERE value->>'action_type' = 'landing_page_view') AS landing_page_view,
    (SELECT (value->>'value')::numeric
     FROM jsonb_array_elements(actions)
     WHERE value->>'action_type' = 'lead') AS lead
     
   FROM meta.custom_campaign_device;

-- country

--- campaign insights by country

DROP  VIEW IF EXISTS campaign_insights_by_country_flattened CASCADE;

CREATE VIEW campaign_insights_by_country_flattened AS
 SELECT date_start AS "time",
    account_id AS account_id,
    campaign_id,
    country,
    impressions,
    clicks,
    spend,
    reach,
    frequency,
    ctr,
    cpc,
    cpm,

    (SELECT (value->>'value')::numeric
     FROM jsonb_array_elements(actions)
     WHERE value->>'action_type' = 'link_click') AS link_click,
    (SELECT (value->>'value')::numeric
     FROM jsonb_array_elements(actions)
     WHERE value->>'action_type' = 'landing_page_view') AS landing_page_view,
    (SELECT (value->>'value')::numeric
     FROM jsonb_array_elements(actions)
     WHERE value->>'action_type' = 'lead') AS lead

   FROM meta.custom_campaign_country;
-- ============================================================================

-- account views


DROP VIEW IF EXISTS account_insights_by_gender CASCADE;

CREATE VIEW account_insights_by_gender AS
SELECT 
    time, 
    account_id, 
    gender, 
    SUM(impressions) AS impressions, 
    SUM(clicks) AS clicks,
    SUM(spend) AS spend, 
    SUM(link_click) AS link_click, 
    SUM(landing_page_view) AS landing_page_view,
    SUM(lead) AS lead
FROM campaign_insights_by_gender
GROUP BY time, account_id, gender;


DROP VIEW IF EXISTS account_insights_by_device CASCADE;

CREATE VIEW account_insights_by_device AS
SELECT 
    time, 
    account_id, 
    device_platform, 
    SUM(impressions) AS impressions, 
    SUM(clicks) AS clicks,
    SUM(spend) AS spend, 
    SUM(link_click) AS link_click, 
    SUM(landing_page_view) AS landing_page_view,
    SUM(lead) AS lead
FROM campaign_insights_by_device_flattened
GROUP BY time, account_id, device_platform;


DROP VIEW IF EXISTS account_insights_by_age CASCADE;

CREATE VIEW account_insights_by_age AS
SELECT 
    time, 
    account_id, 
    age, 
    SUM(impressions) AS impressions, 
    SUM(clicks) AS clicks,
    SUM(spend) AS spend, 
    SUM(link_click) AS link_click, 
    SUM(landing_page_view) AS landing_page_view,
    SUM(lead) AS lead
FROM campaign_insights_by_age
GROUP BY time, account_id, age;

DROP VIEW IF EXISTS account_insights_by_gender_and_age CASCADE;

CREATE VIEW account_insights_by_gender_and_age AS
SELECT
    time,
    account_id,
    gender,
    age,
    SUM(impressions) AS impressions,
    SUM(clicks) AS clicks,
    SUM(spend) AS spend,
    SUM(link_click) AS link_click,
    SUM(landing_page_view) AS landing_page_view,
    SUM(lead) AS lead
FROM campaign_insights_by_gender_and_age
GROUP BY time, account_id, age, gender;

-- Aggregates campaign insights by country to account level
DROP VIEW IF EXISTS account_insights_by_country CASCADE;

CREATE VIEW account_insights_by_country AS
SELECT
    time,
    account_id,
    country,
    SUM(impressions) AS impressions,
    SUM(clicks) AS clicks,
    SUM(spend) AS spend,
    SUM(link_click) AS link_click,
    SUM(landing_page_view) AS landing_page_view,
    SUM(lead) AS lead
FROM campaign_insights_by_country_flattened
GROUP BY time, account_id, country;

DROP VIEW IF EXISTS account_insights;
CREATE VIEW account_insights AS
SELECT 
    time, 
    account_id, 
    SUM(impressions) AS impressions, 
    SUM(clicks) AS clicks,
    SUM(spend) AS spend, 
    SUM(link_click) AS link_click, 
    SUM(landing_page_view) AS landing_page_view,
    SUM(lead) AS lead,
    SUM(reach) as reach,
    AVG(frequency) as frequency,
    avg(cpc) as cpc,
    avg(cpm) as cpm,
    avg(cpp) as cpp,
    avg(ctr) as ctr

FROM campaign_insights
group by time, account_id;

DROP MATERIALIZED VIEW IF EXISTS ads_insights CASCADE;
-- ads view
CREATE MATERIALIZED VIEW ads_insights AS
SELECT 
    date_start AS time,
	name as ad_name,
    ins.account_id,
    ins.ad_id,
    ins.adset_id,
    ins.campaign_id,
    impressions,
    reach,
    clicks,     
    (SELECT SUM((elem.value ->> 'value')::numeric)
     FROM jsonb_array_elements(ins.actions) AS elem
     WHERE (elem.value ->> 'action_type') = 'link_click') AS link_click,
    (SELECT SUM((elem.value ->> 'value')::numeric)
     FROM jsonb_array_elements(ins.actions) AS elem
     WHERE (elem.value ->> 'action_type') = 'lead') AS lead,
    (SELECT sum((value->>'value')::numeric)
     FROM jsonb_array_elements(actions)
     WHERE value->>'action_type' = 'landing_page_view') AS landing_page_view,
    spend,
    frequency,
    cpc,
    cpm,
    ctr,
    cpp
FROM meta.ads_insights ins
	join meta.ads as a on a.id = ins.ad_id;

-- Create indexes for efficient querying
CREATE INDEX idx_ads_insights
    ON ads_insights(time, ad_id);

CREATE UNIQUE INDEX ads_insights_unique
    ON ads_insights(time, account_id, ad_id);

REFRESH MATERIALIZED VIEW CONCURRENTLY ads_insights;

DROP VIEW IF EXISTS adset_insights CASCADE;

CREATE VIEW adset_insights AS
SELECT 
    time,
    i.account_id,
	name as adset_name,
	i.adset_id,
	i.campaign_id,
    SUM(impressions) AS impressions, 
    SUM(clicks) AS clicks,
	sum(link_click) as link_click,
	sum(lead) as lead,
	sum(landing_page_view) as landing_page_view,
    SUM(spend) AS spend, 
	sum(reach),
    AVG(frequency) as frequency,
    avg(cpc) as cpc,
    avg(cpm) as cpm,
    avg(cpp) as cpp,
    avg(ctr) as ctr

FROM ads_insights as i left join meta.ad_sets as m on m.id = i.adset_id
group by time, i.account_id, i.adset_id, i.campaign_id, adset_name;


DROP VIEW IF EXISTS g_account_insights CASCADE;
CREATE VIEW g_account_insights AS
SELECT 
    time,
    google_account_id,
    clicks,
    impressions,
    interactions,
    cost_micros,
    cost_micros / 1000000.0 as cost,
    leads,
    engagements,
    customer_currency_code,
    account_name,
    
    -- CTR (Click-Through Rate)
    (clicks::numeric / impressions_nz) * 100 as ctr,
    
    -- CPM (Cost Per Mille) in micros and standard units
    (cost_micros::numeric / impressions_nz) * 1000 as cpm_micros,
    (cost_micros::numeric / impressions_nz) * 1000 / 1000000.0 as cpm,
    
    -- CPC (Cost Per Click) in micros and standard units
    cost_micros::numeric / clicks_nz as cpc_micros,
    cost_micros::numeric / clicks_nz / 1000000.0 as cpc,
    
    -- CPL (Cost Per Lead) in micros and standard units
    cost_micros::numeric / leads_nz as cpl_micros,
    cost_micros::numeric / leads_nz / 1000000.0 as cpl,
    
    -- Conversion Rate
    (leads::numeric / clicks_nz) * 100 as conversion_rate,
    
    -- Engagement Rate
    (engagements::numeric / impressions_nz) * 100 as engagement_rate
    
FROM (
    SELECT 
        segments_date as time, 
        customer_id as google_account_id, 
        sum(metrics_clicks) as clicks, 
        sum(metrics_impressions) as impressions, 
        sum(metrics_interactions) as interactions, 
        sum(metrics_cost_micros) as cost_micros,
        sum(metrics_conversions) as leads, 
        sum(metrics_engagements) as engagements,
        customer_currency_code,
        customer_descriptive_name as account_name,
        -- Null-safe denominators
        NULLIF(sum(metrics_clicks), 0) as clicks_nz,
        NULLIF(sum(metrics_impressions), 0) as impressions_nz,
        NULLIF(sum(metrics_conversions), 0) as leads_nz
    FROM google.account_performance_report
    GROUP BY google_account_id, time, customer_currency_code, account_name
) base;

DROP VIEW IF EXISTS g_account_insights_by_country CASCADE;

CREATE VIEW g_account_insights_by_country AS
select segments_date as time, customer_id as google_account_id, 
	g.metrics_clicks as clicks, 
	g.metrics_impressions as impressions,
	g.metrics_cost_micros as cost_micros,
	g.metrics_cost_micros / 1000000.0 as cost,
	g.metrics_conversions as conversions,
	g.metrics_conversions_value as conversion_value,
	metrics_interactions as interactions, 
	m.country_code
	from google.geo_view_with_metrics as g join geotargets as m on m.criteria_id = 
	g.geographic_view_country_criterion_id
	order by time;



DROP VIEW IF EXISTS g_account_insights_device CASCADE;
CREATE VIEW g_account_insights_device AS
SELECT 
    time,
    google_account_id,
    device,
    clicks,
    impressions,
    interactions,
    cost_micros,
    cost_micros / 1000000.0 as cost,
    leads,
    engagements,
    customer_currency_code,
    account_name,
    
    -- CTR (Click-Through Rate)
    (clicks::numeric / impressions_nz) * 100 as ctr,
    
    -- CPM (Cost Per Mille) in micros and standard units
    (cost_micros::numeric / impressions_nz) * 1000 as cpm_micros,
    (cost_micros::numeric / impressions_nz) * 1000 / 1000000.0 as cpm,
    
    -- CPC (Cost Per Click) in micros and standard units
    cost_micros::numeric / clicks_nz as cpc_micros,
    cost_micros::numeric / clicks_nz / 1000000.0 as cpc,
    
    -- CPL (Cost Per Lead) in micros and standard units
    cost_micros::numeric / leads_nz as cpl_micros,
    cost_micros::numeric / leads_nz / 1000000.0 as cpl,
    
    -- Conversion Rate
    (leads::numeric / clicks_nz) * 100 as conversion_rate,
    
    -- Engagement Rate
    (engagements::numeric / impressions_nz) * 100 as engagement_rate
    
FROM (
    SELECT 
        segments_date as time, 
        customer_id as google_account_id, 
        segments_device as device,
        sum(metrics_clicks) as clicks, 
        sum(metrics_impressions) as impressions, 
        sum(metrics_interactions) as interactions, 
        sum(metrics_cost_micros) as cost_micros,
        sum(metrics_conversions) as leads, 
        sum(metrics_engagements) as engagements,
        customer_currency_code,
        customer_descriptive_name as account_name,
        -- Null-safe denominators
        NULLIF(sum(metrics_clicks), 0) as clicks_nz,
        NULLIF(sum(metrics_impressions), 0) as impressions_nz,
        NULLIF(sum(metrics_conversions), 0) as leads_nz
    FROM google.account_performance_report
    GROUP BY google_account_id, time, customer_currency_code, account_name, segments_device
) base;


-- Google campaign insights aggregated from campaign_metrics
DROP VIEW IF EXISTS g_campaign_insights CASCADE;

CREATE VIEW g_campaign_insights AS
SELECT
    segments_date as time,
    campaign_id,
	customer_id as google_account_id,
    campaign_name,
    SUM(metrics_clicks) as clicks,
    SUM(metrics_impressions) as impressions,
    SUM(metrics_interactions) as interactions,
    SUM(metrics_cost_micros) as cost_micros,
    SUM(metrics_cost_micros) / 1000000.0 as cost,
    SUM(metrics_conversions) as conversions,
    SUM(metrics_all_conversions) as all_conversions,
    SUM(metrics_conversions_value) as conversions_value,

    -- CTR (Click-Through Rate)
    (SUM(metrics_clicks)::numeric / NULLIF(SUM(metrics_impressions), 0)) * 100 as ctr,

    -- CPM (Cost Per Mille)
    (SUM(metrics_cost_micros)::numeric / NULLIF(SUM(metrics_impressions), 0)) * 1000 / 1000000.0 as cpm,

    -- CPC (Cost Per Click)
    SUM(metrics_cost_micros)::numeric / NULLIF(SUM(metrics_clicks), 0) / 1000000.0 as cpc,

    -- Cost per conversion
    SUM(metrics_cost_micros)::numeric / NULLIF(SUM(metrics_conversions), 0) / 1000000.0 as cost_per_conversion

FROM google.campaign_metrics
GROUP BY customer_id, segments_date, campaign_id, campaign_name
ORDER BY segments_date;

-- ============================================================================
-- UNIFIED VIEW
DROP VIEW IF EXISTS unified_account_insights CASCADE;

CREATE VIEW unified_account_insights AS
SELECT 
  COALESCE(g.time, m.time) as time,
	g.google_account_id::varchar as google_account_id,
	m.account_id as meta_account_id,
	
  SUM(COALESCE(g.impressions, 0) + COALESCE(m.impressions, 0)) as impressions,
	SUM(COALESCE(g.clicks, 0) + COALESCE(m.clicks, 0)) as clicks,
	SUM(COALESCE(g.clicks, 0) + COALESCE(m.link_click, 0)) as link_clicks,
	
	sum(g.leads + m.lead) as lead,
	SUM(COALESCE(g.cost, 0) + COALESCE(m.spend, 0)) as spend
	

FROM account_metadata as am
FULL OUTER JOIN g_account_insights as g ON g.google_account_id::varchar = am.google_account_id
FULL OUTER JOIN account_insights as m ON m.account_id = am.meta_account_id AND m.time = g.time
GROUP BY 1, 2, 3
ORDER BY 1;

-- Unified device-level insights combining Google and Meta data
DROP VIEW IF EXISTS unified_account_insights_by_device CASCADE;

CREATE VIEW unified_account_insights_by_device AS
-- Man verliert Tablet  und mobile-app als device type ober who cares. TV und so bei google werd a als mobile innigschmisse. Taucht lei olle heiligen zeiten auf
SELECT
  COALESCE(g.time, m.time) as time,
  g.google_account_id::varchar as google_account_id,
  m.account_id as meta_account_id,
  -- Normalize device types
  CASE 
    WHEN UPPER(COALESCE(g.device, m.device_platform)) IN ('DESKTOP') THEN 'DESKTOP'
    ELSE 'MOBILE'
  END as device_type,
  SUM(COALESCE(g.impressions, 0) + COALESCE(m.impressions, 0)) as impressions,
  SUM(COALESCE(g.clicks, 0) + COALESCE(m.clicks, 0)) as clicks,
  SUM(COALESCE(g.clicks, 0) + COALESCE(m.link_click, 0)) as link_clicks,
  SUM(COALESCE(g.cost, 0) + COALESCE(m.spend, 0)) as spend
FROM account_metadata as am
FULL OUTER JOIN g_account_insights_device as g 
  ON g.google_account_id::varchar = am.google_account_id
FULL OUTER JOIN account_insights_by_device as m 
  ON m.account_id = am.meta_account_id 
  AND m.time = g.time
  AND CASE 
        WHEN UPPER(g.device) IN ('DESKTOP') THEN 'DESKTOP'
        ELSE 'MOBILE'
      END = CASE 
        WHEN UPPER(m.device_platform) IN ('DESKTOP') THEN 'DESKTOP'
        ELSE 'MOBILE'
      END
GROUP BY 
  COALESCE(g.time, m.time), 
  g.google_account_id, 
  m.account_id, 
  CASE 
    WHEN UPPER(COALESCE(g.device, m.device_platform)) IN ('DESKTOP') THEN 'DESKTOP'
    ELSE 'MOBILE'
  END
ORDER BY 1, device_type;

-- Unified gender-level insights combining Google and Meta data for better audience analysis
DROP VIEW IF EXISTS unified_account_insights_by_gender CASCADE;

CREATE VIEW unified_account_insights_by_gender AS
SELECT
  m.time,
  m.account_id as meta_account_id,

  m.gender,
  SUM(m.impressions) as impressions,
  SUM(m.clicks) as clicks,
  SUM(m.spend) as spend,
  SUM(m.link_click) as link_clicks,
  SUM(m.lead) as leads

FROM account_insights_by_gender as m
GROUP BY m.time, m.account_id, m.gender
ORDER BY m.time;

DROP VIEW IF EXISTS unified_account_insights_by_country CASCADE;

CREATE VIEW unified_account_insights_by_country AS
SELECT
  COALESCE(g.time, m.time) as time,
  g.google_account_id::varchar as google_account_id,
  m.account_id as meta_account_id,
  COALESCE(g.country_code, m.country) as country_code,
  SUM(g.impressions) as google_impressions,
  SUM(m.impressions) as meta_impressions,
  SUM(COALESCE(g.impressions, 0) + COALESCE(m.impressions, 0)) as total_impressions,
  SUM(g.clicks) as google_clicks,
  SUM(m.clicks) as meta_clicks,
  SUM(COALESCE(g.clicks, 0) + COALESCE(m.clicks, 0)) as total_clicks,
  SUM(g.cost) as google_cost,
  SUM(m.spend) as meta_spend,
  SUM(COALESCE(g.cost, 0) + COALESCE(m.spend, 0)) as total_spend,
  SUM(m.link_click) as meta_link_clicks,
  SUM(m.lead) as meta_leads
FROM account_metadata as am
FULL OUTER JOIN g_account_insights_by_country as g 
  ON g.google_account_id::varchar = am.google_account_id
FULL OUTER JOIN account_insights_by_country as m 
  ON m.account_id = am.meta_account_id 
  AND m.time = g.time
  AND m.country = g.country_code
GROUP BY COALESCE(g.time, m.time), g.google_account_id, m.account_id, COALESCE(g.country_code, m.country)
ORDER BY COALESCE(g.time, m.time);


