-- 订单均摊结算统计 — 公共CTE链（detail.sql / summary.sql 共用）
-- 参数：{period_start} 账期起始日，{period_end} 账期结束日
-- 所有金额均为税后金额（价外税，含税价 / (1+税率)）

WITH
-- 步骤0：获取所有历史退费记录（不受当前账期限制）
all_refund_records AS (
  SELECT
    out_trade_no AS order_no,
    SUM(refund_amount_int)::numeric / 100 AS total_refund_amount,
    MAX(refund_type) AS refund_type,
    MAX(DATE(updated_at)) AS latest_refund_date
  FROM bi_refund_order
  WHERE status = 3
    AND DATE(updated_at) <= '{period_end}'::date
  GROUP BY out_trade_no
),
-- 步骤1：获取所有符合条件的订单基础信息
order_base AS (
  SELECT 
    o.id AS order_id,
    o.out_trade_no AS order_no,
    o.trade_no,
    DATE(o.pay_success_date) AS order_date,
    o.pay_amount_int::numeric / 100 AS pay_amount,
    CASE WHEN DATE(o.pay_success_date) < '2026-05-01' THEN 0.01 ELSE 0.06 END AS tax_rate,
    (o.pay_amount_int::numeric / 100) / (1 + CASE WHEN DATE(o.pay_success_date) < '2026-05-01' THEN 0.01 ELSE 0.06 END)
      * CASE WHEN DATE(o.pay_success_date) < '2026-05-01' THEN 0.01 ELSE 0.06 END AS tax_amount,
    (o.pay_amount_int::numeric / 100) / (1 + CASE WHEN DATE(o.pay_success_date) < '2026-05-01' THEN 0.01 ELSE 0.06 END) AS after_tax_amount,
    DATE(o.pay_success_date) + INTERVAL '7 days' AS amortization_start_date,
    o.order_status,
    a.id AS account_id,
    o.key_from,
    o.sale_channel,
    CASE WHEN ar.order_no IS NOT NULL THEN 1 ELSE 0 END AS has_refund,
    COALESCE(ar.total_refund_amount, 0) AS total_refund_amount,
    CASE WHEN ar.order_no IS NOT NULL
              AND COALESCE(ar.total_refund_amount, 0) >= o.pay_amount_int::numeric / 100
         THEN 1 ELSE 0 END AS is_full_refund,
    ar.refund_type,
    ar.latest_refund_date
  FROM bi_vala_order o
  JOIN bi_vala_app_account a ON o.account_id = a.id
  LEFT JOIN all_refund_records ar ON o.out_trade_no = ar.order_no
  WHERE 
    o.pay_success_date >= '2025-06-01'
    AND o.pay_success_date <= '{period_end}'::date + INTERVAL '1 day' - INTERVAL '1 second'
    AND o.order_status IN (3,4)
    AND o.pay_amount_int >= 1000
),
-- 步骤2：合并计算原始均摊周期和退后均摊周期（一次表扫描）
order_cycle AS (
  SELECT 
    out_trade_no AS order_no,
    COUNT(DISTINCT id) * 90 AS original_cycle_days,
    COUNT(DISTINCT CASE WHEN status != -1 THEN id END) * 90 AS active_cycle_days
  FROM bi_vala_seasonal_ticket
  GROUP BY out_trade_no
),
-- 步骤3：合并订单基础信息与均摊周期（仅计算基础字段，衍生字段在步骤3.5统一计算）
order_with_cycle AS (
  SELECT
    ob.*,
    COALESCE(oc.active_cycle_days, 0) AS active_cycle_days,
    -- total_cycle_days: 退后均摊周期。若active=0且has_refund=0且original>0，
    -- 说明退费发生在账期后（季卡已删但账期内无退款记录），回退到原始周期
    CASE WHEN COALESCE(oc.active_cycle_days, 0) = 0
         AND COALESCE(oc.original_cycle_days, 0) > 0
         AND ob.has_refund = 0
    THEN COALESCE(oc.original_cycle_days, 0)
    ELSE COALESCE(oc.active_cycle_days, 0)
    END AS total_cycle_days,
    COALESCE(oc.original_cycle_days, 0) AS original_cycle_days,
    -- 原始均摊结束日
    ob.amortization_start_date
      + COALESCE(oc.original_cycle_days, 0) * INTERVAL '1 day' - INTERVAL '1 day' AS original_amortization_end_date,
    -- 原始日均摊金额（基于原订单税后金额和原始周期）
    CASE WHEN COALESCE(oc.original_cycle_days, 0) > 0
      THEN ob.after_tax_amount / oc.original_cycle_days ELSE 0 END AS original_daily_amort_amount,
    -- 原始日税费均摊
    CASE WHEN COALESCE(oc.original_cycle_days, 0) > 0
      THEN ob.tax_amount / oc.original_cycle_days ELSE 0 END AS original_daily_tax_amount
  FROM order_base ob
  LEFT JOIN order_cycle oc ON ob.order_no = oc.order_no
),
-- 步骤3.5：基于effective total_cycle_days计算衍生字段（均摊结束日、日均摊金额、日税费金额）
order_with_cycle_fixed AS (
  SELECT
    owc.*,
    -- 均摊结束日（基于effective total_cycle_days）
    CASE WHEN owc.total_cycle_days > 0
      THEN owc.amortization_start_date + owc.total_cycle_days * INTERVAL '1 day' - INTERVAL '1 day'
      ELSE NULL END AS amortization_end_date,
    -- 退后日均摊金额
    CASE WHEN owc.total_cycle_days > 0 AND owc.has_refund = 1 AND owc.is_full_refund = 0
      THEN (owc.pay_amount - owc.total_refund_amount) / (1 + owc.tax_rate) / owc.total_cycle_days
      WHEN owc.total_cycle_days > 0
      THEN owc.after_tax_amount / owc.total_cycle_days
      ELSE 0 END AS daily_amort_amount,
    -- 退后日税费均摊
    CASE WHEN owc.total_cycle_days > 0 AND owc.has_refund = 1 AND owc.is_full_refund = 0
      THEN (owc.pay_amount - owc.total_refund_amount) / (1 + owc.tax_rate) * owc.tax_rate / owc.total_cycle_days
      WHEN owc.total_cycle_days > 0
      THEN owc.tax_amount / owc.total_cycle_days
      ELSE 0 END AS daily_tax_amount
  FROM order_with_cycle owc
),
-- 步骤4：判断订单场景分类
order_classified AS (
  SELECT
    owc.*,
    GREATEST(owc.amortization_start_date, '{period_start}'::date) AS eff_start,
    LEAST(owc.amortization_end_date, '{period_end}'::date) AS eff_end,
    -- 试用期内退费（退费日 < 转正日，从未产生均摊，不应触发冲销）
    CASE WHEN owc.has_refund = 1
              AND owc.latest_refund_date < DATE(owc.amortization_start_date)
         THEN 1 ELSE 0 END AS is_trial_period_refund,
    -- 账期前全额退费（场景F：本账期完全排除）
    CASE WHEN owc.has_refund = 1 AND owc.is_full_refund = 1
              AND owc.latest_refund_date < '{period_start}'::date
         THEN 1 ELSE 0 END AS is_pre_period_full_refund,
    -- 账期前部分退费（场景C：按退后金额正常均摊）
    CASE WHEN owc.has_refund = 1 AND owc.is_full_refund = 0
              AND owc.latest_refund_date < '{period_start}'::date
         THEN 1 ELSE 0 END AS is_pre_period_partial_refund,
    -- 账期内退费（场景A/B/D/E）
    CASE WHEN owc.has_refund = 1
              AND owc.latest_refund_date >= '{period_start}'::date
              AND owc.latest_refund_date <= '{period_end}'::date
         THEN 1 ELSE 0 END AS is_current_period_refund,
    -- 账期内下单
    CASE WHEN owc.order_date >= '{period_start}'::date
              AND owc.order_date <= '{period_end}'::date
         THEN 1 ELSE 0 END AS is_ordered_in_period,
    -- 退后订单税后金额
    CASE WHEN owc.has_refund = 1 AND owc.is_full_refund = 0
         THEN (owc.pay_amount - owc.total_refund_amount) / (1 + owc.tax_rate)
         ELSE owc.after_tax_amount END AS refunded_after_tax_amount,
    -- 退后订单税费
    CASE WHEN owc.has_refund = 1 AND owc.is_full_refund = 0
         THEN (owc.pay_amount - owc.total_refund_amount) / (1 + owc.tax_rate) * owc.tax_rate
         ELSE owc.tax_amount END AS refunded_tax_amount
  FROM order_with_cycle_fixed owc
  WHERE owc.total_cycle_days > 0
     OR (owc.has_refund = 1 AND owc.is_full_refund = 1 AND owc.original_cycle_days > 0)
),
-- 步骤5：计算均摊天数
order_with_days AS (
  SELECT
    oc2.*,
    -- 账期内有效均摊天数（基于退后周期）
    CASE WHEN oc2.eff_end >= oc2.eff_start AND oc2.total_cycle_days > 0
      THEN EXTRACT(DAY FROM (oc2.eff_end - oc2.eff_start))::int + 1 ELSE 0 END AS period_amort_days,
    -- 从转正日到账期结束日的总已均摊天数（基于退后周期）
    CASE WHEN '{period_end}'::date >= oc2.amortization_start_date AND oc2.total_cycle_days > 0
      THEN EXTRACT(DAY FROM (LEAST('{period_end}'::date, oc2.amortization_end_date) - oc2.amortization_start_date))::int + 1
      ELSE 0 END AS total_amorted_days_to_period_end,
    -- 从转正日到账期起始日前一天的历史已均摊天数（基于原始周期，用于冲销计算）
    CASE WHEN '{period_start}'::date > oc2.amortization_start_date AND oc2.original_cycle_days > 0
      THEN EXTRACT(DAY FROM (LEAST('{period_start}'::date - 1, oc2.original_amortization_end_date) - oc2.amortization_start_date))::int + 1
      ELSE 0 END AS historical_amorted_days,
    -- 从转正日到账期结束日的天数（基于退后周期，用于退后订单重新均摊）
    CASE WHEN '{period_end}'::date >= oc2.amortization_start_date AND oc2.total_cycle_days > 0
      THEN EXTRACT(DAY FROM (LEAST('{period_end}'::date, oc2.amortization_end_date) - oc2.amortization_start_date))::int + 1
      ELSE 0 END AS refunded_amort_days_to_period_end
  FROM order_classified oc2
)
