<?php

namespace App\Services\Exams;

use Illuminate\Http\UploadedFile;

class ExamDraftFileService
{
    public function storeUploadedFile(UploadedFile $file, string $subdir, array $allowedExtensions, int $maxBytes): ?array
    {
        $ext = strtolower($file->getClientOriginalExtension());
        if (!in_array($ext, $allowedExtensions, true)) {
            return null;
        }
        if ($file->getSize() > $maxBytes) {
            return null;
        }

        $destination = storage_path('uploads/' . trim($subdir, '/'));
        if (!is_dir($destination)) {
            mkdir($destination, 0755, true);
        }

        $filename = uniqid('exam_', true) . '.' . $ext;
        try {
            $file->move($destination, $filename);
            return [
                'stored' => $filename,
                'original' => $file->getClientOriginalName(),
                'extension' => $ext,
            ];
        } catch (\Throwable) {
            return null;
        }
    }

    public function ensurePdfExists(string $finalFilename, ?string $originalExt, string $subdir): ?string
    {
        $pdfNeighbor = $this->neighborPdfIfExists($finalFilename, $subdir);
        if ($pdfNeighbor !== null) {
            return $pdfNeighbor;
        }
        $ext = strtolower((string) $originalExt);
        if ($ext === 'pdf') {
            $path = $this->fullUploadPath($subdir, $finalFilename);
            return is_file($path) ? $finalFilename : null;
        }
        return $this->convertDocToPdf($this->fullUploadPath($subdir, $finalFilename), $subdir);
    }

    public function copyDraftToFinal(string $draftFilename, string $sourceDir, string $targetDir): ?string
    {
        $source = $this->fullUploadPath($sourceDir, $draftFilename);
        if (!is_file($source)) {
            return null;
        }
        $destinationDir = storage_path('uploads/' . trim($targetDir, '/'));
        if (!is_dir($destinationDir)) {
            mkdir($destinationDir, 0755, true);
        }
        $ext = pathinfo($draftFilename, PATHINFO_EXTENSION);
        $destName = uniqid('final_', true) . '.' . $ext;
        $destPath = $destinationDir . '/' . $destName;
        if (!@copy($source, $destPath)) {
            return null;
        }
        return $destName;
    }

    private function convertDocToPdf(string $sourcePath, string $targetSubdir): ?string
    {
        $ext = strtolower(pathinfo($sourcePath, PATHINFO_EXTENSION));
        if (!in_array($ext, ['doc', 'docx'], true)) {
            return null;
        }

        $targetDir = storage_path('uploads/' . trim($targetSubdir, '/'));
        if (!is_dir($targetDir)) {
            mkdir($targetDir, 0755, true);
        }

        $base = pathinfo($sourcePath, PATHINFO_FILENAME);
        $targetPath = $targetDir . '/' . $base . '.pdf';

        $cmd = 'soffice --headless --convert-to pdf --outdir ' . escapeshellarg($targetDir) . ' ' . escapeshellarg($sourcePath) . ' 2>/dev/null';
        @exec($cmd);

        return is_file($targetPath) ? basename($targetPath) : null;
    }

    private function neighborPdfIfExists(string $filename, string $subdir): ?string
    {
        if ($filename === '') {
            return null;
        }
        $path = $this->fullUploadPath($subdir, $filename);
        $base = pathinfo($path, PATHINFO_FILENAME);
        $dir = pathinfo($path, PATHINFO_DIRNAME);
        $pdfPath = $dir . '/' . $base . '.pdf';
        return is_file($pdfPath) ? basename($pdfPath) : null;
    }

    private function fullUploadPath(string $subdir, string $filename): string
    {
        return storage_path('uploads/' . trim($subdir, '/') . '/' . $filename);
    }
}
