<?php
declare(strict_types=1);

namespace App\Services;

use App\Core\Auth;
use App\Models\Account;
use App\Models\Activity;
use App\Models\AuditLog;
use App\Models\Contact;
use App\Models\EmailLog;
use App\Models\Lead;
use App\Models\Opportunity;
use App\Models\Task;

final class RecordService
{
    public static function logActivity(string $type, string $subject, ?string $body, ?string $relatedType, ?int $relatedId): int
    {
        return Activity::create([
            'type' => $type,
            'subject' => $subject,
            'body' => $body,
            'related_type' => $relatedType,
            'related_id' => $relatedId,
            'owner_id' => Auth::instance()->id(),
            'activity_at' => date('Y-m-d H:i:s'),
        ]);
    }

    public static function logLeadStatus(int $leadId, string $from, string $to, ?string $note = null): int
    {
        $labels = Lead::statusLabels();
        $fromLabel = $labels[$from] ?? $from;
        $toLabel = $labels[$to] ?? $to;
        $text = trim((string) $note);
        return self::logActivity(
            'stage',
            $fromLabel . ' → ' . $toLabel,
            $text !== '' ? $text : null,
            'lead',
            $leadId
        );
    }

    public static function convertLead(int $leadId, bool $createDeal, float $amount = 0): array
    {
        $lead = Lead::find($leadId);
        if (!$lead) {
            return ['ok' => false, 'error' => 'Lead not found.'];
        }
        if ($lead['status'] === 'converted') {
            return ['ok' => false, 'error' => 'Already converted.'];
        }
        $fromStatus = (string) ($lead['status'] ?? 'new');
        $name = $lead['company'] ?: trim($lead['first_name'] . ' ' . $lead['last_name']);
        $accountId = Account::create([
            'name' => $name,
            'email' => $lead['email'],
            'phone' => $lead['phone'],
            'territory_id' => $lead['territory_id'] ?: null,
            'owner_id' => $lead['owner_id'] ?: Auth::instance()->id(),
            'status' => 'active',
        ]);
        Contact::create([
            'account_id' => $accountId,
            'first_name' => $lead['first_name'],
            'last_name' => $lead['last_name'] ?: $lead['first_name'],
            'email' => $lead['email'],
            'phone' => $lead['phone'],
            'owner_id' => $lead['owner_id'] ?: Auth::instance()->id(),
            'is_primary' => 1,
        ]);
        $oppId = null;
        if ($createDeal) {
            $stages = \App\Models\PipelineStage::openStages();
            $stage = $stages[0] ?? null;
            if ($stage) {
                $oppId = Opportunity::create([
                    'account_id' => $accountId,
                    'name' => $name,
                    'amount' => $amount,
                    'stage_id' => $stage['id'],
                    'probability' => $stage['probability'],
                    'owner_id' => $lead['owner_id'] ?: Auth::instance()->id(),
                    'next_step' => 'Discovery call',
                    'next_step_at' => date('Y-m-d H:i:s', strtotime('+2 days')),
                ]);
            }
        }
        Lead::update($leadId, [
            'status' => 'converted',
            'converted_account_id' => $accountId,
            'converted_opportunity_id' => $oppId,
            'converted_at' => date('Y-m-d H:i:s'),
        ]);
        self::logLeadStatus($leadId, $fromStatus, 'converted');
        self::logActivity('note', 'Lead converted to account', null, 'account', $accountId);
        AuditLog::write('lead.convert', 'lead', $leadId, ['account_id' => $accountId, 'opportunity_id' => $oppId]);
        return ['ok' => true, 'account_id' => $accountId, 'opportunity_id' => $oppId];
    }

    public static function logEmail(array $data): int
    {
        $id = EmailLog::create([
            'related_type' => $data['related_type'] ?: null,
            'related_id' => $data['related_id'] ?: null,
            'direction' => 'out',
            'subject' => $data['subject'],
            'body' => $data['body'],
            'to_email' => $data['to_email'],
            'from_email' => current_user()['email'] ?? null,
            'owner_id' => Auth::instance()->id(),
            'provider' => $data['provider'] ?? null,
            'sent_at' => date('Y-m-d H:i:s'),
            'status' => !empty($data['sent']) ? 'sent' : 'logged',
        ]);
        self::logActivity(
            'email',
            $data['subject'],
            $data['body'],
            $data['related_type'] ?: null,
            $data['related_id'] ? (int) $data['related_id'] : null
        );
        return $id;
    }

    public static function addTask(array $data): int
    {
        $title = trim((string) ($data['title'] ?? ''));
        $relatedType = trim((string) ($data['related_type'] ?? ''));
        $relatedId = (int) ($data['related_id'] ?? 0);
        $priority = (string) ($data['priority'] ?? 'normal');
        if (!in_array($priority, ['low', 'normal', 'high'], true)) {
            $priority = 'normal';
        }

        $ownerId = (int) ($data['owner_id'] ?? 0) ?: (int) Auth::instance()->id();
        $id = Task::create([
            'title' => $title,
            'description' => trim((string) ($data['description'] ?? '')) ?: null,
            'due_at' => self::combineDueAt($data),
            'status' => 'open',
            'priority' => $priority,
            'owner_id' => $ownerId,
            'related_type' => $relatedType !== '' ? $relatedType : null,
            'related_id' => $relatedId > 0 ? $relatedId : null,
            'created_by' => Auth::instance()->id(),
        ]);
        self::logActivity(
            'task',
            $title,
            $data['description'] ?? null,
            $relatedType !== '' ? $relatedType : null,
            $relatedId > 0 ? $relatedId : null
        );
        NotificationService::taskAssigned($ownerId, $title);
        return $id;
    }

    public static function combineDueAt(array $data): ?string
    {
        $date = trim((string) ($data['due_date'] ?? ''));
        $time = trim((string) ($data['due_time'] ?? ''));
        if ($date !== '') {
            if ($time === '') {
                $time = '17:00';
            }
            return self::normalizeDateTime($date . ' ' . $time);
        }
        return self::normalizeDateTime($data['due_at'] ?? null);
    }

    public static function normalizeDateTime(mixed $value): ?string
    {
        $raw = trim((string) $value);
        if ($raw === '') {
            return null;
        }
        $raw = str_replace('T', ' ', $raw);
        if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/', $raw)) {
            $raw .= ':00';
        }
        return $raw;
    }
}
