<?php

namespace App\Services\Reimbursements;

use App\Models\ReimbursementBatchAdminFile;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Str;
use RuntimeException;

class ReimbursementFileService
{
    public function receiptUrl(?string $filename): ?string
    {
        if (!$filename) {
            return null;
        }
        $safe = basename(trim($filename));
        return $safe !== '' ? url('/api/v1/files/reimbursements/' . $safe) : null;
    }

    public function expenseReceiptUrl(?string $filename): ?string
    {
        if (!$filename) {
            return null;
        }
        $safe = basename(trim($filename));
        return $safe !== '' ? url('/api/v1/files/receipts/' . $safe) : null;
    }

    public function adminFileUrl(string $filename, string $mode = 'inline'): string
    {
        return url('/api/v1/finance/reimbursements/batches/admin-files/' . rawurlencode($filename) . '/' . $mode);
    }

    public function storeReceipt(?UploadedFile $file): ?string
    {
        if (!$file || !$file->isValid()) {
            return null;
        }

        if (($file->getSize() ?? 0) <= 0) {
            return null;
        }

        $dir = $this->ensureUploadDir();
        $extension = $file->getClientOriginalExtension();
        $extension = $extension !== '' ? '.' . strtolower($extension) : '';
        $filename = 'reimb_' . date('Ymd_His') . '_' . Str::random(8) . $extension;

        if (!$file->move($dir, $filename)) {
            throw new RuntimeException('Unable to save uploaded file.');
        }

        return $filename;
    }

    public function storeAdminFile(int $batchId, int $adminId, UploadedFile $file, int $userId): array
    {
        $dir = $this->ensureUploadDir();
        $extension = $file->getClientOriginalExtension();
        $extension = $extension !== '' ? '.' . strtolower($extension) : '';
        $filename = 'batch_check_' . date('Ymd_His') . '_' . Str::random(8) . $extension;

        if (!$file->move($dir, $filename)) {
            throw new RuntimeException('Unable to save uploaded file.');
        }

        $existing = ReimbursementBatchAdminFile::query()
            ->where('batch_id', $batchId)
            ->where('admin_id', $adminId)
            ->first();

        if ($existing && !empty($existing->filename)) {
            $oldPath = $dir . DIRECTORY_SEPARATOR . $existing->filename;
            if (is_file($oldPath)) {
                @unlink($oldPath);
            }
        }

        $payload = [
            'batch_id' => $batchId,
            'admin_id' => $adminId,
            'filename' => $filename,
            'original_filename' => $file->getClientOriginalName(),
            'uploaded_at' => now(),
            'uploaded_by' => $userId ?: null,
        ];

        if ($existing) {
            $existing->fill($payload);
            $existing->save();
        } else {
            ReimbursementBatchAdminFile::query()->create($payload);
        }

        return [
            'filename' => $filename,
            'original_filename' => $file->getClientOriginalName(),
            'url' => $this->adminFileUrl($filename, 'inline'),
        ];
    }

    private function ensureUploadDir(): string
    {
        $dir = storage_path('uploads/reimbursements');

        if (!is_dir($dir)) {
            if (!@mkdir($dir, 0755, true) && !is_dir($dir)) {
                throw new RuntimeException('Upload directory is not available.');
            }
        }

        if (!is_writable($dir)) {
            throw new RuntimeException('Upload directory is not writable.');
        }

        return $dir;
    }
}
