<?php

namespace App\Http\Controllers;

use App\Enums\FolderPriority;
use App\Enums\FolderStatus;
use App\Enums\FolderType;
use App\Http\Requests\StoreFolderRequest;
use App\Http\Requests\UpdateFolderRequest;
use App\Models\Client;
use App\Models\Folder;
use App\Models\MediaDownload;
use App\Models\Workspace;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;

class FolderController extends Controller
{
    protected function folderTypeLabels(): array
    {
        return [
            FolderType::VAT => 'TVA',
            FolderType::VatMonthly => 'TVA mensuelle',
            FolderType::VatQuarterly => 'TVA trimestrielle',
            FolderType::CorporateTax => 'IS',
            FolderType::IncomeTax => 'IR',
            FolderType::CNSS => 'CNSS',
            FolderType::AnnualBalance => 'Bilan',
            FolderType::Other => 'Autre',
        ];
    }

    protected function folderStatusLabels(): array
    {
        return [
            FolderStatus::Draft => 'Brouillon',
            FolderStatus::WaitingDocuments => 'En attente documents',
            FolderStatus::DocumentsReceived => 'Documents reçus',
            FolderStatus::Processing => 'En cours de traitement',
            FolderStatus::AdditionalDocumentsRequested => 'Pièces complémentaires demandées',
            FolderStatus::WaitingClientValidation => 'En attente validation client',
            FolderStatus::Validated => 'Validé',
            FolderStatus::Closed => 'Clôturé',
            FolderStatus::Cancelled => 'Annulé',
        ];
    }

    protected function folderPriorityLabels(): array
    {
        return [
            FolderPriority::Low => 'Basse',
            FolderPriority::Medium => 'Normale',
            FolderPriority::High => 'Haute',
        ];
    }

    protected function currentWorkspace(Request $request): Workspace
    {
        $workspaceId = $request->session()->get('current_workspace_id');

        return Workspace::query()->findOrFail($workspaceId);
    }

    /**
     * Display a listing of the folders.
     */
    public function index(Request $request): Response
    {
        $workspace = $this->currentWorkspace($request);

        $perPage = min(max((int) $request->input('per_page', 10), 10), 100);

        $folders = $workspace->folders()
            ->with(['client', 'assignee'])
            ->latest()
            ->paginate($perPage)
            ->through(fn (Folder $folder) => [
                'id' => $folder->id,
                'title' => $folder->title,
                'type' => $folder->type->value,
                'client_name' => $folder->client->company_name,
                'status' => $folder->status->value,
                'due_date' => $folder->due_date?->format('Y-m-d'),
                'showUrl' => route('folders.show', $folder),
                'editUrl' => route('folders.edit', $folder),
                'destroyUrl' => route('folders.destroy', $folder),
            ]);

        return Inertia::render('folders/Index', [
            'folders' => $folders,
            'createUrl' => route('folders.create'),
            'workspaceName' => $workspace->name,
        ]);
    }

    /**
     * Show the form for creating a new folder.
     */
    public function create(Request $request): Response
    {
        $workspace = $this->currentWorkspace($request);
        $initialClientId = $request->integer('client_id', 0) ?: null;

        return Inertia::render('folders/Create', [
            'indexUrl' => route('folders.index'),
            'storeUrl' => route('folders.store'),
            'initialClientId' => $initialClientId,
            'folderTypeLabels' => $this->folderTypeLabels(),
            'folderStatusLabels' => $this->folderStatusLabels(),
            'folderPriorityLabels' => $this->folderPriorityLabels(),
            'clients' => $workspace->clients()->orderBy('company_name')->get(['id', 'company_name'])->map(fn (Client $c) => [
                'id' => $c->id,
                'company_name' => $c->company_name,
            ])->values()->all(),
            'workspaceUsers' => $workspace->users()
                ->orderBy('users.name')
                ->select('users.id', 'users.name', 'users.email')
                ->get()
                ->map(fn ($u) => [
                    'id' => $u->id,
                    'name' => $u->name,
                    'email' => $u->email,
                ])->values()->all(),
        ]);
    }

    /**
     * Store a newly created folder in storage.
     */
    public function store(StoreFolderRequest $request): RedirectResponse
    {
        $workspace = $this->currentWorkspace($request);
        $data = $request->validated();
        $data['workspace_id'] = $workspace->id;
        $data['created_by'] = $request->user()?->id;
        $data['status'] = $data['status'] ?? FolderStatus::Draft->value;

        Folder::query()->create($data);

        return to_route('folders.index');
    }

    /**
     * Display the specified folder.
     */
    public function show(Request $request, Folder $folder): Response
    {
        $workspace = $this->currentWorkspace($request);
        $this->authorizeFolder($workspace, $folder);

        $folder->load(['client', 'creator', 'assignee', 'messages' => fn ($q) => $q->with(['senderUser', 'senderClient'])->latest()]);

        $allMedia = $folder->getMedia('documents');
        $downloadedMediaIds = MediaDownload::query()
            ->where('user_id', $request->user()->id)
            ->whereIn('media_id', $allMedia->pluck('id'))
            ->pluck('media_id')
            ->all();

        $messages = $folder->messages->map(function ($m) use ($folder, $allMedia, $downloadedMediaIds) {
            $attachments = $allMedia
                ->filter(fn ($media) => $media->getCustomProperty('message_id') === $m->id)
                ->map(fn ($media) => [
                    'id' => $media->id,
                    'file_name' => $media->file_name,
                    'mime_type' => $media->mime_type,
                    'size' => $media->human_readable_size,
                    'downloadUrl' => route('folders.media.download', ['folder' => $folder, 'mediaId' => $media->id]),
                    'is_downloaded' => in_array($media->id, $downloadedMediaIds),
                ])
                ->values()
                ->all();

            $confirmationStatus = null;
            if ($m->type->value === 'confirmation') {
                $confirmationStatus = $folder->refused_at ? 'refused' : ($folder->validated_at ? 'confirmed' : 'pending');
            }

            return [
                'id' => $m->id,
                'type' => $m->type->value,
                'body' => $m->body,
                'sent_by_type' => $m->sent_by_type->value,
                'sender_name' => $m->sender_name,
                'created_at' => $m->created_at->format('Y-m-d H:i'),
                'attachments' => $attachments,
                'confirmation_status' => $confirmationStatus,
            ];
        })->values()->all();

        $documents = $allMedia->map(fn ($m) => [
            'id' => $m->id,
            'name' => $m->name,
            'file_name' => $m->file_name,
            'size' => $m->human_readable_size,
            'created_at' => $m->created_at->format('d/m/Y H:i'),
            'uploaded_by' => $m->getCustomProperty('uploaded_by_type') === 'user' ? 'Comptable' : 'Client',
            'downloadUrl' => route('folders.media.download', ['folder' => $folder, 'mediaId' => $m->id]),
            'is_downloaded' => in_array($m->id, $downloadedMediaIds),
        ])->values()->all();

        return Inertia::render('folders/Show', [
            'folder' => [
                'id' => $folder->id,
                'title' => $folder->title,
                'type' => $folder->type->value,
                'client_id' => $folder->client_id,
                'client_name' => $folder->client->company_name,
                'period_year' => $folder->period_year,
                'period_month' => $folder->period_month,
                'period_quarter' => $folder->period_quarter,
                'due_date' => $folder->due_date?->format('Y-m-d'),
                'status' => $folder->status->value,
                'priority' => $folder->priority?->value,
                'assigned_to' => $folder->assigned_to,
                'assignee_name' => $folder->assignee?->name,
                'validated_at' => $folder->validated_at?->format('Y-m-d H:i'),
                'closed_at' => $folder->closed_at?->format('Y-m-d H:i'),
                'notes_internal' => $folder->notes_internal,
                'notes_client' => $folder->notes_client,
                'created_at' => $folder->created_at?->format('Y-m-d H:i'),
            ],
            'messages' => $messages,
            'documents' => $documents,
            'messagesStoreUrl' => route('folders.messages.store', $folder),
            'mediaStoreUrl' => route('folders.media.store', $folder),
            'messageTypeLabels' => [
                'invite' => 'Invitation',
                'situation' => 'Situation',
                'file_request' => 'Demande de pièces',
                'confirmation' => 'Demande de validation',
                'text' => 'Message',
            ],
            'indexUrl' => route('folders.index'),
            'editUrl' => route('folders.edit', $folder),
            'workspaceUsers' => $workspace->users()->orderBy('users.name')
                ->select('users.id', 'users.name', 'users.email')
                ->get()->map(fn ($u) => ['id' => $u->id, 'name' => $u->name])
                ->values()->all(),
            'mentionStoreUrl' => route('folders.mentions.store', $folder),
            'canMention' => in_array(
                $workspace->users()->where('users.id', $request->user()->id)->first()?->pivot?->role?->value,
                ['owner', 'manager']
            ),
        ]);
    }

    /**
     * Show the form for editing the specified folder.
     */
    public function edit(Request $request, Folder $folder): Response
    {
        $workspace = $this->currentWorkspace($request);
        $this->authorizeFolder($workspace, $folder);

        return Inertia::render('folders/Edit', [
            'folder' => [
                'id' => $folder->id,
                'title' => $folder->title,
                'type' => $folder->type->value,
                'client_id' => $folder->client_id,
                'period_year' => $folder->period_year,
                'period_month' => $folder->period_month,
                'period_quarter' => $folder->period_quarter,
                'due_date' => $folder->due_date?->format('Y-m-d'),
                'status' => $folder->status->value,
                'priority' => $folder->priority?->value,
                'assigned_to' => $folder->assigned_to,
                'notes_internal' => $folder->notes_internal,
                'notes_client' => $folder->notes_client,
                'created_at' => $folder->created_at?->format('Y-m-d H:i'),
            ],
            'indexUrl' => route('folders.index'),
            'updateUrl' => route('folders.update', $folder),
            'folderTypeLabels' => $this->folderTypeLabels(),
            'folderStatusLabels' => $this->folderStatusLabels(),
            'folderPriorityLabels' => $this->folderPriorityLabels(),
            'clients' => $workspace->clients()->orderBy('company_name')->get(['id', 'company_name'])->map(fn (Client $c) => [
                'id' => $c->id,
                'company_name' => $c->company_name,
            ])->values()->all(),
            'workspaceUsers' => $workspace->users()
                ->orderBy('users.name')
                ->select('users.id', 'users.name', 'users.email')
                ->get()
                ->map(fn ($u) => [
                    'id' => $u->id,
                    'name' => $u->name,
                    'email' => $u->email,
                ])->values()->all(),
        ]);
    }

    /**
     * Update the specified folder in storage.
     */
    public function update(UpdateFolderRequest $request, Folder $folder): RedirectResponse
    {
        $workspace = $this->currentWorkspace($request);
        $this->authorizeFolder($workspace, $folder);

        $folder->update($request->validated());

        return to_route('folders.index');
    }

    /**
     * Remove the specified folder from storage.
     */
    public function destroy(Request $request, Folder $folder): RedirectResponse
    {
        $workspace = $this->currentWorkspace($request);
        $this->authorizeFolder($workspace, $folder);

        $folder->delete();

        return to_route('folders.index');
    }

    protected function authorizeFolder(Workspace $workspace, Folder $folder): void
    {
        if ($folder->workspace_id !== $workspace->id) {
            abort(404);
        }
    }
}
