<?php

namespace App\Http\Controllers\Tenant;

use App\Http\Controllers\Controller;
use App\Http\Requests\Renewals\CreateRenewalApplicationRequest;
use App\Http\Requests\Renewals\RenewalFollowUpRequest;
use App\Http\Requests\Renewals\RenewalTransitionRequest;
use App\Models\RenewalOpportunity;
use App\Models\RenewalReminderLog;
use App\Models\Service;
use App\Models\User;
use App\Services\RenewalService;
use Illuminate\Http\Request;

class RenewalCenterController extends Controller
{
    public function __construct(private readonly RenewalService $renewals) {}

    public function index(Request $request)
    {
        $tenantId = $request->user()->tenant_id;
        $base = RenewalOpportunity::query()->where('tenant_id', $tenantId);
        $metrics = [
            'expired' => (clone $base)->whereDate('expiry_date', '<', today())->whereNotIn('status', ['completed', 'lost'])->count(),
            'today' => (clone $base)->whereDate('expiry_date', today())->whereNotIn('status', ['completed', 'lost'])->count(),
            'seven_days' => (clone $base)->whereBetween('expiry_date', [today(), today()->addDays(7)])->whereNotIn('status', ['completed', 'lost'])->count(),
            'thirty_days' => (clone $base)->whereBetween('expiry_date', [today(), today()->addDays(30)])->whereNotIn('status', ['completed', 'lost'])->count(),
            'in_progress' => (clone $base)->whereIn('status', ['contacted', 'interested', 'application_created'])->count(),
            'scheduled_reminders' => RenewalReminderLog::query()->where('tenant_id', $tenantId)->where('status', 'scheduled')->count(),
        ];

        $opportunities = RenewalOpportunity::query()
            ->where('tenant_id', $tenantId)
            ->with(['customer.contact', 'company', 'corporateEmployee', 'employee', 'assignedUser', 'reminderLogs'])
            ->when($request->query('status'), fn ($query, $status) => $query->where('status', $status))
            ->when($request->query('entity_type'), fn ($query, $type) => $query->where('entity_type', $type))
            ->when($request->query('document_status'), fn ($query, $status) => $query->where('document_status', $status))
            ->when($request->boolean('reminder_due'), fn ($query) => $query->where('reminder_enabled', true)->whereNotNull('next_reminder_at'))
            ->when($request->query('window'), function ($query, $window) {
                if ($window === 'expired') {
                    $query->whereDate('expiry_date', '<', today());
                } elseif (in_array((int) $window, [7, 30, 60, 90], true)) {
                    $query->whereBetween('expiry_date', [today(), today()->addDays((int) $window)]);
                }
            })
            ->when($request->query('q'), function ($query, $search) {
                $query->where(function ($builder) use ($search) {
                    $builder->where('renewal_number', 'like', "%{$search}%")
                        ->orWhere('document_number', 'like', "%{$search}%")
                        ->orWhereHas('customer', fn ($customer) => $customer->where('full_name_en', 'like', "%{$search}%"))
                        ->orWhereHas('company', fn ($company) => $company->where('name_en', 'like', "%{$search}%"));
                });
            })
            ->orderBy('expiry_date')
            ->paginate(25)
            ->withQueryString();

        $reminderCount = RenewalReminderLog::query()->where('tenant_id', $tenantId)->count();

        return view('tenant.renewals.dashboard', compact('metrics', 'opportunities', 'reminderCount'));
    }

    public function show(Request $request, int $id)
    {
        $tenantId = $request->user()->tenant_id;
        $opportunity = RenewalOpportunity::query()
            ->where('tenant_id', $tenantId)
            ->with([
                'customer.contact',
                'company',
                'corporateEmployee',
                'employee',
                'assignedUser',
                'statusHistory.changedByUser',
                'reminderLogs.creator',
                'application.attendedBy',
                'application.typedByUser',
            ])
            ->findOrFail($id);
        $services = Service::where('tenant_id', $tenantId)->where('status', 'active')->orderBy('name_en')->get();
        $users = User::where('tenant_id', $tenantId)->where('status', 'active')->orderBy('name')->get();
        $allowedStatuses = $this->renewals->allowedTransitions($opportunity->status);

        return view('tenant.renewals.show', compact('opportunity', 'services', 'users', 'allowedStatuses'));
    }

    public function scan(Request $request)
    {
        $created = $this->renewals->scanTenant($request->user()->tenant);
        $reminders = $this->renewals->dispatchDueReminders($request->user()->tenant);

        return back()->with('status', "Expiry scan completed: {$created} new opportunities and {$reminders} due reminders.");
    }

    public function transition(RenewalTransitionRequest $request, int $id)
    {
        $opportunity = RenewalOpportunity::query()
            ->where('tenant_id', $request->user()->tenant_id)
            ->findOrFail($id);
        $this->renewals->transition(
            $request->user()->tenant,
            $opportunity,
            $request->validated('status'),
            $request->user(),
            $request->validated('notes'),
            $request->safe()->only(['assigned_user_id', 'next_followup_at', 'lost_reason'])
        );

        return back()->with('status', 'Renewal pipeline updated.');
    }

    public function followUp(RenewalFollowUpRequest $request, int $id)
    {
        $opportunity = RenewalOpportunity::query()
            ->where('tenant_id', $request->user()->tenant_id)
            ->findOrFail($id);
        $this->renewals->recordFollowUp(
            $request->user()->tenant,
            $opportunity,
            $request->user(),
            $request->validated('activity_type'),
            $request->validated('notes'),
            $request->validated('next_followup_at')
        );

        return back()->with('status', 'Follow-up recorded with a complete activity trail.');
    }

    public function createApplication(CreateRenewalApplicationRequest $request, int $id)
    {
        $opportunity = RenewalOpportunity::query()
            ->where('tenant_id', $request->user()->tenant_id)
            ->findOrFail($id);
        $service = Service::where('tenant_id', $request->user()->tenant_id)->findOrFail($request->integer('service_id'));
        $application = $this->renewals->createApplicationFromRenewal(
            $request->user()->tenant,
            $opportunity,
            $service,
            $request->user()
        );

        return redirect()->route('app.applications.show', $application->id)
            ->with('status', "Application {$application->application_number} created from the renewal cycle.");
    }

    public function updateDocumentStatus(Request $request, int $id)
    {
        abort_unless($request->user()->hasPermission('renewals.manage'), 403);
        $validated = $request->validate([
            'document_status' => 'required|in:active,expiring,expired,renewal_in_progress,renewed,on_hold,cancelled',
            'document_number' => 'nullable|string|max:120',
            'expiry_date' => 'nullable|date',
            'reminder_enabled' => 'nullable|boolean',
        ]);
        $opportunity = RenewalOpportunity::query()
            ->where('tenant_id', $request->user()->tenant_id)
            ->findOrFail($id);
        $this->renewals->updateDocumentStatus(
            $request->user()->tenant,
            $opportunity,
            $request->user(),
            $validated + ['reminder_enabled' => $request->boolean('reminder_enabled')]
        );

        return back()->with('status', 'Renewal document status updated with an audit record.');
    }

    public function scheduleReminder(Request $request, int $id)
    {
        abort_unless($request->user()->hasPermission('renewals.manage'), 403);
        $validated = $request->validate([
            'channel' => 'required|in:in_app,whatsapp,sms,email',
            'scheduled_at' => 'required|date|after_or_equal:today',
            'notes' => 'nullable|string|max:1000',
        ]);
        $opportunity = RenewalOpportunity::query()
            ->where('tenant_id', $request->user()->tenant_id)
            ->findOrFail($id);
        $this->renewals->scheduleReminder(
            $request->user()->tenant,
            $opportunity,
            $request->user(),
            $validated['channel'],
            $validated['scheduled_at'],
            $validated['notes'] ?? null
        );

        return back()->with('status', 'Renewal reminder scheduled successfully.');
    }

    public function complete(Request $request, int $id)
    {
        abort_unless($request->user()->hasPermission('renewals.manage'), 403);
        $opportunity = RenewalOpportunity::query()
            ->where('tenant_id', $request->user()->tenant_id)
            ->findOrFail($id);
        $this->renewals->complete($request->user()->tenant, $opportunity, $request->user());

        return back()->with('status', 'Renewal cycle completed. The next document version can now start a new expiry cycle.');
    }
}
