<?php

declare(strict_types=1);

namespace App\Models;

use CodeIgniter\Model;

class LeadCallModel extends Model
{
    protected $table            = 'lead_calls';
    protected $primaryKey       = 'id';
    protected $returnType       = 'array';
    protected $useSoftDeletes   = false;
    protected $allowedFields    = [
        'lead_id',
        'agent_id',
        'agent_email',
        'cloudtalk_call_id',
        'cloudtalk_contact_id',
        'direction',
        'caller_number',
        'destination_number',
        'status',
        'started_at',
        'answered_at',
        'ended_at',
        'duration_seconds',
        'talk_time_seconds',
        'wrap_up_time_seconds',
        'result',
        'agent_notes',
        'disposition',
        'raw_json',
    ];
    protected $useTimestamps    = true;
    protected $createdField     = 'created_at';
    protected $updatedField     = 'updated_at';

    public function findByCloudTalkCallId(string $callId): ?array
    {
        $row = $this->where('cloudtalk_call_id', $callId)->first();
        return $row ?: null;
    }

    public function findByPhoneAndTimeWindow(
        ?int $leadId,
        string $destinationDigits,
        string $callerDigits,
        string $startedAtMysql,
        int $windowSeconds = 600
    ): ?array {
        $destClean = preg_replace('/\D+/', '', $destinationDigits);
        $callClean = preg_replace('/\D+/', '', $callerDigits);
        if ($destClean === '' && $callClean === '') return null;
        if ($startedAtMysql === '') return null;
        $ts = strtotime($startedAtMysql);
        if ($ts === false) return null;
        $minTs = $ts - $windowSeconds;
        $maxTs = $ts + $windowSeconds;
        $minDate = date('Y-m-d H:i:s', $minTs);
        $maxDate = date('Y-m-d H:i:s', $maxTs);

        $builder = $this;
        if ($leadId > 0) {
            $builder = $builder->where('lead_id', $leadId);
        }
        $builder = $builder
            ->groupStart()
                ->where('started_at >=', $minDate)
                ->where('started_at <=', $maxDate)
            ->groupEnd();

        if ($destClean !== '' && $callClean !== '') {
            $builder = $builder
                ->groupStart()
                    ->where("REGEXP_REPLACE(COALESCE(destination_number,''), '[^0-9]', '') = ", $destClean)
                    ->orWhere("REGEXP_REPLACE(COALESCE(caller_number,''),      '[^0-9]', '') = ", $callClean)
                ->groupEnd();
        } elseif ($destClean !== '') {
            $builder = $builder->where("REGEXP_REPLACE(COALESCE(destination_number,''), '[^0-9]', '') = ", $destClean);
        } else {
            $builder = $builder->where("REGEXP_REPLACE(COALESCE(caller_number,''),      '[^0-9]', '') = ", $callClean);
        }

        $row = $builder->orderBy('started_at', 'DESC')->first();
        return $row ?: null;
    }

    public function sanitizeCallStatus(mixed $rawStatus, string $default = 'initiated'): string
    {
        $s = trim((string) $rawStatus);
        if ($s === '' || ctype_digit($s)) {
            return $default;
        }
        $known = [
            'initiated','ringing','answered','ended','missed','failed','canceled','queued','in_progress','busy','no_answer',
            'initiated_call','call_initiated','call_started','start','started','answered_call','hangup','hangup_caller','hangup_agent'
        ];
        $sLower = strtolower($s);
        foreach ($known as $k) {
            if ($sLower === $k || str_contains($sLower, $k)) {
                if (in_array($k, ['start','started','call_started','initiated_call','call_initiated','queued'], true)) return 'ringing';
                if (in_array($k, ['answered_call'], true)) return 'answered';
                if (in_array($k, ['hangup','hangup_caller','hangup_agent'], true)) return 'ended';
                if (in_array($k, ['no_answer'], true)) return 'missed';
                if (in_array($k, ['in_progress'], true)) return 'answered';
                return $k;
            }
        }
        $map = [
            'active'    => 'answered',
            'completed' => 'ended',
            'done'      => 'ended',
            'finished'  => 'ended',
            'success'   => 'ended',
            'ok'        => 'ended',
        ];
        return $map[$sLower] ?? $default;
    }

    public function getForLead(int $leadId): array
    {
        return $this
            ->select('lead_calls.*, users.full_name as agent_name, users.username as agent_username, users.email as agent_email')
            ->join('users', 'users.id = lead_calls.agent_id', 'left')
            ->where('lead_calls.lead_id', $leadId)
            ->orderBy('lead_calls.created_at', 'DESC')
            ->findAll();
    }
}
