<?php

namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Models\AttendanceImport;
use App\Services\AttendanceImportService;
use App\Support\AfterResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\StreamedResponse;

class AttendanceImportController extends Controller
{
    public function __construct(private readonly AttendanceImportService $attendanceImportService) {}

    public function index()
    {
        $actor = Auth::user();
        abort_unless($actor && $this->canManageAttendance($actor), 403);

        $companyId = $actor->company_id;
        $imports = AttendanceImport::query()
            ->when($companyId, fn ($query) => $query->where('company_id', $companyId))
            ->with('creator')
            ->withCount('rows')
            ->latest()
            ->paginate(10);

        return view('attendance.import', compact('imports'));
    }

    public function downloadTemplate(): StreamedResponse
    {
        $actor = Auth::user();
        abort_unless($actor && $this->canManageAttendance($actor), 403);

        $headers = $this->attendanceImportService->templateHeaders();
        $sampleRow = $this->attendanceImportService->templateSampleRow();

        return response()->streamDownload(function () use ($headers, $sampleRow) {
            $handle = fopen('php://output', 'w');
            fputcsv($handle, $headers);
            fputcsv($handle, $sampleRow);
            fclose($handle);
        }, 'attendance-import-template.csv', ['Content-Type' => 'text/csv']);
    }

    public function store(Request $request)
    {
        $actor = Auth::user();
        abort_unless($actor && $this->canManageAttendance($actor), 403);

        $validated = $request->validate([
            'file' => 'required|file|mimes:csv,txt|max:5120',
        ]);

        $import = $this->attendanceImportService->createAndValidatePreview($validated['file'], $actor);

        return redirect()
            ->route('attendance.import.preview', $import)
            ->with('success', 'File validated. Review the preview before confirming import.');
    }

    public function preview(AttendanceImport $import)
    {
        $actor = Auth::user();
        abort_unless($actor, 403);
        $this->assertCompanyImport($import, $actor);
        abort_unless($this->canManageAttendance($actor), 403);

        if ($import->status !== AttendanceImport::STATUS_PREVIEW) {
            return redirect()->route('attendance.import.show', $import);
        }

        $import->load(['rows' => fn ($query) => $query->orderBy('row_number')]);

        return view('attendance.import-preview', compact('import'));
    }

    public function confirm(AttendanceImport $import)
    {
        $actor = Auth::user();
        abort_unless($actor, 403);
        $this->assertCompanyImport($import, $actor);
        abort_unless($this->canManageAttendance($actor), 403);

        if ($import->status !== AttendanceImport::STATUS_PREVIEW) {
            return redirect()
                ->route('attendance.import.show', $import)
                ->with('error', 'This import is no longer awaiting confirmation.');
        }

        if ((int) $import->valid_rows === 0) {
            return redirect()
                ->route('attendance.import.preview', $import)
                ->with('error', 'There are no valid rows to import.');
        }

        if ($import->mode === 'queued') {
            AfterResponse::run(fn () => $this->attendanceImportService->processDeferred($import->id));

            return redirect()
                ->route('attendance.import.show', $import)
                ->with('success', 'Import accepted. It will be processed right after this response.');
        }

        $this->attendanceImportService->confirm($import);

        return redirect()
            ->route('attendance.import.show', $import)
            ->with('success', 'Attendance import completed.');
    }

    public function cancel(AttendanceImport $import)
    {
        $actor = Auth::user();
        abort_unless($actor, 403);
        $this->assertCompanyImport($import, $actor);
        abort_unless($this->canManageAttendance($actor), 403);

        $this->attendanceImportService->cancel($import);

        return redirect()
            ->route('attendance.import.index')
            ->with('success', 'Import cancelled.');
    }

    public function show(AttendanceImport $import)
    {
        $actor = Auth::user();
        abort_unless($actor, 403);
        $this->assertCompanyImport($import, $actor);
        abort_unless($this->canManageAttendance($actor), 403);

        $import->load(['rows' => fn ($query) => $query->orderBy('row_number'), 'creator']);

        return view('attendance.import-show', compact('import'));
    }

    public function downloadErrors(AttendanceImport $import): StreamedResponse
    {
        $actor = Auth::user();
        abort_unless($actor, 403);
        $this->assertCompanyImport($import, $actor);
        abort_unless($this->canManageAttendance($actor), 403);

        $lines = $this->attendanceImportService->errorReportRows($import);

        return response()->streamDownload(function () use ($lines) {
            $handle = fopen('php://output', 'w');
            foreach ($lines as $line) {
                fputcsv($handle, $line);
            }
            fclose($handle);
        }, 'attendance-import-'.$import->id.'-errors.csv', ['Content-Type' => 'text/csv']);
    }

    private function assertCompanyImport(AttendanceImport $import, $actor): void
    {
        $companyId = $actor?->company_id;
        if ($companyId && (int) $import->company_id !== (int) $companyId) {
            abort(404);
        }
    }

    private function canManageAttendance($authUser): bool
    {
        if (! $authUser || ! $authUser->company_id) {
            return false;
        }
        $roleName = $authUser->role?->name ?? '';

        return $authUser->isTenantAdmin() || $roleName === 'manager';
    }
}
