<?php

namespace Win7\Phone;

use Win7\App;
use Win7\Phone\Exception\PhoneException;

/**
 * Classe de conexão direta com o 3cx. Utilizada para obter a lista de
 * ligações para gravação posterior no banco de dados local.
 *
 * @namespace Win7\Phone
 * @author Thiago Daher
 */
final class Connection
{

    /**
     * @var \Win7\Phone\Connection
     */
    private static Connection $instance;

    /**
     * @var array
     */
    private static array $config;

    /**
     * @var resource
     */
    private $connection;

    /**
     * @param $connection
     * @throws \Win7\Phone\Exception\PhoneException
     */
    private function __construct($connection)
    {
        if (!is_resource($connection)) {
            throw new PhoneException('Conexão com banco de dados inválida');
        }

        $this->connection = $connection;
    }

    /**
     * @return \Win7\Phone\Connection
     * @throws \Win7\Phone\Exception\PhoneException
     */
    public static function getConnection(): Connection
    {
        if (!isset(self::$instance)) {
            self::$instance = new Connection(pg_connect(sprintf(
                'host=%s port=%s dbname=%s user=%s password=%s connect_timeout=10',
                self::getOption('host'),
                self::getOption('port'),
                self::getOption('database'),
                self::getOption('user'),
                self::getOption('password'),
            )));
        }

        return self::$instance;
    }

    /**
     * @param array $config
     * @return void
     */
    public static function setConfig(array $config)
    {
        self::$config = $config;
    }

    /**
     * @return array
     */
    private static function getConfig(): array
    {
        if (!isset(self::$config)) {
            self::$config = App::getConfig()->get('phone');

        }

        return self::$config;
    }

    /**
     * @param string $optionName
     * @return mixed
     */
    private static function getOption(string $optionName)
    {
        return self::getConfig()[$optionName] ?? '';
    }

    /**
     * @param string $startDate
     * @param string $endDate
     * @return array
     * @throws \Win7\Phone\Exception\PhoneException
     */
    public function getCalls(string $startDate, string $endDate): array
    {
        $consulta = pg_query_params(
            $this->connection,
            "SELECT * FROM cl_get_call_log($1, $2, 0, '', 0, '', 0, 0, NULL, NULL, true)",
            [$startDate, $endDate]
        );

        if (!$consulta) {
            throw new PhoneException('Não foi possível fazer a consulta: ' . pg_last_error());
        }

        $results = pg_fetch_all($consulta);

        return !$results ? [] : $results;
    }

    /**
     * @param string $startDate
     * @param string $endDate
     * @return array
     * @throws PhoneException
     */
    public function getCDRCalls(string $startDate, string $endDate): array
    {
        $consulta = pg_query_params(
            $this->connection,
            "SELECT *
            FROM cdroutput
            where cdr_started_at >= $1
              and cdr_started_at <= $2
              and creation_method = 'call_init'
            order by cdr_started_at",
            [$startDate, $endDate]
        );

        if (!$consulta) {
            throw new PhoneException('Não foi possível fazer a consulta: ' . pg_last_error());
        }

        $results = pg_fetch_all($consulta);

        return !$results ? [] : $results;
    }

    /**
     * @param string $callHistoryId
     * @return array
     * @throws PhoneException
     */
    public function getCDRCall(string $callHistoryId): array
    {
        $consulta = pg_query_params(
            $this->connection,
            "SELECT cdroutput.*, cdrrecordings.recording_url FROM cdroutput 
            left join cdrrecordings on cdrrecordings.cdr_id = cdroutput.cdr_id
            where call_history_id = $1",
            [$callHistoryId]
        );

        if (!$consulta) {
            throw new PhoneException('Não foi possível fazer a consulta: ' . pg_last_error());
        }

        $results = pg_fetch_all($consulta);

        return !$results ? [] : $results;
    }
}