<?php
namespace App\Support;
use App\Models\Equipment;
use App\Models\Project;
use App\Services\SequenceService;
class CrudHooks {
    public static function autonumber(): array {
        return [
            'blast-logs' => ['blast_no' => 'blast'], 'fuel-logs' => ['log_no' => 'fuel_log'],
            'trip-logs' => ['trip_no' => 'trip'], 'qc-tests' => ['test_no' => 'qc_test'],
            'leave-applications' => ['leave_no' => 'leave'], 'staff-advances' => ['advance_no' => 'advance'],
            'employees' => ['employee_no' => 'employee'], 'hse-incidents' => ['incident_no' => 'hse_incident'],
            'hse-inspections' => ['inspection_no' => 'hse_inspection'], 'work-permits' => ['permit_no' => 'work_permit'],
            'subcontracts' => ['subcontract_no' => 'subcontract'], 'fixed-assets' => ['asset_no' => 'fixed_asset'],
            'drill-logs' => ['drill_no' => 'drill'],
        ];
    }
    public static function saving(string $key, array $data, $record = null): array {
        // C4: currency code integrity on master data
        foreach (['currency' => 'bank-accounts', 'default_currency' => ['customers', 'suppliers']] as $field => $keys) {
            if (in_array($key, (array) $keys) && isset($data[$field])) {
                $data[$field] = strtoupper(trim((string) $data[$field])) ?: 'GHS';
                if (!\App\Models\Currency::where('code', $data[$field])->where('is_active', true)->exists()) {
                    throw \Illuminate\Validation\ValidationException::withMessages([$field => 'Unknown or inactive currency — maintain it under Finance → Currencies.']);
                }
            }
        }
        switch ($key) {
            case 'currencies':
                if ($record === null) $data['code'] = strtoupper(trim((string) ($data['code'] ?? '')));
                else unset($data['code']);
                if ($record && $record->is_base) { $data['rate_to_ghs'] = 1; $data['is_active'] = true; } // base locked
                $data['rate_to_ghs'] = max(0.000001, (float) ($data['rate_to_ghs'] ?? 1));
                break;
            case 'fuel-logs':
                $data['amount'] = round(((float) ($data['qty_litres'] ?? 0)) * ((float) ($data['rate_per_litre'] ?? 0)), 2);
                break;
            case 'drill-logs':
                $data['total_meters'] = round(((float) ($data['holes_drilled'] ?? 0)) * ((float) ($data['depth_per_hole_m'] ?? 0)), 2);
                break;
            case 'explosives-registers':
                $data['closing_balance'] = round(((float) ($data['opening_balance'] ?? 0)) + ((float) ($data['received_qty'] ?? 0)) - ((float) ($data['issued_qty'] ?? 0)), 3);
                break;
            case 'boq-items':
                if (empty($data['amount'])) $data['amount'] = round(((float) ($data['qty'] ?? 0)) * ((float) ($data['rate'] ?? 0)), 2);
                break;
            case 'attendances':
                if (!empty($data['check_in']) && !empty($data['check_out']) && empty($data['hours_worked'])) {
                    $in = strtotime($data['check_in']); $out = strtotime($data['check_out']);
                    if ($out < $in) $out += 86400;
                    $data['hours_worked'] = round(($out - $in) / 3600, 2);
                }
                break;
            case 'leave-applications':
                if (!empty($data['from_date']) && !empty($data['to_date']) && empty($data['days_requested'])) {
                    $data['days_requested'] = max(1, (int) round((strtotime($data['to_date']) - strtotime($data['from_date'])) / 86400) + 1);
                }
                break;
            case 'staff-advances':
                $m = max(1, (int) ($data['repayment_months'] ?? 1));
                if (empty($data['monthly_deduction'])) $data['monthly_deduction'] = round(((float) ($data['amount'] ?? 0)) / $m, 2);
                $data['balance'] = round(((float) ($data['amount'] ?? 0)) - (float) ($record->amount_repaid ?? 0), 2);
                break;
            case 'fixed-assets':
                if ($record === null) { $data['accumulated_depreciation'] = 0; $data['net_book_value'] = (float) ($data['purchase_cost'] ?? 0) - (float) ($data['salvage_value'] ?? 0); }
                break;
            case 'fiscal-years':
                if (!empty($data['is_current'])) \App\Models\FiscalYear::where('is_current', true)->update(['is_current' => false]);
                break;
            case 'price-lists':
                if (!empty($data['is_default'])) \App\Models\PriceList::where('is_default', true)->update(['is_default' => false]);
                break;
            case 'customers': case 'suppliers': case 'bank-accounts': case 'accounts':
                if ($record === null) {
                    $open = (float) ($data['opening_balance'] ?? 0);
                    $data['current_balance'] = $data['current_balance'] ?? $open;
                }
                unset($data['current_balance']);
                if ($record === null && $key === 'customers') $data['current_balance'] = (float) ($data['opening_balance'] ?? 0);
                if ($record === null && $key === 'suppliers') $data['current_balance'] = (float) ($data['opening_balance'] ?? 0);
                if ($record === null && $key === 'bank-accounts') $data['current_balance'] = (float) ($data['opening_balance'] ?? 0);
                if ($record === null && $key === 'accounts') $data['current_balance'] = (float) ($data['opening_balance'] ?? 0);
                break;
            case 'employees':
                if (isset($data['allowances']) && is_string($data['allowances'])) {
                    $allow = [];
                    foreach (preg_split('/\r?\n/', $data['allowances']) as $line) {
                        if (str_contains($line, '=')) { [$k, $v] = explode('=', $line, 2); $allow[trim($k)] = (float) trim($v); }
                    }
                    $data['allowances'] = $allow;
                }
                break;
        }
        return $data;
    }
    public static function posted(string $key, $record, bool $isNew): void {
        try {
            switch ($key) {
                case 'currencies':
                    \App\Services\CurrencyService::bust();
                    if (!$isNew && $record->wasChanged('rate_to_ghs')) {
                        \App\Models\CurrencyRateHistory::updateOrCreate(
                            ['currency_code' => $record->code, 'effective_date' => date('Y-m-d')],
                            ['rate_to_ghs' => $record->rate_to_ghs, 'set_by' => \Illuminate\Support\Facades\Auth::id()]);
                    }
                    break;
                case 'meter-readings':
                    $eq = Equipment::find($record->equipment_id);
                    if ($eq) {
                        if ($record->meter_type === 'hours') $eq->current_hours = max($eq->current_hours, $record->reading_value);
                        else $eq->current_km = max($eq->current_km, $record->reading_value);
                        $eq->save();
                    }
                    break;
                case 'fuel-logs':
                    $eq = Equipment::find($record->equipment_id);
                    if ($eq) {
                        if ($record->meter_hours) $eq->current_hours = max($eq->current_hours, $record->meter_hours);
                        if ($record->meter_km) $eq->current_km = max($eq->current_km, $record->meter_km);
                        $eq->save();
                    }
                    break;
                case 'equipment-deployments':
                    $eq = Equipment::find($record->equipment_id);
                    if ($eq) {
                        if ($record->status === 'deployed') { $eq->status = 'deployed'; $eq->current_project_id = $record->project_id; $eq->current_quarry_id = $record->quarry_id ?? $eq->current_quarry_id; }
                        else { $eq->status = 'available'; if ($record->project_id) $eq->current_project_id = null; }
                        $eq->save();
                    }
                    break;
                case 'project-tasks':
                    $p = Project::with('tasks')->find($record->project_id);
                    if ($p && $p->tasks->count()) {
                        $w = $p->tasks->sum('weight_factor') ?: 1;
                        $p->progress_percent = round($p->tasks->sum(fn($t) => $t->progress_percent * $t->weight_factor) / $w, 2);
                        $p->save();
                    }
                    break;
            }
        } catch (\Throwable $e) {}
    }
    public static function transition(string $key, $record, string $to): void {
        if ($key === 'tax-filings' && $to === 'filed') {
            $record->filing_date ??= now()->format('Y-m-d');
            $record->filed_by ??= \Illuminate\Support\Facades\Auth::id();
            $record->save();
        }
        if ($key === 'staff-advances' && $to === 'approved') {
            $record->balance = round($record->amount - $record->amount_repaid, 2);
            $record->save();
        }
    }
}
