<?php

namespace App\Services;

use App\Models\DeliveryArea;
use App\Models\Setting;
use Illuminate\Support\Collection;

/**
 * ShippingCalculator — fondasi mode perhitungan ongkir.
 *
 * Mode yang tersedia (setting: shipping_mode):
 *   flat        — Satu ongkir flat per pesanan (DEFAULT, perilaku saat ini)
 *   per_mitra   — Ongkir per mitra (fondasi, belum aktif)
 *   manual      — Ongkir ditentukan admin (fondasi, belum aktif)
 *   free        — Gratis ongkir Rp0
 *
 * Penggunaan:
 *   $calculator = new ShippingCalculator();
 *   $cost       = $calculator->calculate($deliveryArea, $items);
 */
class ShippingCalculator
{
    public readonly string $mode;
    public readonly int    $defaultCost;

    public function __construct()
    {
        $this->mode        = Setting::get('shipping_mode', 'flat');
        $this->defaultCost = (int) Setting::get('default_delivery_cost', 0);
    }

    /**
     * Hitung ongkir berdasarkan mode aktif.
     *
     * @param  DeliveryArea|null     $deliveryArea  Area terpilih oleh customer
     * @param  Collection            $items         Item keranjang (untuk mode per_mitra)
     * @return int                   Nilai ongkir dalam Rupiah
     */
    public function calculate(?DeliveryArea $deliveryArea, Collection $items = new Collection()): int
    {
        return match ($this->mode) {
            'free'      => $this->calculateFree(),
            'per_mitra' => $this->calculatePerMitra($deliveryArea, $items),
            'manual'    => $this->calculateManual($deliveryArea),
            default     => $this->calculateFlat($deliveryArea),  // 'flat' = default
        };
    }

    /**
     * Apakah mode saat ini menggunakan tarif default (bukan dari area)?
     * Dipakai di view checkout untuk menampilkan info "tarif default".
     */
    public function isUsingDefaultCost(?DeliveryArea $deliveryArea): bool
    {
        if ($this->mode === 'free') return false;
        if ($this->mode === 'flat' && $deliveryArea === null) return true;
        return false;
    }

    // ── Mode: Flat per Pesanan (DEFAULT) ──────────────────────────────────
    // Perilaku identik dengan sebelum Sprint 3.4.
    // Jika area dipilih → pakai cost area. Jika tidak → pakai default.
    private function calculateFlat(?DeliveryArea $deliveryArea): int
    {
        return $deliveryArea?->cost ?? $this->defaultCost;
    }

    // ── Mode: Gratis Ongkir ───────────────────────────────────────────────
    private function calculateFree(): int
    {
        return 0;
    }

    // ── Mode: Per Mitra (Fondasi — Sprint berikutnya) ─────────────────────
    // Saat ini fallback ke flat. Logika lengkap di Sprint berikutnya.
    private function calculatePerMitra(?DeliveryArea $deliveryArea, Collection $items): int
    {
        // TODO Sprint berikutnya: hitung ongkir per mitra dari $items
        return $this->calculateFlat($deliveryArea);
    }

    // ── Mode: Manual Admin (Fondasi — Sprint berikutnya) ──────────────────
    // Saat ini fallback ke flat. Admin set cost saat memproses pesanan.
    private function calculateManual(?DeliveryArea $deliveryArea): int
    {
        // TODO Sprint berikutnya: return 0 dan biarkan admin isi saat proses
        return $this->calculateFlat($deliveryArea);
    }

    /**
     * Daftar mode yang tersedia untuk select di Pengaturan Admin.
     */
    public static function modes(): array
    {
        return [
            'flat'      => 'Flat per Pesanan',
            'per_mitra' => 'Per Mitra',
            'manual'    => 'Manual Admin',
            'free'      => 'Gratis Ongkir',
        ];
    }
}
