<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\Submission;
use App\Models\AuditLog;
use App\Services\SubmissionService;
use App\Services\CsvExportService;
use Illuminate\Http\Request;

class SubmissionController extends Controller
{
    public function index(Request $request)
    {
        $query = Submission::latest()->orderByDesc('created_at');

        // Filtros
        if ($status = $request->get('status')) {
            $query->where('status', $status);
        }

        if ($flag = $request->get('flag')) {
            match ($flag) {
                'sem_correspondencia' => $query->where('flag_sem_correspondencia', true),
                'ip_fora_pt' => $query->where('flag_ip_fora_pt', true),
                'inconsistencia' => $query->where('flag_inconsistencia', true),
                'suspeito' => $query->where('flag_suspeito', true),
                default => null,
            };
        }

        if ($sort = $request->get('sort')) {
            $dir = $request->get('dir', 'desc');
            $query->reorder($sort, $dir);
        }

        $search = $request->get('search');

        // NIF: pesquisa exata via hash (campos encriptados nao suportam LIKE)
        if ($search && preg_match('/^\d{1,9}$/', $search)) {
            $query->where('nif_hash', hash('sha256', $search));
            $submissions = $query->paginate(25)->withQueryString();
        } elseif ($search) {
            // Nome: filtrar em PHP apos decrypt (volume pequeno)
            $all = $query->get()->filter(function ($s) use ($search) {
                return str_contains(mb_strtolower($s->nome_completo), mb_strtolower($search));
            });
            $page = max(1, (int) $request->get('page', 1));
            $perPage = 25;
            $submissions = new \Illuminate\Pagination\LengthAwarePaginator(
                $all->forPage($page, $perPage)->values(),
                $all->count(),
                $perPage,
                $page,
                ['path' => $request->url(), 'query' => $request->query()]
            );
        } else {
            $submissions = $query->paginate(25)->withQueryString();
        }

        $isContabilidade = $request->user('admin')->isContabilidade();

        return view('admin.submissions.index', compact('submissions', 'isContabilidade'));
    }

    public function show(Request $request, Submission $submission)
    {
        $user = $request->user('admin');

        if ($user->isContabilidade()) {
            return view('admin.submissions.show-contabilidade', compact('submission'));
        }

        // Obter anterior e próximo respeitando filtros
        $query = Submission::latest()->orderByDesc('created_at');
        $this->applyFilters($query, $request);

        $ids = $query->pluck('id')->toArray();
        $currentIndex = array_search($submission->id, $ids);
        $prevId = $currentIndex !== false && $currentIndex > 0 ? $ids[$currentIndex - 1] : null;
        $nextId = $currentIndex !== false && $currentIndex < count($ids) - 1 ? $ids[$currentIndex + 1] : null;

        // Historico do mesmo NIF (via hash — campo encriptado)
        $history = Submission::where('nif_hash', $submission->nif_hash)
            ->where('id', '!=', $submission->id)
            ->orderByDesc('created_at')
            ->get();

        // Audit log
        $auditLogs = AuditLog::where('entity_type', 'submission')
            ->where('entity_id', $submission->id)
            ->orderByDesc('created_at')
            ->get();

        // URL assinada do comprovativo
        $signedUrl = SubmissionService::getSignedUrl($submission);

        return view('admin.submissions.show', compact(
            'submission',
            'prevId',
            'nextId',
            'history',
            'auditLogs',
            'signedUrl'
        ));
    }

    public function updateStatus(Request $request, Submission $submission)
    {
        $request->validate([
            'status' => 'required|in:' . implode(',', array_keys(Submission::STATUSES)),
            'reason' => 'required_if:status,rejeitado,bloqueado|nullable|string|max:500',
        ]);

        $oldStatus = $submission->status;
        $newStatus = $request->status;

        $submission->update([
            'status' => $newStatus,
            'rejection_reason' => in_array($newStatus, ['rejeitado', 'bloqueado']) ? $request->reason : $submission->rejection_reason,
        ]);

        AuditLog::log(
            'status_change',
            $request->user('admin')->id,
            'submission',
            $submission->id,
            ['status' => $oldStatus],
            ['status' => $newStatus],
            $request->reason
        );

        return back()->with('success', "Estado alterado para \"{$submission->status_label}\".");
    }

    public function updateMorada(Request $request, Submission $submission)
    {
        $request->validate([
            'morada_corrigida' => 'required|string|max:500',
        ]);

        $old = $submission->morada_corrigida;
        $submission->update(['morada_corrigida' => $request->morada_corrigida]);

        AuditLog::log(
            'morada_edit',
            $request->user('admin')->id,
            'submission',
            $submission->id,
            ['morada_corrigida' => $old],
            ['morada_corrigida' => $request->morada_corrigida]
        );

        return back()->with('success', 'Morada corrigida atualizada.');
    }

    public function exportContabilidade(Request $request)
    {
        $submissions = Submission::latest()->byStatus('aprovado')->get();

        if ($submissions->isEmpty()) {
            return back()->with('warning', 'Não existem submissões aprovadas para exportar.');
        }

        $csv = CsvExportService::exportContabilidade($submissions);
        $filename = 'segunor_contabilidade_' . date('Y-m-d_His') . '.csv';

        AuditLog::log('export_contabilidade', $request->user('admin')->id, null, null, null, [
            'count' => $submissions->count(),
        ]);

        return response($csv)
            ->header('Content-Type', 'text/csv; charset=UTF-8')
            ->header('Content-Disposition', "attachment; filename=\"{$filename}\"");
    }

    public function exportErp(Request $request)
    {
        $submissions = Submission::latest()->byStatus('aprovado')->get();

        if ($submissions->isEmpty()) {
            return back()->with('warning', 'Não existem submissões aprovadas para exportar.');
        }

        $csv = CsvExportService::exportErp($submissions);
        $filename = 'segunor_erp_' . date('Y-m-d_His') . '.csv';

        AuditLog::log('export_erp', $request->user('admin')->id, null, null, null, [
            'count' => $submissions->count(),
        ]);

        return response($csv)
            ->header('Content-Type', 'text/csv; charset=UTF-8')
            ->header('Content-Disposition', "attachment; filename=\"{$filename}\"");
    }

    public function markExportedAsConcluded(Request $request)
    {
        $count = Submission::latest()->byStatus('aprovado')->update(['status' => 'concluido']);

        AuditLog::log('bulk_mark_concluded', $request->user('admin')->id, null, null, null, [
            'count' => $count,
        ]);

        return back()->with('success', "{$count} submissões marcadas como concluídas.");
    }

    public function generatePdf(Request $request, Submission $submission)
    {
        $pdf = \Barryvdh\DomPDF\Facade\Pdf::loadView('admin.submissions.pdf', compact('submission'));
        $pdf->setPaper('a4', 'portrait');

        $filename = 'Ficha_Funcionario_' . str_replace(' ', '_', $submission->nome_completo) . '.pdf';

        AuditLog::log('export_pdf', $request->user('admin')->id, 'submission', $submission->id);

        return $pdf->stream($filename);
    }

    private function applyFilters($query, Request $request): void
    {
        if ($status = $request->get('status'))
            $query->where('status', $status);
        if ($flag = $request->get('flag')) {
            match ($flag) {
                'sem_correspondencia' => $query->where('flag_sem_correspondencia', true),
                'ip_fora_pt' => $query->where('flag_ip_fora_pt', true),
                'inconsistencia' => $query->where('flag_inconsistencia', true),
                'suspeito' => $query->where('flag_suspeito', true),
                default => null,
            };
        }
        if ($search = $request->get('search')) {
            if (preg_match('/^\d{1,9}$/', $search)) {
                $query->where('nif_hash', hash('sha256', $search));
            }
            // Nome: nao e possivel filtrar em SQL com campos encriptados
            // A filtragem por nome e feita em PHP no metodo index()
        }
    }
}
