<?php

namespace Modules\Vrc\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Modules\Vrc\Entities\VrcInspection;
use Modules\Vrc\Entities\VrcInspectionResult;
use Modules\Vrc\Entities\VrcInspectionTemplate;
use Modules\Vrc\Entities\VrcRepairOrder;
use Modules\Vrc\Entities\VrcRepairOrderService;
use Modules\Vrc\Entities\VrcService;
use Modules\Vrc\Services\Contracts\MediaServiceContract;
use Modules\Vrc\Services\RepairOrder\RepairOrderService;

class InspectionController extends VrcBaseController
{
    public function __construct(
        protected MediaServiceContract $media,
        protected RepairOrderService $orders
    ) {
    }

    /** Touch-friendly inspection form for a repair order. */
    public function create($repairOrderId)
    {
        $this->guard('vrc.inspection.manage');
        $ro = VrcRepairOrder::where('business_id', $this->businessId())->findOrFail($repairOrderId);

        return view('vrc::inspections.create', [
            'ro'        => $ro,
            'templates' => VrcInspectionTemplate::where('business_id', $this->businessId())->where('is_active', true)->pluck('name', 'id')->toArray(),
            'type'      => request('type', 'intake'),
        ]);
    }

    /** Create an inspection from a template (or blank) on a repair order. */
    public function store(Request $request, $repairOrderId)
    {
        $this->guard('vrc.inspection.manage');
        $ro = VrcRepairOrder::where('business_id', $this->businessId())->findOrFail($repairOrderId);

        $data = $this->validate($request, [
            'template_id' => 'nullable|integer',
            'type'        => 'required|in:intake,in_process,final',
            'summary'     => 'nullable|string',
        ]);

        DB::beginTransaction();
        try {
            $inspection = VrcInspection::create([
                'business_id'    => $this->businessId(),
                'repair_order_id' => $ro->id,
                'template_id'    => $data['template_id'] ?? null,
                'type'           => $data['type'],
                'performed_by'   => $this->userId(),
                'performed_at'   => now(),
                'summary'        => $data['summary'] ?? null,
                'status'         => 'draft',
            ]);

            // Seed result rows from the template items.
            if (! empty($data['template_id'])) {
                $template = VrcInspectionTemplate::with('items')->find($data['template_id']);
                foreach (optional($template)->items ?? [] as $item) {
                    VrcInspectionResult::create([
                        'business_id'      => $this->businessId(),
                        'inspection_id'    => $inspection->id,
                        'template_item_id' => $item->id,
                        'label'            => $item->label,
                    ]);
                }
            }
            DB::commit();

            return redirect()->route('vrc.inspections.edit', $inspection->id);
        } catch (\Exception $e) {
            DB::rollBack();
            \Log::emergency($e->getMessage());
            return back()->with('status', ['success' => 0, 'msg' => __('messages.something_went_wrong')]);
        }
    }

    public function edit($id)
    {
        $this->guard('vrc.inspection.manage');
        $inspection = VrcInspection::with('results')->where('business_id', $this->businessId())->findOrFail($id);

        return view('vrc::inspections.edit', [
            'inspection' => $inspection,
            'services'   => VrcService::where('business_id', $this->businessId())->where('is_active', true)->orderBy('name')->pluck('name', 'id')->toArray(),
        ]);
    }

    /** Printable inspection report (PDF) via the ERP mPDF mechanism. */
    public function reportPdf($id)
    {
        $this->guard('vrc.inspection.view');
        $inspection = VrcInspection::with(['results', 'repairOrder.vehicle.make', 'repairOrder.vehicle.model'])
            ->where('business_id', $this->businessId())->findOrFail($id);

        $html = view('vrc::inspections.report_pdf', compact('inspection'))->render();
        $mpdf = $this->getMpdf();
        $mpdf->WriteHTML($html);

        return $mpdf->Output('inspection-' . $inspection->id . '.pdf', 'I');
    }

    /** Save the per-item results (status / value / note / recommended service). */
    public function saveResults(Request $request, $id)
    {
        $this->guard('vrc.inspection.manage');
        $inspection = VrcInspection::where('business_id', $this->businessId())->findOrFail($id);

        try {
            DB::transaction(function () use ($request, $inspection) {
                foreach ((array) $request->input('result', []) as $resultId => $fields) {
                    VrcInspectionResult::where('inspection_id', $inspection->id)->where('id', $resultId)->update([
                        'result'                 => $fields['result'] ?? null,
                        'value'                  => $fields['value'] ?? null,
                        'note'                   => $fields['note'] ?? null,
                        'recommended_service_id' => $fields['recommended_service_id'] ?? null,
                    ]);
                }
                // Allow ad-hoc rows.
                foreach ((array) $request->input('new_label', []) as $i => $label) {
                    if (trim((string) $label) === '') {
                        continue;
                    }
                    VrcInspectionResult::create([
                        'business_id'   => $inspection->business_id,
                        'inspection_id' => $inspection->id,
                        'label'         => $label,
                        'result'        => $request->input('new_result')[$i] ?? null,
                        'note'          => $request->input('new_note')[$i] ?? null,
                    ]);
                }
                $diagram = json_decode((string) $request->input('body_diagram', ''), true);
                $tdResult = $request->input('test_drive_result');
                $inspection->update([
                    'status'              => $request->boolean('complete') ? 'completed' : 'draft',
                    'summary'             => $request->input('summary'),
                    'body_diagram'        => is_array($diagram) ? $diagram : null,
                    'test_drive_done'     => $request->boolean('test_drive_done'),
                    'test_drive_result'   => in_array($tdResult, ['pass', 'fail'], true) ? $tdResult : null,
                    'test_drive_odometer' => $request->filled('test_drive_odometer') ? (int) $request->input('test_drive_odometer') : null,
                    'test_drive_notes'    => $request->input('test_drive_notes'),
                ]);
            });

            return $this->ok(__('vrc::lang.updated_success'));
        } catch (\Exception $e) {
            \Log::emergency($e->getMessage());
            return $this->fail();
        }
    }

    /** Attach photos to a result row via the ERP media module. */
    public function photos(Request $request, $id)
    {
        $this->guard('vrc.inspection.manage');
        $inspection = VrcInspection::where('business_id', $this->businessId())->findOrFail($id);

        try {
            $this->media->upload($this->businessId(), $inspection, $request, 'photos');
            return $this->ok(__('vrc::lang.photos_uploaded'));
        } catch (\Exception $e) {
            \Log::emergency($e->getMessage());
            return $this->fail();
        }
    }

    /** Store a signature (base64 from a signature pad) via ERP media. */
    public function sign(Request $request, $id)
    {
        $this->guard('vrc.inspection.manage');
        $inspection = VrcInspection::where('business_id', $this->businessId())->findOrFail($id);
        $request->validate(['signature' => 'required|string', 'who' => 'required|in:customer,advisor']);

        try {
            $path = $this->media->storeBase64($request->signature);
            $col = $request->who === 'advisor' ? 'advisor_signature_path' : 'customer_signature_path';
            $inspection->update([$col => $path]);
            return $this->ok(__('vrc::lang.signature_saved'));
        } catch (\Exception $e) {
            \Log::emergency($e->getMessage());
            return $this->fail();
        }
    }

    /**
     * Push flagged items with a recommended service onto the repair order as
     * service lines (the working estimate). Spec §6.5 push-to-estimate.
     */
    public function pushToEstimate($id)
    {
        $this->guard('vrc.inspection.manage');
        $inspection = VrcInspection::with('results')->where('business_id', $this->businessId())->findOrFail($id);
        $ro = VrcRepairOrder::where('business_id', $this->businessId())->findOrFail($inspection->repair_order_id);

        try {
            $added = 0;
            DB::transaction(function () use ($inspection, $ro, &$added) {
                foreach ($inspection->results as $r) {
                    if (! $r->recommended_service_id) {
                        continue;
                    }
                    $svc = VrcService::find($r->recommended_service_id);
                    if (! $svc) {
                        continue;
                    }
                    VrcRepairOrderService::create([
                        'business_id'    => $ro->business_id,
                        'repair_order_id' => $ro->id,
                        'service_id'     => $svc->id,
                        'description'    => $svc->name . ' — ' . $r->label,
                        'hsn_sac'        => $svc->hsn_sac,
                        'labor_hours'    => $svc->default_labor_hours,
                        'qty'            => 1,
                        'unit_price'     => $svc->default_price,
                        'tax_rate_id'    => $svc->taxable ? $svc->tax_rate_id : null,
                    ]);
                    $added++;
                }
                if ($added > 0) {
                    $this->orders->recomputeTotals($ro);
                }
            });

            return $this->ok(trans_choice('vrc::lang.pushed_services', $added, ['count' => $added]));
        } catch (\Exception $e) {
            \Log::emergency($e->getMessage());
            return $this->fail();
        }
    }
}
