<?php

namespace Modules\Sale\Services;

use App\Models\ActivityLogModel;
use App\Models\LeadModel;

class LeadService
{
    protected LeadModel $leads;
    protected LeadScoringService $scoring;
    protected LeadAssignmentService $assignment;
    protected ActivityLogModel $activity;

    public function __construct()
    {
        $this->leads      = new LeadModel();
        $this->scoring    = new LeadScoringService();
        $this->assignment = new LeadAssignmentService();
        $this->activity   = new ActivityLogModel();
    }

    public function create(array $input, ?int $actingUserId): array
    {
        $data = $this->mapInput($input, $actingUserId);
        $data['created_by'] = $actingUserId;
        $data['updated_by'] = $actingUserId;

        if (empty($data['assigned_to'])) {
            $data['assigned_to'] = $this->assignment->resolveAssignee($data['lead_source_id']);
        }

        $data['score'] = $this->scoring->calculateScore($data);

        if (! $this->leads->insert($data, true)) {
            return ['success' => false, 'errors' => $this->leads->errors()];
        }

        $id = $this->leads->getInsertID();
        $this->activity->log('leads', 'created', $actingUserId, "Created lead #{$id} ({$data['first_name']} {$data['last_name']})", (string) $id);

        return ['success' => true, 'id' => $id];
    }

    public function update(int $id, array $input, ?int $actingUserId): array
    {
        $lead = $this->leads->find($id);
        if (! $lead) {
            return ['success' => false, 'errors' => ['id' => 'Lead not found.']];
        }

        if ($lead['status'] === 'converted') {
            return ['success' => false, 'errors' => ['status' => 'Converted leads cannot be edited.']];
        }

        $data = $this->mapInput($input, $actingUserId);
        $data['updated_by'] = $actingUserId;
        $data['score']      = $this->scoring->calculateScore(array_merge($lead, $data));

        if (! $this->leads->update($id, $data)) {
            return ['success' => false, 'errors' => $this->leads->errors()];
        }

        $this->activity->log('leads', 'updated', $actingUserId, "Updated lead #{$id}", (string) $id);

        return ['success' => true];
    }

    public function delete(int $id, ?int $actingUserId): array
    {
        $lead = $this->leads->find($id);
        if (! $lead) {
            return ['success' => false, 'error' => 'Lead not found.'];
        }

        $this->leads->delete($id);
        $this->activity->log('leads', 'deleted', $actingUserId, "Deleted lead #{$id}", (string) $id);

        return ['success' => true];
    }

    protected function mapInput(array $input, ?int $actingUserId): array
    {
        return [
            'first_name'      => trim($input['first_name']),
            'last_name'       => trim($input['last_name']),
            'company_name'    => $input['company_name'] ?: null,
            'email'           => $input['email'] ?: null,
            'phone'           => $input['phone'] ?: null,
            'job_title'       => $input['job_title'] ?: null,
            'lead_source_id'  => ! empty($input['lead_source_id']) ? (int) $input['lead_source_id'] : null,
            'assigned_to'     => ! empty($input['assigned_to']) ? (int) $input['assigned_to'] : null,
            'status'          => $input['status'] ?? 'new',
            'priority'        => $input['priority'] ?? 'medium',
            'estimated_value' => $input['estimated_value'] !== '' && $input['estimated_value'] !== null
                ? (float) $input['estimated_value'] : null,
            'notes'           => $input['notes'] ?: null,
        ];
    }
}
