<?php
declare(strict_types=1);

namespace App\Controllers;

use App\Core\Auth;
use App\Core\Request;
use App\Core\Validator;
use App\Models\AuditLog;
use App\Models\Lead;
use App\Models\Task;
use App\Models\Territory;
use App\Models\User;
use App\Services\AutomationService;
use App\Services\IndustryService;
use App\Services\RecordService;

final class LeadController extends BaseController
{
    public function index(Request $request): void
    {
        $this->requireModule('leads');
        $status = (string) ($_GET['status'] ?? 'new');
        if (!in_array($status, ['all', 'new', 'qualified', 'unqualified', 'converted'], true)) {
            $status = 'new';
        }
        $sources = Lead::sources();
        $source = trim((string) ($_GET['source'] ?? ''));
        if ($source !== '' && !in_array($source, $sources, true)) {
            $source = '';
        }
        $territories = Territory::allForTenant();
        $territoryId = (int) ($_GET['territory'] ?? 0);
        $territoryIds = array_map(static fn(array $t): int => (int) $t['id'], $territories);
        if ($territoryId > 0 && !in_array($territoryId, $territoryIds, true)) {
            $territoryId = 0;
        }
        $created = (string) ($_GET['created'] ?? 'all');
        if (!in_array($created, ['all', 'today', 'week', 'month', 'last_week', 'last_month'], true)) {
            $created = 'all';
        }
        $page = $this->page();
        $scope = $this->ownerScope();
        $assigned = (int) ($_GET['assigned'] ?? 0);
        $unassignedOnly = null;
        $ownerFilter = $scope;
        if ($scope === null) {
            if ($assigned === -1) {
                $unassignedOnly = 1;
                $ownerFilter = null;
            } elseif ($assigned > 0) {
                $ownerFilter = $assigned;
            }
        }
        $result = Lead::paginate($this->q(), $status, $page, 15, $unassignedOnly, $ownerFilter, $source, $territoryId, $created);
        view('leads/index', [
            'title' => noun('leads', 'Leads'),
            'rows' => $result['rows'],
            'total' => $result['total'],
            'page' => $page,
            'pages' => max(1, (int) ceil($result['total'] / 15)),
            'q' => $this->q(),
            'status' => $status,
            'source' => $source,
            'sources' => $sources,
            'created' => $created,
            'territoryId' => $territoryId,
            'assigned' => $assigned,
            'showAssigned' => $scope === null,
            'counts' => Lead::boardCounts($ownerFilter, $source),
            'territories' => $territories,
            'owners' => User::salespeople(Auth::instance()->tenantId()),
            'notifications' => $this->notifications(),
        ]);
    }

    public function show(Request $request): void
    {
        $this->requireModule('leads');
        $id = (int) $request->param('id');
        $lead = Lead::detail($id);
        if (!$lead) {
            flash('error', 'Lead not found.');
            redirect('leads');
        }
        $timeline = \App\Models\Activity::timeline('lead', $id);
        view('leads/show', [
            'title' => trim($lead['first_name'] . ' ' . $lead['last_name']),
            'lead' => $lead,
            'timeline' => $timeline,
            'statusHistory' => Lead::statusHistory($lead, $timeline),
            'tasks' => Task::forRelated('lead', $id),
            'owners' => User::salespeople(Auth::instance()->tenantId()),
            'notifications' => $this->notifications(),
        ]);
    }

    public function store(Request $request): void
    {
        $this->requireModule('leads');
        $this->verifyCsrf($request);
        $data = $request->all();
        $v = (new Validator())->required($data, ['first_name' => 'First name']);
        if (trim((string) ($data['email'] ?? '')) === '' && trim((string) ($data['phone'] ?? '')) === '') {
            $v->add('email', 'Enter an email or a phone number.');
        }
        if (($data['email'] ?? '') !== '') {
            $v->email($data, 'email', 'Email');
        }
        if ($v->fails()) {
            $this->fail($v);
        }
        $id = Lead::create([
            'first_name' => $data['first_name'],
            'last_name' => $data['last_name'] ?? '',
            'company' => $data['company'] ?? null,
            'email' => $data['email'] ?? null,
            'phone' => $data['phone'] ?? null,
            'source' => $data['source'] ?? null,
            'status' => 'new',
            'owner_id' => Auth::instance()->id(),
            'territory_id' => !empty($data['territory_id']) ? (int) $data['territory_id'] : null,
            'attrs' => json_encode(IndustryService::sanitizeAttrs($data['attrs'] ?? [], entity_fields('lead')), JSON_UNESCAPED_UNICODE),
        ]);
        RecordService::logActivity('note', 'Lead created', null, 'lead', $id);
        AuditLog::write('lead.create', 'lead', $id);
        AutomationService::run('lead_created', [
            'owner_id' => (int) Auth::instance()->id(),
            'related_type' => 'lead',
            'related_id' => $id,
            'title' => trim(($data['first_name'] ?? '') . ' ' . ($data['last_name'] ?? '')),
        ]);
        json_out(['ok' => true, 'id' => $id, 'redirect' => url('leads/' . $id)]);
    }

    public function qualify(Request $request): void
    {
        $this->requireModule('leads');
        $this->verifyCsrf($request);
        $id = (int) $request->param('id');
        $lead = Lead::find($id);
        if (!$lead) {
            json_out(['ok' => false, 'error' => 'Not found.'], 404);
        }
        $status = $request->input('status');
        if (!in_array($status, ['qualified', 'unqualified'], true)) {
            json_out(['ok' => false, 'error' => 'Pick qualified or not qualified.'], 422);
        }
        $from = (string) ($lead['status'] ?? 'new');
        if ($from === 'converted') {
            json_out(['ok' => false, 'error' => 'Already converted.'], 422);
        }
        if ($from !== $status) {
            Lead::update($id, ['status' => $status]);
            RecordService::logLeadStatus($id, $from, $status, $request->input('notes'));
            AuditLog::write('lead.qualify', 'lead', $id, ['status' => $status]);
        }
        json_out(['ok' => true]);
    }

    public function convert(Request $request): void
    {
        $this->requireModule('leads');
        $this->verifyCsrf($request);
        $id = (int) $request->param('id');
        $result = RecordService::convertLead(
            $id,
            (bool) $request->input('create_deal', '1'),
            (float) $request->input('amount', 0)
        );
        if (empty($result['ok'])) {
            json_out($result, 422);
        }
        json_out(['ok' => true, 'redirect' => url('accounts/' . $result['account_id'])]);
    }
}
