<?php

namespace App\Http\Controllers;

use App\Models\DigitalForm;
use App\Models\DigitalFormItem;
use App\Models\Order;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;

class DigitalFormController extends Controller
{
    public function create(Order $order)
    {
        abort_unless(auth()->user()->canAccessBranch($order->branch_id), 403);

        return view('digital-forms.create', ['order' => $order->load('customer')]);
    }

    public function store(Request $request, Order $order)
    {
        abort_unless($request->user()->canAccessBranch($order->branch_id), 403);
        $data = $request->validate([
            'checklist' => ['nullable', 'array'],
            'general_note' => ['nullable', 'string', 'max:3000'],
            'signature_data' => ['nullable', 'string'],
            'evidence_images' => ['nullable', 'array', 'max:12'],
            'evidence_images.*' => ['nullable', 'string'],
            'evidence_files' => ['nullable', 'array', 'max:12'],
            'evidence_files.*' => ['nullable', 'image', 'max:5120'],
            'items' => ['nullable', 'array'],
            'items.*.item_name' => ['required', 'string'],
            'items.*.conditions' => ['nullable', 'array'],
            'items.*.note' => ['nullable', 'string'],
            'items.*.evidence_paths' => ['nullable', 'array'],
        ]);

        $retentionDays = (int) config('laundry.evidence_retention_days', 30);
        $directory = 'evidence/orders/'.$order->id;
        $evidencePaths = $this->storeEvidenceImages($request, $directory);

        $form = DigitalForm::query()->create([
            'order_id' => $order->id,
            'customer_id' => $order->customer_id,
            'user_id' => $request->user()->id,
            'checklist' => $data['checklist'] ?? [],
            'general_note' => $data['general_note'] ?? null,
            'evidence_paths' => $evidencePaths,
            'signature_path' => $this->storeDataImage($data['signature_data'] ?? null, $directory, 'signature'),
            'delete_after' => now()->addDays($retentionDays),
        ]);

        foreach ($data['items'] ?? [] as $item) {
            DigitalFormItem::query()->create($item + [
                'digital_form_id' => $form->id,
                'delete_after' => now()->addDays($retentionDays),
            ]);
        }

        return redirect()->route('digital-forms.show', $form)->with('status', 'Form pemeriksaan disimpan.');
    }

    public function show(DigitalForm $digitalForm)
    {
        $digitalForm->load(['items', 'order.customer']);
        abort_unless(auth()->user()->canAccessBranch($digitalForm->order->branch_id), 403);

        return view('digital-forms.show', compact('digitalForm'));
    }

    private function storeEvidenceImages(Request $request, string $directory): array
    {
        $paths = [];

        foreach ($request->input('evidence_images', []) as $image) {
            if ($path = $this->storeDataImage($image, $directory, 'photo')) {
                $paths[] = $path;
            }
        }

        foreach ($request->file('evidence_files', []) as $file) {
            $paths[] = $file->store($directory, 'public');
        }

        return $paths;
    }

    private function storeDataImage(?string $dataUrl, string $directory, string $prefix): ?string
    {
        if (! $dataUrl) {
            return null;
        }

        if (! preg_match('/^data:image\/(png|jpe?g|webp);base64,/', $dataUrl, $matches)) {
            throw ValidationException::withMessages([$prefix => 'Format gambar tidak valid.']);
        }

        $binary = base64_decode(substr($dataUrl, strpos($dataUrl, ',') + 1), true);

        if ($binary === false) {
            throw ValidationException::withMessages([$prefix => 'Gambar tidak bisa diproses.']);
        }

        $extension = $matches[1] === 'jpeg' ? 'jpg' : $matches[1];
        $path = $directory.'/'.$prefix.'-'.Str::uuid().'.'.$extension;
        Storage::disk('public')->put($path, $binary);

        return $path;
    }
}
