<?php

namespace App\Http\Controllers\Additional;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\View\View;
use Symfony\Component\HttpFoundation\BinaryFileResponse;

/**
 * 추가기능 > DOCX 관리 컨트롤러
 * 파일시스템 스캔 기반으로 DOCX 파일 목록 조회 및 다운로드
 */
class DocxController extends Controller
{
    private array $scanPaths = [
        '/var/www/docs/contracts/docx' => ['label' => '계약서', 'source' => 'docs'],
        '/var/www/docs' => ['label' => '문서', 'source' => 'docs'],
        '/var/www/mng/docs' => ['label' => '교육/문서', 'source' => 'mng'],
        '/var/www/mng/public/docs' => ['label' => '공개 문서', 'source' => 'mng'],
        '/var/www/sales-docs' => ['label' => '영업', 'source' => 'sales'],
    ];

    /**
     * DOCX 목록 페이지
     */
    public function index(Request $request): View|Response
    {
        if ($request->header('HX-Request')) {
            return response('', 200)->header('HX-Redirect', route('additional.docx.index'));
        }

        $files = $this->scanDocxFiles();
        $categories = collect($files)->pluck('category')->unique()->sort()->values()->all();
        $totalSize = collect($files)->sum('size_bytes');

        return view('additional.docx.index', [
            'files' => $files,
            'categories' => $categories,
            'totalCount' => count($files),
            'totalSize' => $this->formatFileSize($totalSize),
        ]);
    }

    /**
     * DOCX 파일 다운로드
     */
    public function download(Request $request): BinaryFileResponse|Response
    {
        $filePath = $request->query('file');

        if (! $filePath) {
            abort(400, '파일 경로가 지정되지 않았습니다.');
        }

        // 경로 트래버설 방지
        if (str_contains($filePath, '..')) {
            abort(403, '잘못된 파일 경로입니다.');
        }

        // .docx 확장자만 허용
        if (strtolower(pathinfo($filePath, PATHINFO_EXTENSION)) !== 'docx') {
            abort(403, '허용되지 않는 파일 형식입니다.');
        }

        // 허용된 base path에 속하는지 검증
        $allowed = false;
        foreach (array_keys($this->scanPaths) as $basePath) {
            if (str_starts_with($filePath, $basePath.'/')) {
                $allowed = true;
                break;
            }
        }

        if (! $allowed) {
            abort(403, '허용되지 않는 경로입니다.');
        }

        if (! file_exists($filePath)) {
            abort(404, '파일을 찾을 수 없습니다.');
        }

        return response()->download($filePath, basename($filePath), [
            'Content-Type' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        ]);
    }

    /**
     * 모든 스캔 경로에서 DOCX 파일 수집
     */
    private function scanDocxFiles(): array
    {
        $files = [];
        $seenPaths = [];

        foreach ($this->scanPaths as $basePath => $meta) {
            if (! is_dir($basePath)) {
                continue;
            }

            $this->findDocxInDirectory($basePath, $basePath, $meta, $files, $seenPaths);
        }

        // 수정일 내림차순 정렬
        usort($files, fn ($a, $b) => $b['modified_at'] <=> $a['modified_at']);

        return $files;
    }

    /**
     * 디렉토리에서 DOCX 파일 재귀 검색
     */
    private function findDocxInDirectory(string $dir, string $basePath, array $meta, array &$files, array &$seenPaths): void
    {
        $items = scandir($dir);
        if ($items === false) {
            return;
        }

        foreach ($items as $item) {
            if ($item === '.' || $item === '..') {
                continue;
            }

            $fullPath = $dir.'/'.$item;

            if (is_dir($fullPath)) {
                if (isset($this->scanPaths[$fullPath])) {
                    continue;
                }
                $this->findDocxInDirectory($fullPath, $basePath, $meta, $files, $seenPaths);

                continue;
            }

            if (strtolower(pathinfo($item, PATHINFO_EXTENSION)) !== 'docx') {
                continue;
            }

            // 중복 방지 (realpath 기반)
            $realPath = realpath($fullPath);
            if ($realPath && isset($seenPaths[$realPath])) {
                continue;
            }
            if ($realPath) {
                $seenPaths[$realPath] = true;
            }

            $relativePath = str_replace($basePath.'/', '', $fullPath);
            $sizeBytes = filesize($fullPath);
            $modifiedAt = filemtime($fullPath);

            $files[] = [
                'name' => $item,
                'path' => $fullPath,
                'relative_path' => $relativePath,
                'category' => $meta['label'],
                'source' => $meta['source'],
                'source_dir' => str_replace('/var/www/', '', $basePath),
                'size_bytes' => $sizeBytes,
                'size' => $this->formatFileSize($sizeBytes),
                'modified_at' => $modifiedAt,
                'modified_date' => date('Y-m-d H:i', $modifiedAt),
            ];
        }
    }

    private function formatFileSize(int $bytes): string
    {
        if ($bytes >= 1048576) {
            return number_format($bytes / 1048576, 1).' MB';
        }

        return number_format($bytes / 1024, 0).' KB';
    }
}
