<?php

namespace Win7\Phone\Manager;

use DateTime;
use Win7\Application\Common\StringUtils;
use Win7\Application\Manager\FilterParams;
use Win7\Application\Manager\Manager;
use Win7\Application\Repository\RepositoryManager;
use Win7\Phone\DataTable\CallTable;
use Win7\Phone\Repository\CallRepository;

/**
 * @namespace Win7\Phone\Manager
 * @author Thiago Daher
 *
 * @method CallRepository getRepository()
 */
class CallManager extends Manager
{

    /**
     * @var \Win7\Phone\DataTable\CallTable
     */
    private CallTable $callTable;

    /**
     * @param \Win7\Application\Repository\RepositoryManager $repositoryManager
     * @param \Win7\Phone\DataTable\CallTable $callTable
     */
    public function __construct(RepositoryManager $repositoryManager, CallTable $callTable)
    {
        parent::__construct($repositoryManager);
        $this->callTable = $callTable;
    }

    /**
     * @return string
     */
    protected function getRepositoryClass(): string
    {
        return CallRepository::class;
    }

    /**
     * Obtém os dados de segmento da ligação.
     *
     * @param mixed $id representa o id da ligação
     * @return array|null
     * @throws \ReflectionException
     */
    public function getDadosLigacao($id): ?array
    {
        $ligacao = $this->getRepository()->findById($id);

        if (!$ligacao) {
            return null;
        }

        $resultado = [];

        $segments = $ligacao->segments->sortBy(function ($item) {
            return (int) $item->subrow_desc_number;
        })->values();

        foreach ($segments as $segment) {
            $segmentData = $segment->toArray();
            $segmentData['ringing_duration'] = StringUtils::convertDurationSeconds($segmentData['ringing_duration']);
            $segmentData['talking_duration'] = StringUtils::convertDurationSeconds($segmentData['talking_duration']);
            $segmentData['answered'] = $segmentData['answered'] ? 't' : 'n';

            if (!$ligacao->antiga) {
                $descricao = $this->gerarDescricaoCDR($segmentData);
                $origem = StringUtils::filter3cxNumber($segment->getSourceNumberFromData(), $segment->source_display_name);
                $destino = StringUtils::filter3cxNumber($segment->getDestinationNumberFromData(), $segment->destination_display_name);
                $descricao = str_replace(['#ORIGEM#', '#DESTINO#'], [$origem, $destino], $descricao);

                if(!empty($segment->destination_display_name) && ctype_digit($segment->getDestinationNumberFromData())){
                    $destino = $segment->destination_display_name . " - $destino";
                }

                $segmentData['descricao_cdr'] = $descricao;
                $segmentData['origem_cdr'] = $origem;
                $segmentData['destino_cdr'] = $destino;
            }

            $resultado[] = $segmentData;
        }

        return $resultado;
    }

    /**
     * Gera um descrição do CDR, com placeholders na string para a origem e destino.
     * #ORIGEM# e #DESTINO#.
     *
     * @param array $cdr
     * @return string
     */
    public function gerarDescricaoCDR(array $cdr): string
    {
        $creationMethod = $cdr['creation_method'] ?? '';
//        $creationForwardReason = $cdr['creation_forward_reason'] ?? '';
        $terminationReason = $cdr['termination_reason'] ?? '';

        $explicacao = "";

        switch ($creationMethod) {
            case 'call_init':
                $explicacao .= "Chamada iniciada por #ORIGEM#. ";
                break;
            case 'route_to':
                $explicacao .= "Chamada roteada para #DESTINO#. ";
                break;
            case 'transfer':
                $explicacao .= "Chamada transferida para #DESTINO#. ";
                break;
            case 'divert':
                $explicacao .= "Chamada desviada para #DESTINO#. ";
                break;
            case 'pickup':
                $explicacao .= "#DESTINO# atendeu a chamada. ";
                break;
            case 'join':
                $explicacao .= "#DESTINO# foi adicionado à chamada. ";
                break;
            case 'barge_in':
                $explicacao .= "#DESTINO# entrou na chamada. ";
                break;
            case 'fork':
                $explicacao .= "Chamada bifurcada para #DESTINO#. ";
                break;
            default:
                $explicacao .= "Ação de chamada desconhecida. ";
                break;
        }

//        if (!empty($creationForwardReason) && $creationForwardReason !== 'none') {
//            $motivos = [
//                'no_answer' => 'sem resposta',
//                'busy' => 'ocupado',
//                'forward_all' => 'encaminhamento incondicional',
//                'not_registered' => 'destino não registrado',
//                'holiday' => 'feriado',
//                'office_time' => 'fora do horário de expediente',
//                'out_of_office' => 'fora do escritório',
//                'break_time' => 'em intervalo',
//                'polling' => 'tentativa de distribuição',
//                'by_caller_id' => 'roteamento por Caller ID',
//                'by_did' => 'roteamento por DID',
//                'no_destinations' => 'sem destinos disponíveis',
//                'callback_requested' => 'callback solicitado',
//                'callback' => 'retorno de chamada',
//            ];
//            $motivo = $motivos[$creationForwardReason] ?? $creationForwardReason;
//            $explicacao .= "Motivo do redirecionamento: {$motivo}. ";
//        }

        if (!empty($terminationReason)) {
            $terminacoes = [
                'continued_in' => 'Encaminhamento por regra do PABX',
                'redirected' => 'Chamada redirecionada',
                'rejected' => 'Chamada rejeitada',
                'cancelled' => 'Chamada cancelada',
                'src_participant_terminated' => 'A origem encerrou a chamada',
                'dst_participant_terminated' => 'O destino encerrou a chamada',
            ];
            $motivoTerminacao = $terminacoes[$terminationReason] ?? $terminationReason;
            $explicacao .= "$motivoTerminacao. ";
        }

        return trim($explicacao);
    }

    /**
     * @param \Win7\Application\Manager\FilterParams $params
     * @return array
     * @throws \ReflectionException
     */
    public function getSubligacoes(FilterParams $params): array
    {
        $resultado = $this->getRepository()->findSubligacoes($params);

        $subligacoes = [];

        foreach ($resultado as $subligacao) {
            $startTime = DateTime::createFromFormat('Y-m-d H:i:s', $subligacao->start_time);

            $subligacoes[] = [
                'data' => $startTime->format('d/m/Y H:i:s'),
                'custo' => StringUtils::formatMoney($subligacao->real_cost),
                'id' => $subligacao->id,
            ];
        }

        return $subligacoes;
    }

    /**
     * @param array $params
     * @return int
     * @throws \ReflectionException
     */
    public function contarLigacoes(array $params): int
    {
        $params = new FilterParams($params);

        if ($params->getOption('esconderEfetuadas')) {
            $params->setOption('efetuadas', false);
            $params->setOption('recebidas', true);
        }

        return $this->getRepository()->countCalls($params);
    }

    /**
     * Adaptação do método antigo para obter todas as ligações.
     * Ainda precisa ser muito melhorado, mas foi deixado assim para fins de compatibilidade.
     *
     * @param array $params
     * @return array
     * @throws \ReflectionException
     * @throws \Win7\Application\Exception\UserException
     */
    public function obterTodasLigacoes(array $params): array
    {
        $params = new FilterParams($params);
        $tableResult = $this->callTable->getAllData($params);
        $result = [];
        $ramais = [];
        $naoAtendidas = 0;

        foreach ($tableResult['data'] as $data) {
            if (!in_array($data[4], $ramais)) {
                $ramais[] = $data[4];
            }

            $result[] = [
                'fonte' => $data[4],
                'origem' => $data[2],
                'destino' => $data[3],
                'data' => $params->getOption('grafico') ? date('Y-m-d', strtotime($data[1])) : $data[1],
                'valor' => $data[5],
                'duracao' => $data[6],
                'valido' => $data[11] ? '1' : '0',
                'id' => $data[0],
                'atendida' => $data[10] ? 'Atendida' : 'Não Atendida',
                'espera' => $data[7],
                'duracaofinal' => $data[8],
            ];

            if (!$data[10]) {
                $naoAtendidas++;
            }
        }

        $extra = [];

        if (count($result) > 0) {
            $extra['data2'] = date('Y-m-d', strtotime($result[0]['data']));
            $extra['data'] = date('Y-m-d', strtotime($result[count($result) - 1]['data']));
        }

        $extra['ids'] = $ramais;
        $extra['totalgasto'] = $tableResult['valor'];
        $extra['totalligacoes'] = $tableResult['recordsTotal'];
        $extra['naoatendidas'] = $naoAtendidas;

        array_unshift($result, $extra);

        return $result;
    }
}