<?php
declare(strict_types=1);

final class QuotationCalculator
{
    public const VALID_METHODS = [
        'On-Grid Solar System' => ['Peak Load', 'Monthly Electricity Bill'],
        'Off-Grid Solar System' => ['Load Calculation', 'Monthly Electricity Bill'],
        'Hybrid Solar System' => ['Load Calculation', 'Monthly Electricity Bill'],
        'Solar Water Pumping System' => ['Water Pumping'],
    ];

    public const PANEL_MOUNTING = ['Shade', 'Rooftop', 'Ground Mounting'];
    private const COMMON_BATTERY_AH = [50, 65, 100, 120, 150, 200, 250, 300];

    public static function isValidSystemMethod(string $systemType, string $method): bool
    {
        return in_array($method, self::VALID_METHODS[$systemType] ?? [], true);
    }

    public static function load(array $loads, float $sunHour = 4.5): array
    {
        $connected = 0.0;
        $energy = 0.0;
        foreach ($loads as $load) {
            $qty = (float)($load['qty'] ?? 0);
            $watt = (float)($load['watt_rating'] ?? 0);
            $backup = (float)($load['backup_when_no_sun'] ?? 0);
            $connected += $qty * $watt;
            $energy += $qty * $watt * $backup;
        }
        $inverterVa = $connected * 1.25;
        $batteryWh = $energy * 1.25;
        $battery = self::battery($batteryWh, $inverterVa);
        return [
            'connected_load_w' => round($connected, 2),
            'daily_energy_wh' => round($energy, 2),
            'inverter_va' => self::clean($inverterVa),
            'battery_wh' => self::clean($batteryWh),
            'battery_voltage' => $battery['battery_voltage'],
            'battery_ah' => $battery['battery_ah'],
            'battery_spec' => $battery['battery_spec'],
            'solar_panel_w' => self::clean(($energy / max($sunHour, 1)) * 1.25),
        ];
    }

    public static function bill(float $bill, float $rate, float $sunHour): array
    {
        $monthly = $rate > 0 ? $bill / $rate : 0;
        $daily = $monthly / 30;
        return [
            'monthly_units' => round($monthly, 2),
            'daily_units' => round($daily, 2),
            'solar_kw' => round($sunHour > 0 ? $daily / $sunHour : 0, 2),
        ];
    }

    public static function peak(float $kw, float $safety): array
    {
        return ['suggested_kw' => round($kw * (1 + ($safety / 100)), 2)];
    }

    public static function pump(float $hp, float $headFt = 0, float $waterDemandLiters = 0, float $averageSunHour = 4.5, float $pumpEfficiency = 0.55, float $systemEfficiency = 0.75, string $pumpType = 'AC'): array
    {
        $kw = $hp * 0.746;
        $headM = max(0, $headFt) * 0.3048;
        $dailyWaterM3 = max(0, $waterDemandLiters) / 1000;
        $hydraulicEnergyKwh = ($dailyWaterM3 * 1000 * 9.81 * $headM) / 3600000;
        $electricalEnergyKwh = $pumpEfficiency > 0 ? $hydraulicEnergyKwh / $pumpEfficiency : 0;
        $solarKwByWater = ($averageSunHour > 0 && $systemEfficiency > 0) ? $electricalEnergyKwh / ($averageSunHour * $systemEfficiency) : 0;
        $solarKwByHp = $kw * 1.5;
        $suggestedSolarKw = max($solarKwByWater, $solarKwByHp) + $solarKwByWater;
        $suggestedSolarKw *= 1.15;
        $suggestedSolarKw = self::roundSolarKw($suggestedSolarKw);
        $type = strtoupper(trim($pumpType));
        return [
            'pump_kw' => round($kw, 2),
            'head_m' => round($headM, 2),
            'daily_water_m3' => round($dailyWaterM3, 2),
            'daily_pumping_energy_kwh' => round($electricalEnergyKwh, 2),
            'solar_kw_by_water' => round($solarKwByWater, 2),
            'solar_kw_by_hp' => round($solarKwByHp, 2),
            'suggested_solar_kw' => $suggestedSolarKw,
            'suggested_inverter_kw' => round($kw * ($type === 'DC' ? 1.15 : 1.25), 2),
        ];
    }

    public static function energy(float $systemCapacityKw, float $grandTotal, float $monthlyBill, float $averageSunHour = 4.5, float $performanceRatio = 0.75, float $gridEmissionFactor = 0.62, float $coalFactor = 0.4, float $electricityRate = 10, string $method = ''): array
    {
        $annualEnergy = $systemCapacityKw * $averageSunHour * 365 * $performanceRatio;
        $annualSavings = $method === 'Monthly Electricity Bill' && $monthlyBill > 0 ? $monthlyBill * 12 : $annualEnergy * $electricityRate;
        return [
            'annual_energy_kwh' => round($annualEnergy, 2),
            'carbon_reduced_kg' => round($annualEnergy * $gridEmissionFactor, 2),
            'coal_reduced_kg' => round($annualEnergy * $coalFactor, 2),
            'annual_savings_amount' => round($annualSavings, 2),
            'payback_period_years' => $annualSavings > 0 ? round($grandTotal / $annualSavings, 2) : null,
        ];
    }

    public static function battery(float $batteryRequiredWh, float $inverterVa): array
    {
        $voltage = $inverterVa <= 1000 ? 12 : ($inverterVa <= 3000 ? 24 : 48);
        $calculatedAh = $voltage > 0 ? $batteryRequiredWh / $voltage : 0;
        $ah = self::roundBatteryAh($calculatedAh);
        return [
            'battery_voltage' => $ah > 0 ? $voltage : null,
            'battery_ah' => $ah > 0 ? $ah : null,
            'battery_spec' => $ah > 0 ? $voltage . 'V ' . $ah . 'Ah' : 'Not Required',
        ];
    }

    public static function roundBatteryAh(float $ah): int
    {
        if ($ah <= 0) {
            return 0;
        }
        foreach (self::COMMON_BATTERY_AH as $size) {
            if ($ah <= $size) {
                return $size;
            }
        }
        return (int)(ceil($ah / 50) * 50);
    }

    public static function roundSolarKw(float $kw): float
    {
        if ($kw <= 0) {
            return 0.0;
        }
        $step = $kw <= 10 ? 0.5 : 1.0;
        return round(ceil($kw / $step) * $step, 2);
    }

    private static function clean(float $value): float
    {
        if ($value >= 1000) {
            return round($value / 100) * 100;
        }
        return round($value, 2);
    }
}
