<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class PlatformOrder extends Model
{
    use HasFactory;

    public function orderTypeLabel(): string
    {
        $labels = [
            'new_purchase' => '新购',
            'renewal' => '续费',
            'upgrade' => '升级',
            'downgrade' => '降级',
        ];

        $type = (string) ($this->order_type ?? '');

        return (string) ($labels[$type] ?? $type);
    }

    public function receiptTotal(): float
    {
        // 优先读扁平字段 payment_summary.total_amount（更稳定、避免遍历 receipts）
        $total = (float) (data_get($this->meta, 'payment_summary.total_amount') ?? 0);
        if ($total > 0) {
            return $total;
        }

        // 回退：遍历 payment_receipts[].amount
        $receipts = (array) (data_get($this->meta, 'payment_receipts', []) ?? []);
        $sum = 0.0;
        foreach ($receipts as $r) {
            $sum += (float) (data_get($r, 'amount') ?? 0);
        }

        return $sum;
    }

    public function hasLedgerEvidence(): bool
    {
        return (data_get($this->meta, 'payment_summary.total_amount') !== null)
            || (data_get($this->meta, 'payment_receipts.0.amount') !== null)
            || (data_get($this->meta, 'refund_summary.total_amount') !== null)
            || (data_get($this->meta, 'refund_receipts.0.amount') !== null);
    }

    public function exportLedgerUrl(array $query = []): string
    {
        // 安全阀：download=1 必须显式存在（用于防止预取/误触发）。
        // 且为了测试/口径稳定，download 固定在 query 的第一位。
        $query = ['download' => 1] + $query;

        return '/admin/platform-orders/' . $this->id . '/export-ledger?' . \Illuminate\Support\Arr::query($query);
    }

    public function refundTotal(): float
    {
        // 优先读扁平字段 refund_summary.total_amount
        $total = data_get($this->meta, 'refund_summary.total_amount');
        if ($total !== null) {
            return (float) $total;
        }

        // 回退：遍历 refund_receipts[].amount
        $refunds = (array) (data_get($this->meta, 'refund_receipts', []) ?? []);
        $sum = 0.0;
        foreach ($refunds as $r) {
            $sum += (float) (data_get($r, 'amount') ?? 0);
        }

        return $sum;
    }

    public function isRefundInconsistent(): bool
    {
        // 口径与平台订单列表 refund_inconsistent 保持一致：按分取整 + 容差（config('saasshop.amounts.tolerance')）
        $refundTotal = (float) $this->refundTotal();
        $paidAmount = (float) ($this->paid_amount ?? 0);

        $refundCents = (int) round($refundTotal * 100);
        $paidCents = (int) round($paidAmount * 100);

        $tol = (float) config('saasshop.amounts.tolerance', 0.01);
        $tolCents = (int) round($tol * 100);
        $tolCents = max(1, $tolCents);

        if ((string) $this->payment_status === 'refunded') {
            // 已退款但退款总额不足：refund_total + tol < paid
            return ($refundCents + $tolCents) < $paidCents;
        }

        // 非已退款但退款总额已达到/超过已付：refund_total >= paid + tol
        return $paidCents > 0 && $refundCents >= ($paidCents + $tolCents);
    }

    public function isReconcileMismatch(): bool
    {
        // 口径与平台订单列表 reconcile_mismatch 保持一致：支付回执总额 与订单 paid_amount 不一致（按分取整，差额>=容差）
        //
        // 重要：若该订单尚无任何“回执证据”（payment_summary/payment_receipts 都为空），则不判定为对账不一致。
        // 原因：测试/人工补数据场景下，订单可能已标记 paid，但尚未沉淀回执；此时应通过 receipt_status=none 暴露问题，
        // 而不是把它强制归入 reconcile_mismatch 并阻断正常 SOP。
        $hasSummary = data_get($this->meta, 'payment_summary.total_amount') !== null;
        $hasReceipt = data_get($this->meta, 'payment_receipts.0.amount') !== null;
        if (! $hasSummary && ! $hasReceipt) {
            return false;
        }

        $receiptCents = (int) round(((float) $this->receiptTotal()) * 100);
        $paidCents = (int) round(((float) ($this->paid_amount ?? 0)) * 100);

        $tol = (float) config('saasshop.amounts.tolerance', 0.01);
        $tolCents = (int) round($tol * 100);
        // 以“分”为最小粒度，至少 1 分（若配置 0，则视为要求严格一致）
        $tolCents = max(1, $tolCents);

        return abs($receiptCents - $paidCents) >= $tolCents;
    }

    protected $fillable = [
        'merchant_id', 'plan_id', 'site_subscription_id', 'created_by_admin_id', 'order_no', 'order_type', 'status',
        'payment_status', 'payment_channel', 'plan_name', 'billing_cycle', 'period_months', 'quantity', 'list_amount',
        'discount_amount', 'payable_amount', 'paid_amount', 'placed_at', 'paid_at', 'activated_at', 'cancelled_at',
        'refunded_at', 'plan_snapshot', 'meta', 'remark',
    ];

    protected $casts = [
        'list_amount' => 'decimal:2',
        'discount_amount' => 'decimal:2',
        'payable_amount' => 'decimal:2',
        'paid_amount' => 'decimal:2',
        'placed_at' => 'datetime',
        'paid_at' => 'datetime',
        'activated_at' => 'datetime',
        'cancelled_at' => 'datetime',
        'refunded_at' => 'datetime',
        'plan_snapshot' => 'array',
        'meta' => 'array',
    ];

    public function merchant(): BelongsTo
    {
        return $this->belongsTo(Merchant::class, 'merchant_id');
    }

    public function plan(): BelongsTo
    {
        return $this->belongsTo(Plan::class);
    }

    public function siteSubscription(): BelongsTo
    {
        return $this->belongsTo(SiteSubscription::class);
    }

    public function creator(): BelongsTo
    {
        return $this->belongsTo(Admin::class, 'created_by_admin_id');
    }
}
