<cfprocessingdirective pageencoding="utf-8" />
<cfcomponent output="false">

  <cffunction name="ensureDemoStore" access="private" returntype="void" output="false">
    <cfif NOT structKeyExists(session, "demoReports")>
      <cfset session.demoReports = {} />
    </cfif>
    <cfif NOT structKeyExists(session, "demoReportIndex")>
      <cfset session.demoReportIndex = {} />
    </cfif>
    <cfif NOT structKeyExists(application, "demoNextReportId")>
      <cfset application.demoNextReportId = 1000 />
    </cfif>
  </cffunction>

  <cffunction name="nextDemoReportId" access="private" returntype="numeric" output="false">
    <cfset var nextId = 0 />
    <cflock scope="application" type="exclusive" timeout="3">
      <cfif NOT structKeyExists(application, "demoNextReportId")>
        <cfset application.demoNextReportId = 1000 />
      </cfif>
      <cfset nextId = application.demoNextReportId />
      <cfset application.demoNextReportId = application.demoNextReportId + 1 />
    </cflock>
    <cfreturn nextId />
  </cffunction>

  <cffunction name="newDemoReport" access="private" returntype="struct" output="false">
    <cfargument name="companyId" type="numeric" required="true" />
    <cfargument name="reportYear" type="numeric" required="true" />
    <cfargument name="userId" type="numeric" required="true" />
    <cfargument name="reportId" type="numeric" required="true" />

    <cfset var report = {
      id = arguments.reportId,
      company_id = arguments.companyId,
      module_key = "gas_sectors",
      report_year = arguments.reportYear,
      period_type = "calendar",
      total_sale_kwh = 0,
      resellers_kwh = 0,
      endconsumers_kwh = 0,
      grosscustomers_count = 0,
      grosscustomers_total_kwh = 0,
      sector_private_households_kwh = 0,
      sector_agriculture_kwh = 0,
      sector_industry_kwh = 0,
      sector_services_kwh = 0,
      sector_district_heating_kwh = 0,
      sector_other_kwh = 0,
      sector_fuel_kwh = 0,
      sector_wkk_kwh = 0,
      canton_zh_kwh = 0,
      canton_be_kwh = 0,
      canton_lu_kwh = 0,
      canton_ur_kwh = 0,
      canton_sz_kwh = 0,
      canton_ow_kwh = 0,
      canton_nw_kwh = 0,
      canton_gl_kwh = 0,
      canton_zg_kwh = 0,
      canton_fr_kwh = 0,
      canton_so_kwh = 0,
      canton_bs_kwh = 0,
      canton_bl_kwh = 0,
      canton_sh_kwh = 0,
      canton_ar_kwh = 0,
      canton_ai_kwh = 0,
      canton_sg_kwh = 0,
      canton_gr_kwh = 0,
      canton_ag_kwh = 0,
      canton_tg_kwh = 0,
      canton_ti_kwh = 0,
      canton_vd_kwh = 0,
      canton_vs_kwh = 0,
      canton_ne_kwh = 0,
      canton_ge_kwh = 0,
      canton_ju_kwh = 0,
      canton_abroad_kwh = 0,
      biogas_import_total_kwh = 0,
      biogas_import_lbg_kwh = 0,
      biogas_import_network_kwh = 0,
      biogas_import_certificate_kwh = 0,
      deviation_comment = "",
      is_completed = 0,
      status = "draft",
      updated_by = arguments.userId
    } />

    <cfreturn report />
  </cffunction>

  <cffunction name="reportStructToQuery" access="private" returntype="query" output="false">
    <cfargument name="reportData" type="struct" required="true" />

    <cfset var q = queryNew("id,company_id,module_key,report_year,period_type,total_sale_kwh,resellers_kwh,endconsumers_kwh,grosscustomers_count,grosscustomers_total_kwh,sector_private_households_kwh,sector_agriculture_kwh,sector_industry_kwh,sector_services_kwh,sector_district_heating_kwh,sector_other_kwh,sector_fuel_kwh,sector_wkk_kwh,canton_zh_kwh,canton_be_kwh,canton_lu_kwh,canton_ur_kwh,canton_sz_kwh,canton_ow_kwh,canton_nw_kwh,canton_gl_kwh,canton_zg_kwh,canton_fr_kwh,canton_so_kwh,canton_bs_kwh,canton_bl_kwh,canton_sh_kwh,canton_ar_kwh,canton_ai_kwh,canton_sg_kwh,canton_gr_kwh,canton_ag_kwh,canton_tg_kwh,canton_ti_kwh,canton_vd_kwh,canton_vs_kwh,canton_ne_kwh,canton_ge_kwh,canton_ju_kwh,canton_abroad_kwh,biogas_import_total_kwh,biogas_import_lbg_kwh,biogas_import_network_kwh,biogas_import_certificate_kwh,deviation_comment,is_completed,status,updated_by") />
    <cfset var col = "" />

    <cfset queryAddRow(q, 1) />
    <cfloop list="#q.columnList#" index="col">
      <cfif structKeyExists(arguments.reportData, col)>
        <cfset querySetCell(q, col, arguments.reportData[col], 1) />
      </cfif>
    </cfloop>

    <cfreturn q />
  </cffunction>

  <cffunction name="getDemoKeyByReportId" access="private" returntype="string" output="false">
    <cfargument name="reportId" type="numeric" required="true" />
    <cfset var reportKey = "" />
    <cfset var reportData = {} />
    <cfset ensureDemoStore() />
    <cfif structKeyExists(session.demoReportIndex, toString(arguments.reportId))>
      <cfreturn session.demoReportIndex[toString(arguments.reportId)] />
    </cfif>
    <!--- Self-heal index: find report by id if index was lost/reset. --->
    <cfloop collection="#session.demoReports#" item="reportKey">
      <cfset reportData = session.demoReports[reportKey] />
      <cfif isStruct(reportData) AND structKeyExists(reportData, "id") AND val(reportData.id) EQ arguments.reportId>
        <cfset session.demoReportIndex[toString(arguments.reportId)] = reportKey />
        <cfreturn reportKey />
      </cfif>
    </cfloop>
    <cfreturn "" />
  </cffunction>

  <cffunction name="isDbFastFailActive" access="private" returntype="boolean" output="false">
    <cfset var downUntil = "" />
    <cfif structKeyExists(application, "reportServiceDbDownUntil")>
      <cfset downUntil = application.reportServiceDbDownUntil />
      <cfif isDate(downUntil) AND downUntil GT now()>
        <cfreturn true />
      </cfif>
    </cfif>
    <cfreturn false />
  </cffunction>

  <cffunction name="markDbUnavailable" access="private" returntype="void" output="false">
    <cflock scope="application" type="exclusive" timeout="2">
      <cfset application.reportServiceDbDownUntil = dateAdd("s", 30, now()) />
    </cflock>
  </cffunction>

  <cffunction name="markDbAvailable" access="private" returntype="void" output="false">
    <cflock scope="application" type="exclusive" timeout="2">
      <cfif structKeyExists(application, "reportServiceDbDownUntil")>
        <cfset structDelete(application, "reportServiceDbDownUntil") />
      </cfif>
    </cflock>
  </cffunction>

  <cffunction name="getOrCreateDemoReport" access="private" returntype="query" output="false">
    <cfargument name="companyId" type="numeric" required="true" />
    <cfargument name="reportYear" type="numeric" required="true" />
    <cfargument name="userId" type="numeric" required="true" />
    <cfset var key = "" />
    <cfset var newId = 0 />
    <cfset var reportData = {} />

    <cfset ensureDemoStore() />
    <cfset key = arguments.companyId & "|gas_sectors|" & arguments.reportYear />

    <cfif NOT structKeyExists(session.demoReports, key)>
      <cfset newId = nextDemoReportId() />
      <cfset session.demoReports[key] = newDemoReport(arguments.companyId, arguments.reportYear, arguments.userId, newId) />
      <cfset session.demoReportIndex[toString(newId)] = key />
    </cfif>

    <cfset reportData = session.demoReports[key] />
    <cfreturn reportStructToQuery(reportData) />
  </cffunction>

  <cffunction name="saveStepToDemo" access="private" returntype="struct" output="false">
    <cfargument name="step" type="numeric" required="true" />
    <cfargument name="reportId" type="numeric" required="true" />
    <cfargument name="formData" type="struct" required="true" />
    <cfargument name="userId" type="numeric" required="true" />
    <cfset var result = { success = true, message = "Gespeichert." } />
    <cfset var demoKey = "" />
    <cfset var reportData = {} />

    <cfset ensureDemoStore() />
    <cfset demoKey = getDemoKeyByReportId(arguments.reportId) />
    <cfif len(demoKey) EQ 0>
      <cfset result.success = false />
      <cfset result.message = "Demo-Speicher nicht gefunden. Bitte Modul neu laden." />
      <cfreturn result />
    </cfif>

    <cfset reportData = session.demoReports[demoKey] />
    <cfset reportData.updated_by = arguments.userId />

    <cfif arguments.step EQ 1>
      <cfset reportData.period_type = arguments.formData.period_type />
      <cfset reportData.total_sale_kwh = arguments.formData.total_sale_kwh />
      <cfset reportData.resellers_kwh = arguments.formData.resellers_kwh />
      <cfset reportData.endconsumers_kwh = arguments.formData.endconsumers_kwh />
      <cfset reportData.grosscustomers_count = arguments.formData.grosscustomers_count />
      <cfset reportData.grosscustomers_total_kwh = arguments.formData.grosscustomers_total_kwh />
    </cfif>

    <cfif arguments.step EQ 2>
      <cfset reportData.sector_private_households_kwh = arguments.formData.sector_private_households_kwh />
      <cfset reportData.sector_agriculture_kwh = arguments.formData.sector_agriculture_kwh />
      <cfset reportData.sector_industry_kwh = arguments.formData.sector_industry_kwh />
      <cfset reportData.sector_services_kwh = arguments.formData.sector_services_kwh />
      <cfset reportData.sector_district_heating_kwh = arguments.formData.sector_district_heating_kwh />
      <cfset reportData.sector_other_kwh = structKeyExists(arguments.formData, "sector_other_kwh") ? arguments.formData.sector_other_kwh : 0 />
      <cfset reportData.sector_fuel_kwh = arguments.formData.sector_fuel_kwh />
      <cfset reportData.sector_wkk_kwh = arguments.formData.sector_wkk_kwh />
    </cfif>

    <cfif arguments.step EQ 3>
      <cfset reportData.canton_zh_kwh = arguments.formData.canton_zh_kwh />
      <cfset reportData.canton_be_kwh = arguments.formData.canton_be_kwh />
      <cfset reportData.canton_lu_kwh = arguments.formData.canton_lu_kwh />
      <cfset reportData.canton_ur_kwh = structKeyExists(arguments.formData, "canton_ur_kwh") ? arguments.formData.canton_ur_kwh : 0 />
      <cfset reportData.canton_sz_kwh = arguments.formData.canton_sz_kwh />
      <cfset reportData.canton_ow_kwh = structKeyExists(arguments.formData, "canton_ow_kwh") ? arguments.formData.canton_ow_kwh : 0 />
      <cfset reportData.canton_nw_kwh = structKeyExists(arguments.formData, "canton_nw_kwh") ? arguments.formData.canton_nw_kwh : 0 />
      <cfset reportData.canton_gl_kwh = arguments.formData.canton_gl_kwh />
      <cfset reportData.canton_zg_kwh = arguments.formData.canton_zg_kwh />
      <cfset reportData.canton_fr_kwh = arguments.formData.canton_fr_kwh />
      <cfset reportData.canton_so_kwh = arguments.formData.canton_so_kwh />
      <cfset reportData.canton_bs_kwh = arguments.formData.canton_bs_kwh />
      <cfset reportData.canton_bl_kwh = arguments.formData.canton_bl_kwh />
      <cfset reportData.canton_sh_kwh = arguments.formData.canton_sh_kwh />
      <cfset reportData.canton_ar_kwh = arguments.formData.canton_ar_kwh />
      <cfset reportData.canton_ai_kwh = arguments.formData.canton_ai_kwh />
      <cfset reportData.canton_sg_kwh = arguments.formData.canton_sg_kwh />
      <cfset reportData.canton_gr_kwh = arguments.formData.canton_gr_kwh />
      <cfset reportData.canton_ag_kwh = arguments.formData.canton_ag_kwh />
      <cfset reportData.canton_tg_kwh = arguments.formData.canton_tg_kwh />
      <cfset reportData.canton_ti_kwh = arguments.formData.canton_ti_kwh />
      <cfset reportData.canton_vd_kwh = arguments.formData.canton_vd_kwh />
      <cfset reportData.canton_vs_kwh = arguments.formData.canton_vs_kwh />
      <cfset reportData.canton_ne_kwh = arguments.formData.canton_ne_kwh />
      <cfset reportData.canton_ge_kwh = arguments.formData.canton_ge_kwh />
      <cfset reportData.canton_ju_kwh = arguments.formData.canton_ju_kwh />
      <cfset reportData.canton_abroad_kwh = arguments.formData.canton_abroad_kwh />
    </cfif>

    <cfif arguments.step EQ 4>
      <cfset reportData.biogas_import_total_kwh = 0 />
      <cfset reportData.biogas_import_lbg_kwh = 0 />
      <cfset reportData.biogas_import_network_kwh = 0 />
      <cfset reportData.biogas_import_certificate_kwh = 0 />
      <cfset oldCompletedDemo = structKeyExists(reportData, "is_completed") ? val(reportData.is_completed) : 0 />
      <cfset reportData.deviation_comment = arguments.formData.deviation_comment />
      <cfset reportData.is_completed = arguments.formData.is_completed />
      <cfset reportData.status = (arguments.formData.is_completed EQ 1) ? "submitted" : "draft" />
      <cfif oldCompletedDemo NEQ 1 AND val(arguments.formData.is_completed) EQ 1>
        <cftry>
          <cfset createObject("component", "services.AdminDataService").logAuditEvent(
            actionKey = "contact_sets_questionnaire_completed",
            entityType = "gas_report",
            entityId = arguments.reportId,
            companyId = val(reportData.company_id),
            reportYear = val(reportData.report_year),
            beforeState = { is_completed = oldCompletedDemo },
            afterState = { is_completed = 1 },
            details = { moduleKey = "gas_sectors" }
          ) />
          <cfcatch></cfcatch>
        </cftry>
      </cfif>
    </cfif>

    <cfset session.demoReports[demoKey] = reportData />
    <cftry>
      <cfset _adsAudit = createObject("component", "services.AdminDataService") />
      <cfset _adsAudit.syncGasSectorsFromReport(val(reportData.company_id), val(reportData.report_year), reportData) />
      <cfset _adsAudit.logAuditEvent(
        actionKey = "module_answer_saved",
        typ = "module_answer_saved",
        entityType = "gas_report",
        entityId = arguments.reportId,
        companyId = val(reportData.company_id),
        reportYear = val(reportData.report_year),
        details = { moduleKey = "gas_sectors", step = arguments.step }
      ) />
      <cfcatch>
      </cfcatch>
    </cftry>
    <cfreturn result />
  </cffunction>

  <cffunction name="getOrCreateReport" access="public" returntype="query" output="false">
    <cfargument name="companyId" type="numeric" required="true" />
    <cfargument name="reportYear" type="numeric" required="true" />
    <cfargument name="userId" type="numeric" required="true" />

    <cfif isDbFastFailActive()>
      <cfreturn getOrCreateDemoReport(arguments.companyId, arguments.reportYear, arguments.userId) />
    </cfif>

    <cftry>
      <cfquery name="qExisting" datasource="#application.datasource#">
        SELECT *
        FROM gas_reports
        WHERE company_id = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.companyId#" />
          AND module_key = 'gas_sectors'
          AND report_year = <cfqueryparam cfsqltype="cf_sql_smallint" value="#arguments.reportYear#" />
        LIMIT 1
      </cfquery>

      <cfif qExisting.recordCount EQ 0>
        <cfquery datasource="#application.datasource#">
          INSERT INTO gas_reports (
            company_id, module_key, report_year, created_by, updated_by
          ) VALUES (
            <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.companyId#" />,
            'gas_sectors',
            <cfqueryparam cfsqltype="cf_sql_smallint" value="#arguments.reportYear#" />,
            <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.userId#" />,
            <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.userId#" />
          )
        </cfquery>

        <cfquery name="qExisting" datasource="#application.datasource#">
          SELECT *
          FROM gas_reports
          WHERE company_id = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.companyId#" />
            AND module_key = 'gas_sectors'
            AND report_year = <cfqueryparam cfsqltype="cf_sql_smallint" value="#arguments.reportYear#" />
          LIMIT 1
        </cfquery>
      </cfif>

      <cfset markDbAvailable() />
      <cfreturn qExisting />
      <cfcatch type="any">
        <cfset markDbUnavailable() />
        <cfreturn getOrCreateDemoReport(arguments.companyId, arguments.reportYear, arguments.userId) />
      </cfcatch>
    </cftry>
  </cffunction>

  <cffunction name="saveStep" access="public" returntype="struct" output="false">
    <cfargument name="step" type="numeric" required="true" />
    <cfargument name="reportId" type="numeric" required="true" />
    <cfargument name="formData" type="struct" required="true" />
    <cfargument name="userId" type="numeric" required="true" />
    <cfargument name="skipValidation" type="boolean" required="false" default="false" />

    <cfset var result = { success = true, message = "Gespeichert." } />
    <cfset var validation = { success = true, message = "" } />
    <cfset var oldCompletedDb = 0 />

    <cfif NOT arguments.skipValidation>
      <cfset validation = validateStep(arguments.step, arguments.formData) />
    </cfif>

    <cfif NOT validation.success>
      <cfset result.success = false />
      <cfset result.message = validation.message />
      <cfreturn result />
    </cfif>

    <cfif isDbFastFailActive()>
      <cfreturn saveStepToDemo(arguments.step, arguments.reportId, arguments.formData, arguments.userId) />
    </cfif>

    <cftry>
      <cfif arguments.step EQ 4>
        <cfquery name="qBeforeCompleted" datasource="#application.datasource#">
          SELECT is_completed, company_id, report_year
          FROM gas_reports
          WHERE id = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.reportId#" />
          LIMIT 1
        </cfquery>
        <cfif qBeforeCompleted.recordCount EQ 1>
          <cfset oldCompletedDb = val(qBeforeCompleted.is_completed[1]) />
        </cfif>
      </cfif>

      <cfif arguments.step EQ 1>
        <cfquery datasource="#application.datasource#">
          UPDATE gas_reports
          SET period_type = <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.formData.period_type#" />,
              total_sale_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.total_sale_kwh#" />,
              resellers_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.resellers_kwh#" />,
              endconsumers_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.endconsumers_kwh#" />,
              grosscustomers_count = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.grosscustomers_count#" />,
              grosscustomers_total_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.grosscustomers_total_kwh#" />,
              updated_by = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.userId#" />
          WHERE id = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.reportId#" />
        </cfquery>
      </cfif>

      <cfif arguments.step EQ 2>
        <cfquery datasource="#application.datasource#">
          UPDATE gas_reports
          SET sector_private_households_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.sector_private_households_kwh#" />,
              sector_agriculture_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.sector_agriculture_kwh#" />,
              sector_industry_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.sector_industry_kwh#" />,
              sector_services_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.sector_services_kwh#" />,
              sector_district_heating_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.sector_district_heating_kwh#" />,
              sector_other_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#structKeyExists(arguments.formData, 'sector_other_kwh') ? val(arguments.formData.sector_other_kwh) : 0#" />,
              sector_fuel_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.sector_fuel_kwh#" />,
              sector_wkk_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.sector_wkk_kwh#" />,
              updated_by = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.userId#" />
          WHERE id = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.reportId#" />
        </cfquery>
      </cfif>

      <cfif arguments.step EQ 3>
        <cfquery datasource="#application.datasource#">
          UPDATE gas_reports
          SET canton_zh_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_zh_kwh#" />,
              canton_be_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_be_kwh#" />,
              canton_lu_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_lu_kwh#" />,
              canton_ur_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#structKeyExists(arguments.formData, 'canton_ur_kwh') ? val(arguments.formData.canton_ur_kwh) : 0#" />,
              canton_sz_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_sz_kwh#" />,
              canton_ow_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#structKeyExists(arguments.formData, 'canton_ow_kwh') ? val(arguments.formData.canton_ow_kwh) : 0#" />,
              canton_nw_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#structKeyExists(arguments.formData, 'canton_nw_kwh') ? val(arguments.formData.canton_nw_kwh) : 0#" />,
              canton_gl_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_gl_kwh#" />,
              canton_zg_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_zg_kwh#" />,
              canton_fr_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_fr_kwh#" />,
              canton_so_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_so_kwh#" />,
              canton_bs_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_bs_kwh#" />,
              canton_bl_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_bl_kwh#" />,
              canton_sh_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_sh_kwh#" />,
              canton_ar_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_ar_kwh#" />,
              canton_ai_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_ai_kwh#" />,
              canton_sg_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_sg_kwh#" />,
              canton_gr_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_gr_kwh#" />,
              canton_ag_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_ag_kwh#" />,
              canton_tg_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_tg_kwh#" />,
              canton_ti_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_ti_kwh#" />,
              canton_vd_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_vd_kwh#" />,
              canton_vs_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_vs_kwh#" />,
              canton_ne_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_ne_kwh#" />,
              canton_ge_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_ge_kwh#" />,
              canton_ju_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_ju_kwh#" />,
              canton_abroad_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.formData.canton_abroad_kwh#" />,
              updated_by = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.userId#" />
          WHERE id = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.reportId#" />
        </cfquery>
      </cfif>

      <cfif arguments.step EQ 4>
        <cfquery datasource="#application.datasource#">
          UPDATE gas_reports
          SET biogas_import_total_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="0" />,
              biogas_import_lbg_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="0" />,
              biogas_import_network_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="0" />,
              biogas_import_certificate_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="0" />,
              deviation_comment = <cfqueryparam cfsqltype="cf_sql_longvarchar" value="#arguments.formData.deviation_comment#" />,
              is_completed = <cfqueryparam cfsqltype="cf_sql_bit" value="#arguments.formData.is_completed#" />,
              completed_at = <cfif arguments.formData.is_completed EQ 1>NOW()<cfelse>NULL</cfif>,
              status = <cfif arguments.formData.is_completed EQ 1>'submitted'<cfelse>'draft'</cfif>,
              updated_by = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.userId#" />
          WHERE id = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.reportId#" />
        </cfquery>
        <cfif oldCompletedDb NEQ 1 AND val(arguments.formData.is_completed) EQ 1>
          <cftry>
            <cfset createObject("component", "services.AdminDataService").logAuditEvent(
              actionKey = "contact_sets_questionnaire_completed",
              entityType = "gas_report",
              entityId = arguments.reportId,
              companyId = (qBeforeCompleted.recordCount EQ 1 ? val(qBeforeCompleted.company_id[1]) : 0),
              reportYear = (qBeforeCompleted.recordCount EQ 1 ? val(qBeforeCompleted.report_year[1]) : 0),
              beforeState = { is_completed = oldCompletedDb },
              afterState = { is_completed = 1 },
              details = { moduleKey = "gas_sectors" }
            ) />
            <cfcatch></cfcatch>
          </cftry>
        </cfif>
      </cfif>
      <cfset markDbAvailable() />
      <cftry>
        <cfquery name="qRptMeta" datasource="#application.datasource#">
          SELECT company_id, report_year
          FROM gas_reports
          WHERE id = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.reportId#" />
          LIMIT 1
        </cfquery>
        <cfif qRptMeta.recordCount EQ 1>
          <cfset createObject("component", "services.AdminDataService").logAuditEvent(
            actionKey = "module_answer_saved",
            typ = "module_answer_saved",
            entityType = "gas_report",
            entityId = arguments.reportId,
            companyId = val(qRptMeta.company_id[1]),
            reportYear = val(qRptMeta.report_year[1]),
            details = { moduleKey = "gas_sectors", step = arguments.step }
          ) />
        </cfif>
        <cfcatch></cfcatch>
      </cftry>
      <cfcatch type="any">
        <cfset markDbUnavailable() />
        <cfreturn saveStepToDemo(arguments.step, arguments.reportId, arguments.formData, arguments.userId) />
      </cfcatch>
    </cftry>

    <cfreturn result />
  </cffunction>

  <cffunction name="validateStep" access="public" returntype="struct" output="false">
    <cfargument name="step" type="numeric" required="true" />
    <cfargument name="formData" type="struct" required="true" />

    <cfset var result = { success = true, message = "" } />
    <cfset var sumSectors = 0 />
    <cfset var fieldTextSvc = createObject("component", "services.FieldTextService") />

    <cfif arguments.step EQ 1>
      <cfif arguments.formData.total_sale_kwh LT 0 OR arguments.formData.resellers_kwh LT 0 OR arguments.formData.endconsumers_kwh LT 0 OR arguments.formData.grosscustomers_count LT 0 OR arguments.formData.grosscustomers_total_kwh LT 0>
        <cfset result.success = false />
        <cfset result.message = fieldTextSvc.getWarning("warn_negative_values", "Negative Werte sind nicht erlaubt.") />
      </cfif>
      <cfif (
        (val(arguments.formData.grosscustomers_count) GT 0 AND val(arguments.formData.grosscustomers_total_kwh) EQ 0)
        OR
        (val(arguments.formData.grosscustomers_total_kwh) GT 0 AND val(arguments.formData.grosscustomers_count) EQ 0)
      )>
        <cfset result.success = false />
        <cfset result.message = fieldTextSvc.getWarning(
          "warn_sectors_grosskunden_pair",
          "Wenn die Anzahl Grosskunden grösser als 0 ist, muss auch der Gesamtverbrauch grösser als 0 sein – und umgekehrt."
        ) />
      </cfif>
      <cfif arguments.formData.total_sale_kwh NEQ (arguments.formData.resellers_kwh + arguments.formData.endconsumers_kwh)>
        <cfset result.success = false />
        <cfset result.message = fieldTextSvc.getWarning("warn_sectors_total_sum", "Kontrollsumme ungültig: Total muss Wiederverkäufer + Endverbraucher sein.") />
      </cfif>
    </cfif>

    <cfif arguments.step EQ 2>
      <cfset sumSectors =
        arguments.formData.sector_private_households_kwh +
        arguments.formData.sector_agriculture_kwh +
        arguments.formData.sector_industry_kwh +
        arguments.formData.sector_services_kwh +
        arguments.formData.sector_district_heating_kwh +
        arguments.formData.sector_fuel_kwh />

      <cfif sumSectors NEQ arguments.formData.endconsumers_kwh>
        <cfset result.success = false />
        <cfset result.message = fieldTextSvc.getWarning("warn_sectors_sector_sum", "Kontrollsumme ungültig: Summe aller Sektoren muss Endverbraucher entsprechen.") />
      </cfif>
    </cfif>

    <cfif arguments.step EQ 3>
      <cfset sumSectors =
        arguments.formData.canton_zh_kwh +
        arguments.formData.canton_be_kwh +
        arguments.formData.canton_lu_kwh +
        arguments.formData.canton_sz_kwh +
        arguments.formData.canton_gl_kwh +
        arguments.formData.canton_zg_kwh +
        arguments.formData.canton_fr_kwh +
        arguments.formData.canton_so_kwh +
        arguments.formData.canton_bs_kwh +
        arguments.formData.canton_bl_kwh +
        arguments.formData.canton_sh_kwh +
        arguments.formData.canton_ar_kwh +
        arguments.formData.canton_ai_kwh +
        arguments.formData.canton_sg_kwh +
        arguments.formData.canton_gr_kwh +
        arguments.formData.canton_ag_kwh +
        arguments.formData.canton_tg_kwh +
        arguments.formData.canton_ti_kwh +
        arguments.formData.canton_vd_kwh +
        arguments.formData.canton_vs_kwh +
        arguments.formData.canton_ne_kwh +
        arguments.formData.canton_ge_kwh +
        arguments.formData.canton_ju_kwh +
        arguments.formData.canton_abroad_kwh />

      <cfif sumSectors NEQ arguments.formData.endconsumers_kwh>
        <cfset result.success = false />
        <cfset result.message = fieldTextSvc.getWarning("warn_sectors_canton_sum", "Kontrollsumme ungültig (Kantone): Summe der Kantonsfelder muss «Erdgas- und Biogasverkauf an Endverbraucher inkl. Verkauf an WKK-Anlagen» entsprechen.") />
      </cfif>
    </cfif>

    <cfif arguments.step EQ 4>
      <!--- Biogas-Import-Felder entfernt; keine Summenprüfung mehr --->
    </cfif>

    <cfreturn result />
  </cffunction>

  <cffunction name="saveKioPrerequisiteFields" access="public" returntype="struct" output="false">
    <cfargument name="reportId" type="numeric" required="true" />
    <cfargument name="periodType" type="string" required="true" />
    <cfargument name="endconsumersKwh" type="numeric" required="true" />
    <cfargument name="userId" type="numeric" required="true" />
    <cfset var result = { success = true, message = "" } />
    <cfset var pt = lCase(trim(arguments.periodType)) />
    <cfset var ec = max(0, val(arguments.endconsumersKwh)) />
    <cfset var demoKey = "" />
    <cfset var reportData = {} />

    <cfif NOT listFind("calendar,hydrological", pt)>
      <cfset pt = "calendar" />
    </cfif>

    <cfif isDbFastFailActive()>
      <cfset ensureDemoStore() />
      <cfset demoKey = getDemoKeyByReportId(arguments.reportId) />
      <cfif len(demoKey) EQ 0>
        <cfset result.success = false />
        <cfreturn result />
      </cfif>
      <cfset reportData = session.demoReports[demoKey] />
      <cfset reportData.period_type = pt />
      <cfset reportData.endconsumers_kwh = ec />
      <cfset reportData.updated_by = arguments.userId />
      <cfset session.demoReports[demoKey] = reportData />
      <cfreturn result />
    </cfif>

    <cftry>
      <cfquery datasource="#application.datasource#">
        UPDATE gas_reports
        SET period_type = <cfqueryparam cfsqltype="cf_sql_varchar" value="#pt#" />,
            endconsumers_kwh = <cfqueryparam cfsqltype="cf_sql_bigint" value="#ec#" />,
            updated_by = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.userId#" />
        WHERE id = <cfqueryparam cfsqltype="cf_sql_bigint" value="#arguments.reportId#" />
      </cfquery>
      <cfset markDbAvailable() />
      <cfcatch type="any">
        <cfset markDbUnavailable() />
        <cfset ensureDemoStore() />
        <cfset demoKey = getDemoKeyByReportId(arguments.reportId) />
        <cfif len(demoKey) GT 0>
          <cfset reportData = session.demoReports[demoKey] />
          <cfset reportData.period_type = pt />
          <cfset reportData.endconsumers_kwh = ec />
          <cfset reportData.updated_by = arguments.userId />
          <cfset session.demoReports[demoKey] = reportData />
        <cfelse>
          <cfset result.success = false />
        </cfif>
      </cfcatch>
    </cftry>

    <cfreturn result />
  </cffunction>

  <cffunction name="isKioPrerequisiteMet" access="public" returntype="boolean" output="false">
    <cfargument name="sectorsReport" type="query" required="true" />
    <cfset var periodType = "" />
    <cfset var endconsumers = 0 />

    <cfif arguments.sectorsReport.recordCount LT 1>
      <cfreturn false />
    </cfif>

    <cfset periodType = lCase(trim(arguments.sectorsReport.period_type[1])) />
    <cfif NOT listFind("calendar,hydrological", periodType)>
      <cfreturn false />
    </cfif>

    <cfset endconsumers = val(arguments.sectorsReport.endconsumers_kwh[1]) />
    <cfreturn endconsumers GT 0 />
  </cffunction>
</cfcomponent>
