<?php

namespace App\Http\Controllers\SuperAdmin;

use App\Events\CompanyCreated;
use App\Http\Controllers\Controller;
use App\Models\Company;
use App\Models\Lead;
use App\Models\LeadFollowup;
use App\Models\Role;
use App\Models\User;
use App\Services\LeadActivityService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

class LeadController extends Controller
{
    public function index(Request $request)
    {
        $query = Lead::query()->latest();

        if ($request->filled('status')) {
            $query->where('status', $request->string('status'));
        }
        if ($request->filled('search')) {
            $search = '%' . $request->string('search') . '%';
            $query->where(function ($q) use ($search) {
                $q->where('company_name', 'like', $search)
                    ->orWhere('contact_person_name', 'like', $search)
                    ->orWhere('mobile', 'like', $search)
                    ->orWhere('email', 'like', $search);
            });
        }

        $leads = $query->paginate(20)->withQueryString();
        $pendingCount = Lead::whereIn('status', ['new', 'contacted', 'qualified', 'meeting_scheduled'])->count();

        return view('superadmin.leads.index', compact('leads', 'pendingCount'));
    }

    public function show(Lead $lead)
    {
        $lead->load(['activities.performer', 'followups' => fn ($query) => $query->latest()]);
        return view('superadmin.leads.show', compact('lead'));
    }

    public function updateStatus(Request $request, Lead $lead, LeadActivityService $activityService)
    {
        $data = $request->validate([
            'status' => ['required', 'in:new,contacted,qualified,meeting_scheduled,converted,rejected'],
            'notes' => ['nullable', 'string', 'max:1000'],
        ]);

        $lead->update([
            'status' => $data['status'],
            'notes' => $data['notes'] ?? $lead->notes,
        ]);

        $activityService->log($lead, 'status_changed', 'Lead status updated', [
            'status' => $data['status'],
        ], Auth::id());

        return back()->with('success', 'Lead status updated.');
    }

    public function storeFollowup(Request $request, Lead $lead, LeadActivityService $activityService)
    {
        $data = $request->validate([
            'followup_at' => ['required', 'date'],
            'channel' => ['required', 'in:call,whatsapp,sms,email,meeting'],
            'notes' => ['nullable', 'string', 'max:1000'],
            'message' => ['nullable', 'string', 'max:1000'],
        ]);

        $followup = LeadFollowup::create([
            'lead_id' => $lead->id,
            'followup_at' => $data['followup_at'],
            'channel' => $data['channel'],
            'status' => 'pending',
            'notes' => $data['notes'] ?? null,
            'message' => $data['message'] ?? null,
            'created_by' => Auth::id(),
        ]);

        $lead->update(['next_followup_at' => $followup->followup_at]);

        $activityService->log($lead, 'followup_created', 'Follow-up added by super admin', [
            'followup_id' => $followup->id,
            'channel' => $followup->channel,
        ], Auth::id());

        return back()->with('success', 'Follow-up scheduled.');
    }

    public function completeFollowup(Request $request, Lead $lead, LeadFollowup $followup, LeadActivityService $activityService)
    {
        abort_if($followup->lead_id !== $lead->id, 404);

        $data = $request->validate([
            'outcome' => ['required', 'string', 'max:50'],
            'notes' => ['nullable', 'string', 'max:1000'],
        ]);

        $followup->update([
            'status' => 'completed',
            'outcome' => $data['outcome'],
            'notes' => $data['notes'] ?? $followup->notes,
            'completed_at' => now(),
        ]);

        $lead->update(['last_contacted_at' => now()]);

        $activityService->log($lead, 'followup_completed', 'Follow-up marked completed', [
            'followup_id' => $followup->id,
            'outcome' => $followup->outcome,
        ], Auth::id());

        return back()->with('success', 'Follow-up marked as completed.');
    }

    public function scheduleMeeting(Request $request, Lead $lead, LeadActivityService $activityService)
    {
        $data = $request->validate([
            'meeting_at' => ['required', 'date'],
            'meeting_mode' => ['required', 'in:online,offline,phone'],
            'notes' => ['nullable', 'string', 'max:1000'],
        ]);

        $lead->update([
            'meeting_at' => $data['meeting_at'],
            'meeting_mode' => $data['meeting_mode'],
            'status' => 'meeting_scheduled',
            'notes' => $data['notes'] ?? $lead->notes,
        ]);

        $activityService->log($lead, 'meeting_scheduled', 'Meeting scheduled', [
            'meeting_at' => $lead->meeting_at?->toDateTimeString(),
            'meeting_mode' => $lead->meeting_mode,
        ], Auth::id());

        return back()->with('success', 'Meeting scheduled successfully.');
    }

    public function convertToCompany(Lead $lead, LeadActivityService $activityService)
    {
        if ($lead->status === 'converted') {
            return back()->with('success', 'Lead is already converted.');
        }

        $company = null;
        $adminUser = null;

        DB::transaction(function () use ($lead, $activityService, &$company, &$adminUser): void {
            $company = Company::create([
                'name' => $lead->company_name,
                'short_name' => $this->makeShortName($lead->company_name),
                'email' => $lead->email,
                'phone' => $lead->mobile,
                'status' => 'active',
                'total_users' => max((int) $lead->employee_count, 1),
                'admin_id' => null,
                'trial_ends_at' => now()->addDays(15),
            ]);

            $adminRole = $this->bootstrapTenantRolesAndGetAdminRole((int) $company->id);
            $adminUser = $this->createLeadAdminUser($lead, (int) $company->id, (int) $adminRole->id);

            $company->update(['admin_id' => $adminUser->id]);

            $lead->update([
                'status' => 'converted',
                'notes' => trim(($lead->notes ? $lead->notes . PHP_EOL : '') . 'Converted to company #' . $company->id . ' with admin user #' . $adminUser->id . ' on ' . now()->format('Y-m-d H:i:s')),
            ]);

            $activityService->log($lead, 'converted', 'Lead converted to company', [
                'company_id' => $company->id,
                'company_name' => $company->name,
                'admin_user_id' => $adminUser->id,
                'admin_email' => $adminUser->email,
            ], Auth::id());

            DB::afterCommit(function () use ($company): void {
                CompanyCreated::dispatch($company->fresh());
            });
        });

        if (! $company || ! $adminUser) {
            return back()->with('error', 'Unable to convert lead right now. Please try again.');
        }

        return redirect()
            ->route('superadmin.companies.edit', $company)
            ->with('success', 'Lead converted successfully. Company admin created: ' . $adminUser->email . ' (temporary password: Welcome@123).');
    }

    private function makeShortName(string $name): string
    {
        $parts = preg_split('/\s+/', trim($name)) ?: [];
        if (count($parts) === 0) {
            return 'COMP';
        }

        if (count($parts) === 1) {
            return strtoupper(substr($parts[0], 0, 6));
        }

        $initials = '';
        foreach (array_slice($parts, 0, 4) as $part) {
            $initials .= strtoupper(substr($part, 0, 1));
        }

        return $initials ?: 'COMP';
    }

    private function bootstrapTenantRolesAndGetAdminRole(int $companyId): Role
    {
        $roles = \App\Services\TenantRoleService::syncAllDefaultRolesForCompany($companyId, false);

        return $roles['admin'];
    }

    private function createLeadAdminUser(Lead $lead, int $companyId, int $roleId): User
    {
        $baseEmail = $lead->email ?: ('admin+' . $lead->id . '@example.local');
        $email = $baseEmail;
        $suffix = 1;
        while (User::where('email', $email)->exists()) {
            $email = Str::before($baseEmail, '@') . '+' . $suffix . '@' . Str::after($baseEmail, '@');
            $suffix++;
        }

        return User::create([
            'company_id' => $companyId,
            'role_id' => $roleId,
            'is_superadmin' => false,
            'user_type' => User::USER_TYPE_ADMIN,
            'login_enabled' => true,
            'allow_login' => true,
            'status' => 'active',
            'name' => $lead->contact_person_name ?: ($lead->company_name . ' Admin'),
            'email' => $email,
            'phone' => $lead->mobile,
            'password' => Hash::make('Welcome@123'),
        ]);
    }
}
