<?php

namespace App\Http\Controllers;

use App\Models\EmailMessage;
use App\Models\EmailTemplate;
use App\Models\Mentorship\Assignment as MentorshipAssignment;
use App\Models\TrainingRegistration;
use App\Models\User;
use App\Services\EmailCommunicationService;
use App\Http\Requests\EmailRequest;
use Illuminate\Http\Request;

class EmailController extends Controller
{
    public function __construct(
        protected EmailCommunicationService $emailService
    ) {}

    /**
     * Display email dashboard.
     */
    public function index(Request $request)
    {
        abort_unless(auth()->user()->can('view emails'), 403);

        $filters = $request->only(['status', 'search', 'date_from', 'date_to', 'sort_by', 'sort_order', 'per_page']);
        $messages = $this->emailService->getHistory(auth()->id(), $filters);
        $statistics = $this->emailService->getStatistics();
        $templates = $this->emailService->getTemplates();

        return view('emails.index', compact('messages', 'statistics', 'templates'));
    }

    /**
     * Show compose form.
     */
    public function create()
    {
        abort_unless(auth()->user()->can('create emails'), 403);

        $templates = $this->emailService->getTemplates();
        $availableRoles = $this->emailService->getAvailableRecipientRoles(auth()->user());

        return view('emails.compose', compact('templates', 'availableRoles'));
    }

    /**
     * Send email.
     */
    public function store(EmailRequest $request)
    {
        abort_unless(auth()->user()->can('create emails'), 403);

        // Server-side recipient validation based on sender role
        $user = auth()->user();
        $recipientIds = $request->input('to_recipients', []);

        if (!$user->hasAnyRole(['Super Manager', 'Manager']) && is_array($recipientIds) && count($recipientIds) > 0) {
            if ($user->hasRole('Trainers')) {
                // Trainers can only email trainees registered in sessions they train
                $allowedIds = TrainingRegistration::whereHas('session.trainers', function ($q) use ($user) {
                    $q->where('trainer_id', $user->id);
                })->pluck('user_id')->toArray();
                $invalid = array_diff($recipientIds, $allowedIds);
                if (!empty($invalid)) {
                    return back()->withInput()
                        ->with('error', 'You can only send emails to your registered trainees.');
                }
            } elseif ($user->hasRole('Mentor')) {
                // Mentors can only email their assigned mentees
                $allowedIds = MentorshipAssignment::where('mentor_id', $user->id)
                    ->pluck('mentee_id')
                    ->toArray();
                $invalid = array_diff($recipientIds, $allowedIds);
                if (!empty($invalid)) {
                    return back()->withInput()
                        ->with('error', 'You can only send emails to your assigned mentees.');
                }
            }
        }

        try {
            $message = $this->emailService->sendEmail(
                auth()->id(),
                $request->input('to_recipients'),
                $request->input('subject'),
                $request->input('html_body'),
                $request->only(['cc_recipients', 'bcc_recipients', 'template_id', 'scheduled_at', 'priority', 'recipient_type', 'target_role', 'text_body'])
            );

            return redirect()
                ->route('emails.show', $message)
                ->with('success', 'Email sent successfully!');
        } catch (\Exception $e) {
            return back()
                ->withInput()
                ->with('error', 'Failed to send email: ' . $e->getMessage());
        }
    }

    /**
     * Show email details.
     */
    public function show(EmailMessage $email)
    {
        abort_unless(auth()->user()->can('view emails'), 403);
        abort_unless($this->canViewMessage($email), 403);

        $email->load(['sender', 'template', 'replies']);

        return view('emails.show', compact('email'));
    }

    /**
     * Show email history.
     */
    public function history(Request $request)
    {
        abort_unless(auth()->user()->can('view emails'), 403);

        $filters = $request->only(['status', 'search', 'date_from', 'date_to', 'sort_by', 'sort_order', 'per_page']);
        $messages = $this->emailService->getHistory(auth()->id(), $filters);

        return view('emails.history', compact('messages'));
    }

    /**
     * Show reply form.
     */
    public function reply(EmailMessage $email)
    {
        abort_unless(auth()->user()->can('reply emails'), 403);
        abort_unless(auth()->user()->hasAnyRole(['Super Manager', 'Manager']), 403);

        $email->load(['sender', 'template']);

        return view('emails.reply', compact('email'));
    }

    /**
     * Send reply.
     */
    public function sendReply(Request $request, EmailMessage $email)
    {
        abort_unless(auth()->user()->can('reply emails'), 403);

        $validated = $request->validate([
            'message' => 'required|string|max:50000',
            'reply_all' => 'nullable|boolean',
        ]);

        try {
            $reply = $this->emailService->replyToEmail(
                $email->id,
                auth()->id(),
                $validated['message'],
                $validated['reply_all'] ?? false
            );

            return redirect()
                ->route('emails.show', $reply)
                ->with('success', 'Reply sent successfully!');
        } catch (\Exception $e) {
            return back()
                ->withInput()
                ->with('error', 'Failed to send reply: ' . $e->getMessage());
        }
    }

    /**
     * Delete email.
     */
    public function destroy(EmailMessage $email)
    {
        abort_unless(auth()->user()->can('delete emails'), 403);

        try {
            $this->emailService->deleteMessage($email->id, auth()->id());
            return redirect()
                ->route('emails.index')
                ->with('success', 'Email deleted successfully!');
        } catch (\Exception $e) {
            return back()->with('error', $e->getMessage());
        }
    }

    /**
     * Display templates.
     */
    public function templates()
    {
        abort_unless(auth()->user()->can('manage email templates'), 403);

        $templates = EmailTemplate::with('creator')->latest()->paginate(15);

        return view('emails.templates', compact('templates'));
    }

    /**
     * Create template.
     */
    public function createTemplate()
    {
        abort_unless(auth()->user()->can('manage email templates'), 403);

        return view('emails.template-form');
    }

    /**
     * Store template.
     */
    public function storeTemplate(Request $request)
    {
        abort_unless(auth()->user()->can('manage email templates'), 403);

        $validated = $request->validate([
            'name' => 'required|string|max:191',
            'subject' => 'required|string|max:191',
            'preheader' => 'nullable|string|max:255',
            'html_content' => 'required|string',
            'text_content' => 'nullable|string',
            'description' => 'nullable|string',
        ]);

        $this->emailService->saveTemplate($validated, auth()->id());

        return redirect()
            ->route('emails.templates')
            ->with('success', 'Template created successfully!');
    }

    /**
     * Edit template.
     */
    public function editTemplate(EmailTemplate $template)
    {
        abort_unless(auth()->user()->can('manage email templates'), 403);
        abort_unless($template->canBeDeleted(), 403, 'System templates cannot be edited.');

        return view('emails.template-form', compact('template'));
    }

    /**
     * Update template.
     */
    public function updateTemplate(Request $request, EmailTemplate $template)
    {
        abort_unless(auth()->user()->can('manage email templates'), 403);

        $validated = $request->validate([
            'name' => 'required|string|max:191',
            'subject' => 'required|string|max:191',
            'preheader' => 'nullable|string|max:255',
            'html_content' => 'required|string',
            'text_content' => 'nullable|string',
            'description' => 'nullable|string',
        ]);

        $this->emailService->saveTemplate($validated, auth()->id(), $template->id);

        return redirect()
            ->route('emails.templates')
            ->with('success', 'Template updated successfully!');
    }

    /**
     * Delete template.
     */
    public function destroyTemplate(EmailTemplate $template)
    {
        abort_unless(auth()->user()->can('manage email templates'), 403);

        try {
            $this->emailService->deleteTemplate($template->id, auth()->id());
            return redirect()
                ->route('emails.templates')
                ->with('success', 'Template deleted successfully!');
        } catch (\Exception $e) {
            return back()->with('error', $e->getMessage());
        }
    }

    /**
     * Get users by role (AJAX).
     */
    public function getUsersByRole(string $role)
    {
        abort_unless(auth()->user()->can('create emails'), 403);

        $users = User::role($role)
            ->whereNotNull('email')
            ->select(['id', 'name', 'email'])
            ->get();

        return response()->json($users);
    }

    /**
     * Check if user can view message.
     */
    protected function canViewMessage(EmailMessage $message): bool
    {
        $user = auth()->user();

        if ($user->hasAnyRole(['Super Manager', 'Manager'])) {
            return true;
        }

        return $message->sender_id === $user->id;
    }
}
