<cfimport prefix="m" taglib="../lib"/>
<cfimport prefix="d" taglib="../lib/data"/>

<cfparam name="ATTRIBUTES.dt_finish" type="date" default=#createDateTime(year(Now()),month(Now()),1,0,0,0)#/>
<cfparam name="ATTRIBUTES.dt_start" type="date" default=#dateAdd('m',-1,ATTRIBUTES.dt_finish)#/>
<cfparam name="ATTRIBUTES.output" type="string" default="report"/>
<cfparam name="ATTRIBUTES.debug" type="boolean" default=false/>

<cfset hours=dateDiff('h',dt_start,dt_finish)/>
<cfset tenant_wz_index=val(mid(request.auth.wz,3,5))/><!--- cut off WZ --->


<!--- QoQ does not support join syntax, at least of Lucee 5.4--->


<!--- Для начала выкатываем просто кусок каталога, не фильтруя по спеке (которой иногда нет) --->
<cfquery name="qSpec">
	select * from (
	values
	 ('Объектное хранилище S3 CEPH','Дисковое пространство: Объем хранения','paas.s3.ceph.vol-m','ГБайт',1.80,0)
	,('Объектное хранилище S3 CEPH','Исходящий трафик','paas.s3.ceph.trf-m','ГБайт',1.50,0)
	,('Объектное хранилище S3 CEPH','Запросы GET, HEAD, OPTIONS','paas.s3.ceph.get-m','10тыс.шт.',0.35,0)
	,('Объектное хранилище S3 CEPH','Запросы PUT, POST, PATCH','paas.s3.ceph.put-m','10тыс.шт.',4.50,0)
	) as 
	s (svc, component, code, unit, price, discount)
	order by code
</cfquery>


<!--- Нужно еще реализовать в модели данных политики бесплатного минимума --->
<cfquery name="qComputing">
	select 'WZ'||to_char(tenant.wzcode,'FM00000') as wz, vdc.name as vdc_name, 
	case 
		when vdc.name like '%-v1cl1%' then 'iaas.ngc.i29' 
		when vdc.name like '%-v1cl2%' then 'iaas.ngc.i31' 
		when vdc.name like '%-v1cl4%' then 'iaas.ngc.a28' 
		when vdc.name like '%-v1cl6%' then 'iaas.ngc.i28' 
		else '['||vdc.name||']' end as code,
	sum(cpu_used/cpu_speed)/4. as core_h,
	sum(mem_used)/1024/4. as gb_h
	from ngcloud_ru.capacity_resource 
	join ngcloud_ru.vdc on capacity_resource.vdc_id=vdc.id 
	join ngcloud_ru.tenant on tenant.id=vdc.tenant_id 
	where tenant.wzcode = <cfqueryparam cfsqltype="cf_sql_integer" value=#tenant_wz_index#/> 
	AND capacity_resource.timestamp >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_start#/> 
	AND capacity_resource.timestamp < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_finish#/> 
	group by tenant.wzcode, vdc.name 
	order by tenant.wzcode, vdc.name;
</cfquery>

<cfif (ATTRIBUTES.debug)>
	<cfdump var=#qComputing#/>
	<cfflush/>
</cfif>

<cfquery name="qComputingAge">
	select max(capacity_resource.timestamp) as dt_load from ngcloud_ru.capacity_resource
</cfquery>


<!--- переделать storage_profile_types с расшифровкой ssd, sata, можно прямо до каталожного кода --->
<cfquery name="qStorage">
	select 'WZ'||to_char(tenant.wzcode,'FM00000') as wz, vdc.name as vdc_name, 
	case 
		WHEN vdc.name LIKE '%-v1cl1%' THEN 'iaas.ngc.i29' 
		WHEN vdc.name LIKE '%-v1cl2%' THEN 'iaas.ngc.i31' 
		WHEN vdc.name LIKE '%-v1cl4%' THEN 'iaas.ngc.a28' 
		WHEN vdc.name LIKE '%-v1cl6%' THEN 'iaas.ngc.i28' 
		ELSE '['||vdc.name||']' END 
	|| CASE 
		WHEN storage_profile_types.name ILIKE '%-SSD%' THEN '.ssd-m'
		WHEN storage_profile_types.name ILIKE '%-SAS' THEN '.sas-m'
		WHEN storage_profile_types.name ILIKE '%-SATA' THEN '.sata-m'
		ELSE '.['|| storage_profile_types.name ||']' END 
	as code,
	storage_profile_types.name, -- *** это не тип, а профайл
	sum("limit")/1024./4 as gb_h_limit, -- 4 потому, что сбор раз в 15 минут
	sum(used)/1024./4 as gb_h_used
	from ngcloud_ru.capacity_storage
	join ngcloud_ru.vdc on capacity_storage.vdc_id=vdc.id 
	join ngcloud_ru.tenant on tenant.id=vdc.tenant_id 
	join ngcloud_ru.storage_profile_types on capacity_storage.storage_profile_types_id=storage_profile_types.id
	where tenant.wzcode = <cfqueryparam cfsqltype="cf_sql_integer" value=#tenant_wz_index#/>
	AND capacity_storage.timestamp >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_start#/>
	AND capacity_storage.timestamp < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_finish#/> 
	group by tenant.wzcode, vdc.name, storage_profile_types.name 
	order by tenant.wzcode, vdc.name, storage_profile_types.name;
</cfquery>
<cfquery name="qStorageAge" datasource="rpt">
	select max(capacity_storage.timestamp) as dt_load from ngcloud_ru.capacity_storage
</cfquery>

<cfif (ATTRIBUTES.debug)>
	<cfdump var=#qStorage#/>
	<cfflush/>
</cfif>

<!--- 
"placement"	"size_gb"	"get_10k"	"put_10k"	"bytes_sent_gb"
HOT_FREE_LIMIT	1	10	1	100 
--->
<!--- надо дисконтировать не ГБ-часы а ГБ-месяцы --->
<cfquery name="qS3Vol">
	select /* *** ниже дублирование кода агрегации - round ceil etc, обратить внимание при правке */
	 (sum(bucket_stat.usage_rgw_main_size_actual)/<cfqueryparam cfsqltype="cf_sql_integer" value=#hours#/>) as vol_B
	,ceil(sum(bucket_stat.usage_rgw_main_size_actual)/<cfqueryparam cfsqltype="cf_sql_integer" value=#hours#/>/1024/1024/1024) as vol_GB
	,greatest(ceil(sum(bucket_stat.usage_rgw_main_size_actual)/<cfqueryparam cfsqltype="cf_sql_integer" value=#hours#/>
	/1024/1024/1024)- 
	case when bucket_stat.placement_id = 1 then 1 else 0 end, 0) as vol_GB_free_tier_subtracted /*считается не в точности так, как в функции*/	
	,case 
		when bucket_stat.placement_id = 1 then 'paas.s3.ceph'
		when bucket_stat.placement_id = 2 then 'paas.s3.cphc'
		else '['|| TO_CHAR(bucket_stat.placement_id,'FM9') ||']' end as code
	--,bucket_stat.placement_id
	,'WZ'||lpad(bucket_stat.owner, 5, '0') as wz -- *** здесь не число, а строка, поэтому другая формула обратной сборки WZ
	
	from s3billing.bucket_stat 
	join s3billing.placement ON s3billing.placement.id=bucket_stat.placement_id 
	join s3billing.bucket_info ON bucket_info.id=bucket_stat.bucket_id 
	where bucket_stat.placement_id in (1,2) 
	AND bucket_stat.owner = <cfqueryparam cfsqltype="cf_sql_varchar" value=#tenant_wz_index#/>
	AND bucket_stat.timestamp_addition >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_start#/> 
	AND bucket_stat.timestamp_addition < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_finish#/>
	group by bucket_stat.owner, bucket_stat.placement_id
	order by bucket_stat.owner, bucket_stat.placement_id;
</cfquery>

<cfif (ATTRIBUTES.debug)>
	<cfdump var=#qS3Vol#/>
	<cfflush/>
</cfif>

<cfquery name="qS3VolAge">
	select max(timestamp_addition) as dt_load from s3billing.bucket_stat
</cfquery>

<cfquery name="qS3OpsTrf">
select	
	sum(
		CASE WHEN 
		(category.name LIKE 'get%'
          OR category.name LIKE 'head%'
          OR category.name LIKE 'options%'
		) THEN ops ELSE 0 END
		) as get 
	,ceil(sum(
		CASE WHEN 
			(category.name LIKE 'get%'
			  OR category.name LIKE 'head%'
			  OR category.name LIKE 'options%'
			) THEN ops ELSE 0 END
		)/10000) as get_10k
	,greatest(ceil(sum(
			CASE WHEN 
				(category.name LIKE 'get%'
				  OR category.name LIKE 'head%'
				  OR category.name LIKE 'options%'
				) THEN ops ELSE 0 END
		)/10000) - CASE WHEN bucket_info.placement_id = 1 THEN 10 ELSE 0 END, 0
	 ) as get_10k_free_tier_subtracted
		
	,sum(
		CASE WHEN 
			(category.name LIKE 'put%'
			  OR category.name LIKE 'post%'
			  OR category.name LIKE 'patch%'
			  OR category.name LIKE 'list%'
			 ) THEN ops ELSE 0 END
	 ) as put
	,ceil(sum(
		CASE WHEN 
			(category.name LIKE 'put%'
			  OR category.name LIKE 'post%'
			  OR category.name LIKE 'patch%'
			  OR category.name LIKE 'list%'
			 ) THEN ops ELSE 0 END
	 )/10000) as put_10k
	,greatest(ceil(sum(
			CASE WHEN 
			(category.name LIKE 'put%'
			  OR category.name LIKE 'post%'
			  OR category.name LIKE 'patch%'
			  OR category.name LIKE 'list%'
			) THEN ops ELSE 0 END
		)/10000) - CASE WHEN bucket_info.placement_id = 1 THEN 1 ELSE 0 END, 0
	 ) as put_10k_free_tier_subtracted
	 
	,(sum(bytes_sent)) as bytes_sent
	,ceil(sum(bytes_sent)/1024/1024/1024) as bytes_sent_GB
	,greatest(ceil(sum(bytes_sent)/1024/1024/1024) - CASE WHEN bucket_info.placement_id = 1 THEN 100 ELSE 0 END, 0
	) as bytes_sent_GB_free_tier_subtracted
	
	,case 
		when bucket_info.placement_id = 1 then 'paas.s3.ceph'
		when bucket_info.placement_id = 2 then 'paas.s3.cphc'
		else '['|| TO_CHAR(bucket_info.placement_id,'FM9') ||']' end as code --*** зачем делать там ключ bigint
	,bucket_info.placement_id
	--category.name, bucket_info.name
	,'WZ'||lpad(user_info.name, 5, '0') as wz
	from s3billing.usage_bucket_by_user 
	join s3billing.user_info on usage_bucket_by_user.user_id=user_info.id  
	join s3billing.category on usage_bucket_by_user.category_id=category.id
	join s3billing.bucket_info on usage_bucket_by_user.bucketid=bucket_info.id 
	join s3billing.placement on bucket_info.placement_id=placement.id 
	where 1=1
	AND user_info.name = <cfqueryparam cfsqltype="cf_sql_varchar" value=#tenant_wz_index#/>
	AND usage_bucket_by_user.time >= <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_start#/> 
	AND usage_bucket_by_user.time < <cfqueryparam cfsqltype="cf_sql_timestamp" value=#ATTRIBUTES.dt_finish#/>
	group by user_info.name, bucket_info.placement_id
	order by user_info.name, bucket_info.placement_id;
</cfquery>

<cfif (ATTRIBUTES.debug)>
	<cfdump var=#qS3OpsTrf#/>
	<cfflush/>
</cfif>

<cfquery name="qS3OpsTrfAge">
	select max(time) as dt_load from s3billing.usage_bucket_by_user 
</cfquery>


<cfquery name="qUnifiedMetric" dbType="query">
select wz, code || '.vcpu-m' as code, core_h as raw_metric, core_h as metric, core_h as chargeable_metric from qComputing
union all
select wz, code || '.ram-m' as code, gb_h as raw_metric, gb_h as metric, gb_h as chargeable_metric from qComputing
union all
select wz, code, gb_h_used as raw_metric, gb_h_used as metric, gb_h_used as chargeable_metric from qStorage
union all
select wz, code || '.vol-m', vol_b as raw_metric, vol_gb as metric, vol_GB_free_tier_subtracted as chargeable_metric from qS3Vol
union all
select wz, code || '.get-m', get as raw_metric, get_10k as metric, get_10k_free_tier_subtracted as chargeable_metric from qS3OpsTrf
union all
select wz, code || '.put-m', put as raw_metric, put_10k as metric, put_10k_free_tier_subtracted as chargeable_metric from qS3OpsTrf
union all
select wz, code || '.trf-m', bytes_sent as raw_metric, bytes_sent_gb as metric, bytes_sent_gb_free_tier_subtracted as chargeable_metric from qS3OpsTrf
</cfquery>

<cfif (ATTRIBUTES.debug)>
	<cfdump var=#qUnifiedMetric#/>
	<cfflush/>
</cfif>

<cfquery name="qCharge" dbType="query">
SELECT 
<d:field_set titleMapOut="titleMap" lengthOut="fieldCount">
	<d:field title="Артикул">s.code</d:field>
	<d:field title="Услуга">s.svc</d:field>
	<d:field title="Компонент">s.component</d:field>
	<d:field title="Кол-во (метрика)" cfSqlType="CF_SQL_NUMERIC">m.chargeable_metric</d:field>
	<d:field title="Ед.изм.">s.unit</d:field>
	<d:field title="Цена &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">s.price*(100-s.discount)/100 as discounted_price</d:field>
	<d:field title="Стоимость &##8381; с НДС" cfSqlType="CF_SQL_NUMERIC">s.price*(100-s.discount)/100*m.chargeable_metric as charge</d:field>
<!--- 	<d:field title="Дата НОУ" cfSqlType="CF_SQL_TIMESTAMP">s.dt_from</d:field> --->
<!--- 	<d:field title="Дата оконч." cfSqlType="CF_SQL_TIMESTAMP">s.dt_to</d:field>
	<d:field title="Ключ строки">s.line_key</d:field> --->
	<d:field title="GPL с НДС" cfSqlType="CF_SQL_NUMERIC">s.price</d:field>
	<d:field title="Скидка%" cfSqlType="CF_SQL_NUMERIC">s.discount</d:field>
	<d:field title="Сырая метрика" cfSqlType="CF_SQL_NUMERIC">m.raw_metric</d:field>
	<d:field title="Приведенная метрика" cfSqlType="CF_SQL_NUMERIC">m.metric</d:field>

<!--- 	<d:field title="Клиентс. назв.">s.user_description</d:field> --->
</d:field_set>
FROM qSpec as s, qUnifiedMetric as m 
WHERE m.wz=<cfqueryparam cfsqltype="cf_sql_varchar" value=#request.auth.wz#/> AND s.code=m.code
order by s.code
</cfquery>

<cfset var report={}/>

<cfset report.qComputingAge = qComputingAge/>
<cfset report.qStorageAge = qStorageAge/>
<cfset report.qS3VolAge = qS3VolAge/>
<cfset report.qS3OpsTrfAge = qS3OpsTrfAge/>
<cfset report.qCharge = qCharge/>
<cfset report.chargeTitleMap = titleMap/>
<cfset report.chargeFieldCount = fieldCount/>

<cfset "CALLER.#ATTRIBUTES.output#" = report/>

<cfexit method="exittag"/>