<?php

namespace App\Http\Controllers\Web;

use App\Http\Controllers\Controller;
use App\Models\GeneratedLetter;
use App\Models\LetterHeadTemplate;
use App\Models\User;
use App\Services\AuditService;
use App\Services\Documents\LetterGeneratorService;
use Illuminate\Http\Request;

class GeneratedLetterController extends Controller
{
    public function __construct(
        protected LetterGeneratorService $generator,
        protected AuditService $audit
    ) {}

    public function index()
    {
        $letters = GeneratedLetter::with(['employee', 'template', 'generatedBy'])
            ->orderByDesc('created_at')
            ->paginate(20);

        return view('generated-letters.index', compact('letters'));
    }

    public function create(Request $request)
    {
        $employees = User::query()->forActiveDirectory()->orderBy('name')->get(['id', 'name']);
        $templates = LetterHeadTemplate::orderBy('name')->get(['id', 'name']);
        $types = $this->generator->supportedTypes();

        $prefill = [
            'user_id' => $request->integer('user_id') ?: null,
            'letter_type' => $request->input('letter_type', GeneratedLetter::TYPE_RELIEVING),
            'letter_head_template_id' => $request->integer('letter_head_template_id') ?: null,
            'last_working_date' => $request->input('last_working_date'),
        ];

        return view('generated-letters.create', compact('employees', 'templates', 'types', 'prefill'));
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'user_id' => 'required|exists:users,id',
            'letter_head_template_id' => 'nullable|exists:letter_head_templates,id',
            'letter_type' => 'required|in:' . implode(',', $this->generator->supportedTypes()),
            'subject' => 'nullable|string|max:191',
            'body_html' => 'nullable|string|max:50000',
            'last_working_date' => 'nullable|date',
        ]);

        $employee = User::findOrFail($validated['user_id']);
        $this->assertTenantUser($employee);

        $template = ! empty($validated['letter_head_template_id'])
            ? LetterHeadTemplate::find($validated['letter_head_template_id'])
            : null;
        if ($template) {
            $this->assertTenantRecord($template);
        }

        $overrides = [];
        if (! empty($validated['last_working_date'])) {
            $overrides['{{last_working_date}}'] = \Carbon\Carbon::parse($validated['last_working_date'])->format('d M Y');
        }

        $variables = $this->generator->variablesForEmployee($employee, auth()->user()?->company, $overrides);
        $bodyHtml = $validated['body_html']
            ?? $this->generator->defaultBody($validated['letter_type'], $variables);
        $subject = $validated['subject']
            ?? $this->generator->defaultSubject($validated['letter_type'], $variables);

        $letter = GeneratedLetter::create([
            'company_id' => auth()->user()->company_id,
            'user_id' => $employee->id,
            'letter_head_template_id' => $template?->id,
            'generated_by_user_id' => auth()->id(),
            'letter_type' => $validated['letter_type'],
            'subject' => $subject,
            'body_html' => $bodyHtml,
        ]);

        $this->audit->log('generated_letter.created', $letter, ['type' => $letter->letter_type]);

        return redirect()->route('generated-letters.show', $letter)
            ->with('success', 'Letter generated successfully.');
    }

    public function show(GeneratedLetter $generatedLetter)
    {
        $this->assertTenantRecord($generatedLetter);
        $generatedLetter->load(['employee', 'template', 'generatedBy']);

        $employee = $generatedLetter->employee;
        $variables = $this->generator->variablesForEmployee($employee, auth()->user()?->company);
        $parts = $this->generator->renderParts(
            $generatedLetter->template,
            $generatedLetter->body_html,
            $variables,
            auth()->user()?->company
        );

        return view('generated-letters.show', [
            'letter' => $generatedLetter,
            'parts' => $parts,
            'company' => auth()->user()?->company,
        ]);
    }

    public function edit(GeneratedLetter $generatedLetter)
    {
        $this->assertTenantRecord($generatedLetter);
        $templates = LetterHeadTemplate::orderBy('name')->get(['id', 'name']);
        $types = $this->generator->supportedTypes();

        return view('generated-letters.edit', compact('generatedLetter', 'templates', 'types'));
    }

    public function update(Request $request, GeneratedLetter $generatedLetter)
    {
        $this->assertTenantRecord($generatedLetter);

        $validated = $request->validate([
            'letter_head_template_id' => 'nullable|exists:letter_head_templates,id',
            'letter_type' => 'required|in:' . implode(',', $this->generator->supportedTypes()),
            'subject' => 'required|string|max:191',
            'body_html' => 'required|string|max:50000',
        ]);

        if (! empty($validated['letter_head_template_id'])) {
            $this->assertTenantRecord(LetterHeadTemplate::findOrFail($validated['letter_head_template_id']));
        }

        $generatedLetter->update($validated);
        $this->audit->log('generated_letter.updated', $generatedLetter);

        return redirect()->route('generated-letters.show', $generatedLetter)->with('success', 'Letter updated.');
    }

    public function downloadPdf(GeneratedLetter $generatedLetter)
    {
        $this->assertTenantRecord($generatedLetter);
        $generatedLetter->load(['employee', 'template']);

        if (! class_exists(\Barryvdh\DomPDF\Facade\Pdf::class)) {
            return redirect()->route('generated-letters.show', $generatedLetter)
                ->with('error', 'PDF download requires barryvdh/laravel-dompdf. Use browser print from preview.');
        }

        $variables = $this->generator->variablesForEmployee(
            $generatedLetter->employee,
            auth()->user()?->company
        );
        $parts = $this->generator->renderParts(
            $generatedLetter->template,
            $generatedLetter->body_html,
            $variables,
            auth()->user()?->company
        );

        $pdf = \Barryvdh\DomPDF\Facade\Pdf::loadView('generated-letters.preview-pdf', [
            'letter' => $generatedLetter,
            'parts' => $parts,
            'company' => auth()->user()?->company,
        ]);

        $this->audit->log('generated_letter.pdf', $generatedLetter);

        $slug = str($generatedLetter->employee?->name ?? 'letter')->slug();

        return $pdf->download('letter-' . $slug . '-' . $generatedLetter->id . '.pdf');
    }

    protected function assertTenantRecord(GeneratedLetter|LetterHeadTemplate $record): void
    {
        $companyId = auth()->user()?->company_id;
        if ($companyId && (int) $record->company_id !== (int) $companyId) {
            abort(403);
        }
    }

    protected function assertTenantUser(User $user): void
    {
        $companyId = auth()->user()?->company_id;
        if ($companyId && (int) $user->company_id !== (int) $companyId) {
            abort(403);
        }
    }
}
