<?php

namespace Modules\Bms\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Modules\Bms\Entities\BmsAsset;
use Modules\Bms\Entities\BmsHall;
use Modules\Bms\Entities\BmsMaintenanceRequest;
use Modules\Bms\Services\Maintenance\MaintenanceService;
use Yajra\DataTables\Facades\DataTables;

/**
 * Maintenance oversight (P1, Release 2 §5.6). Raise requests for halls/offices,
 * drive the Submitted→…→Verified workflow, comment, assign, and watch SLA aging.
 */
class MaintenanceController extends BmsBaseController
{
    public function index()
    {
        $this->guard('bms.maintenance.view');

        if (request()->ajax()) {
            $halls = $this->hallsList();
            $locations = $this->locations();
            $users = $this->usersList();

            $rows = BmsMaintenanceRequest::where('business_id', $this->businessId())
                ->when(request()->filled('status'), fn ($q) => $q->where('status', request('status')))
                ->select(['id', 'code', 'hall_id', 'location_id', 'category', 'priority',
                    'title', 'status', 'assigned_to', 'due_at', 'created_at']);

            return DataTables::of($rows)
                ->addColumn('target', fn ($r) => $r->hall_id ? ($halls[$r->hall_id] ?? '—') : ($locations[$r->location_id] ?? __('bms::lang.office')))
                ->editColumn('category', fn ($r) => __('bms::lang.mcat_' . $r->category))
                ->editColumn('priority', fn ($r) => '<span class="label '.$this->prioClass($r->priority).'">'.__('bms::lang.prio_'.$r->priority).'</span>')
                ->editColumn('status', fn ($r) => '<span class="label '.$this->statusClass($r->status).'">'.__('bms::lang.mst_'.$r->status).'</span>')
                ->addColumn('assignee', fn ($r) => $r->assigned_to ? ($users[$r->assigned_to] ?? '—') : '<span class="text-muted">—</span>')
                ->addColumn('age', function ($r) {
                    $age = optional($r->created_at)->diffForHumans(null, true);
                    $overdue = $r->due_at && in_array($r->status, BmsMaintenanceRequest::OPEN_STATUSES, true) && $r->due_at->isPast();
                    return $overdue
                        ? '<span class="label label-danger">'.__('bms::lang.overdue').'</span> <small>'.$age.'</small>'
                        : '<small>'.$age.'</small>';
                })
                ->addColumn('action', fn ($r) => '<a href="'.route('bms.maintenance.show', $r->id).'" class="tw-dw-btn tw-dw-btn-xs tw-dw-btn-outline tw-dw-btn-primary"><i class="fa fas fa-eye"></i> '.__('bms::lang.open').'</a>')
                ->rawColumns(['priority', 'status', 'assignee', 'age', 'action'])
                ->make(true);
        }

        $counts = BmsMaintenanceRequest::where('business_id', $this->businessId())
            ->select('status', DB::raw('count(*) c'))->groupBy('status')->pluck('c', 'status');

        return view('bms::maintenance.index', ['counts' => $counts, 'statuses' => $this->statuses()]);
    }

    public function create()
    {
        $this->guard('bms.maintenance.manage');
        return view('bms::maintenance.create', $this->formData());
    }

    public function store(Request $request, MaintenanceService $svc)
    {
        $this->guard('bms.maintenance.manage');
        $data = $this->validate($request, [
            'hall_id'     => 'nullable|integer',
            'location_id' => 'nullable|integer',
            'asset_id'    => 'nullable|integer',
            'category'    => 'nullable|string|max:40',
            'priority'    => 'required|in:low,medium,high,urgent',
            'title'       => 'required|string|max:191',
            'description' => 'nullable|string|max:2000',
            'assigned_to' => 'nullable|integer',
        ]);

        try {
            $svc->create($this->businessId(), $data, $this->userId());
            return $this->ok(__('bms::lang.added_success'));
        } catch (\Exception $e) {
            \Log::emergency($e->getMessage());
            return $this->fail();
        }
    }

    public function show($id)
    {
        $this->guard('bms.maintenance.view');
        $req = BmsMaintenanceRequest::where('business_id', $this->businessId())
            ->with(['hall:id,name', 'asset:id,code,name', 'updates'])->findOrFail($id);

        return view('bms::maintenance.show', array_merge($this->formData(), [
            'req'      => $req,
            'next'     => MaintenanceService::FLOW[$req->status] ?? [],
            'users'    => $this->usersList(),
            'locations'=> $this->locations(),
        ]));
    }

    public function transition(Request $request, $id, MaintenanceService $svc)
    {
        $this->guard('bms.maintenance.manage');
        $data = $this->validate($request, [
            'to'          => 'required|string|max:20',
            'comment'     => 'nullable|string|max:1000',
            'assigned_to' => 'nullable|integer',
        ]);

        try {
            $req = BmsMaintenanceRequest::where('business_id', $this->businessId())->findOrFail($id);
            $svc->transition($req, $data['to'], $this->userId(), $data['comment'] ?? null, $data['assigned_to'] ?? null);
            return $this->ok(__('bms::lang.updated_success'));
        } catch (\RuntimeException $e) {
            return $this->fail($e->getMessage());
        } catch (\Exception $e) {
            \Log::emergency($e->getMessage());
            return $this->fail();
        }
    }

    public function comment(Request $request, $id, MaintenanceService $svc)
    {
        $this->guard('bms.maintenance.manage');
        $data = $this->validate($request, ['comment' => 'required|string|max:1000']);
        try {
            $req = BmsMaintenanceRequest::where('business_id', $this->businessId())->findOrFail($id);
            $svc->comment($req, $this->userId(), $data['comment']);
            return $this->ok(__('bms::lang.added_success'));
        } catch (\Exception $e) {
            \Log::emergency($e->getMessage());
            return $this->fail();
        }
    }

    public function destroy($id)
    {
        $this->guard('bms.maintenance.manage');
        try {
            $req = BmsMaintenanceRequest::where('business_id', $this->businessId())->findOrFail($id);
            DB::table('bms_maintenance_updates')->where('request_id', $req->id)->delete();
            $req->delete();
            return $this->ok(__('bms::lang.deleted_success'));
        } catch (\Exception $e) {
            \Log::emergency($e->getMessage());
            return $this->fail();
        }
    }

    // ---- helpers ---------------------------------------------------------

    protected function formData(): array
    {
        return [
            'halls'      => $this->hallsList(),
            'locations'  => $this->locations(),
            'assets'     => $this->assetsList(),
            'users'      => $this->usersList(),
            'categories' => $this->categories(),
            'priorities' => $this->priorities(),
        ];
    }

    protected function hallsList(): array
    {
        return DB::table('bms_halls')->leftJoin('bms_venues', 'bms_venues.id', '=', 'bms_halls.venue_id')
            ->where('bms_halls.business_id', $this->businessId())->orderBy('bms_halls.name')
            ->get(['bms_halls.id', 'bms_halls.name as hall_name', 'bms_venues.name as venue_name'])
            ->mapWithKeys(fn ($h) => [$h->id => trim($h->hall_name . ($h->venue_name ? ' — ' . $h->venue_name : ''))])->toArray();
    }

    protected function assetsList(): array
    {
        return BmsAsset::where('business_id', $this->businessId())->orderBy('code')
            ->get(['id', 'code', 'name'])->mapWithKeys(fn ($a) => [$a->id => $a->code . ' · ' . $a->name])->toArray();
    }

    protected function usersList(): array
    {
        return \App\User::where('business_id', $this->businessId())
            ->get(['id', 'first_name', 'surname', 'username'])
            ->mapWithKeys(fn ($u) => [$u->id => trim(($u->first_name ?? '') . ' ' . ($u->surname ?? '')) ?: $u->username])->toArray();
    }

    protected function categories(): array
    {
        return collect(['electrical', 'plumbing', 'hvac', 'furniture', 'av', 'structural', 'cleaning', 'other'])
            ->mapWithKeys(fn ($c) => [$c => __('bms::lang.mcat_' . $c)])->toArray();
    }

    protected function priorities(): array
    {
        return collect(['low', 'medium', 'high', 'urgent'])->mapWithKeys(fn ($p) => [$p => __('bms::lang.prio_' . $p)])->toArray();
    }

    protected function statuses(): array
    {
        return collect(['submitted', 'reviewed', 'assigned', 'in_progress', 'resolved', 'verified', 'cancelled'])
            ->mapWithKeys(fn ($s) => [$s => __('bms::lang.mst_' . $s)])->toArray();
    }

    protected function prioClass(string $p): string
    {
        return ['low' => 'label-default', 'medium' => 'label-info', 'high' => 'label-warning', 'urgent' => 'label-danger'][$p] ?? 'label-default';
    }

    protected function statusClass(string $s): string
    {
        return [
            'submitted' => 'label-default', 'reviewed' => 'label-info', 'assigned' => 'label-primary',
            'in_progress' => 'label-warning', 'resolved' => 'label-success', 'verified' => 'label-success', 'cancelled' => 'label-default',
        ][$s] ?? 'label-default';
    }
}
