<?php

namespace Modules\Sale\Services;

use App\Models\ActivityLogModel;
use App\Models\OpportunityModel;
use App\Models\SalesStageModel;

class OpportunityService
{
    protected OpportunityModel $opportunities;
    protected SalesStageModel $stages;
    protected ActivityLogModel $activity;

    public function __construct()
    {
        $this->opportunities = new OpportunityModel();
        $this->stages        = new SalesStageModel();
        $this->activity      = new ActivityLogModel();
    }

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

        if ($data['probability'] === null && ! empty($data['sales_stage_id'])) {
            $stage = $this->stages->find($data['sales_stage_id']);
            if ($stage) {
                $data['probability'] = (int) $stage['default_probability'];
            }
        }

        $data['probability'] = (int) ($data['probability'] ?? 0);
        $data['created_by'] = $actingUserId;
        $data['updated_by'] = $actingUserId;

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

        $id = $this->opportunities->getInsertID();
        $this->activity->log('opportunities', 'created', $actingUserId, "Created opportunity #{$id} ({$data['name']})", (string) $id);

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

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

        $data = $this->mapInput($input);
        $data['probability'] = (int) ($data['probability'] ?? 0);
        $data['updated_by']  = $actingUserId;

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

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

        return ['success' => true];
    }

    public function updateProbability(int $id, int $probability, ?int $actingUserId): array
    {
        $opportunity = $this->opportunities->find($id);
        if (! $opportunity) {
            return ['success' => false, 'error' => 'Opportunity not found.'];
        }

        if ($probability < 0 || $probability > 100) {
            return ['success' => false, 'error' => 'Probability must be between 0 and 100.'];
        }

        $this->opportunities->update($id, [
            'probability' => $probability,
            'updated_by'  => $actingUserId,
        ]);

        $this->activity->log('opportunities', 'probability_updated', $actingUserId, "Updated probability for opportunity #{$id} to {$probability}%", (string) $id);

        return ['success' => true];
    }

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

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

        return ['success' => true];
    }

    protected function mapInput(array $input): array
    {
        $probability = $input['probability'] ?? null;
        if ($probability === '' || $probability === null) {
            $probability = null;
        } else {
            $probability = max(0, min(100, (int) $probability));
        }

        return [
            'name'                => trim($input['name']),
            'company_id'          => ! empty($input['company_id']) ? (int) $input['company_id'] : null,
            'contact_id'          => ! empty($input['contact_id']) ? (int) $input['contact_id'] : null,
            'sales_stage_id'      => ! empty($input['sales_stage_id']) ? (int) $input['sales_stage_id'] : null,
            'competitor_id'       => ! empty($input['competitor_id']) ? (int) $input['competitor_id'] : null,
            'expected_revenue'    => isset($input['expected_revenue']) && $input['expected_revenue'] !== ''
                ? (float) $input['expected_revenue']
                : 0,
            'probability'         => $probability,
            'expected_close_date' => trim($input['expected_close_date'] ?? '') ?: null,
            'status'              => $input['status'] ?? 'open',
            'description'         => $input['description'] ?: null,
        ];
    }
}
