<?php

/*
* Trata informações do webhook de push do bitbucket
 */
class BitbucketController extends GxController {

    var $help = 'Bitbucket WebHook + Confluence';

    var $client;
    var $token;
    var $file = 'php://input';

    public function init() {
        // $url = 'http://interno.windel.com.br:8090/rpc/soap-axis/confluenceservice-v2?wsdl';
        // $this->client = new SoapClient($url, array(
        //         'trace' => 1,
        //         'stream_context' => stream_context_create(
        //             array('http' => array(
        //                     'protocol_version' => 1.0,
        //                     'header' => 'Transfer-Encoding: chunked' . "\r\n",
        //                 )
        //             )
        //         )
        //     )
        // );
        // $this->token = $this->client->login('consulta', 'windel');
    }

    public function actionCrmPush() {
        $space_key = 'CRM';
        $model_name = 'Pendencias';
        $this->_sync($space_key, $model_name);
    }

    public function actionWindelCSPush() {
        $space_key = 'WIN';
        $model_name = 'Solicitacoes';
        $this->_sync($space_key, $model_name);
    }

    public function actionZendelPush()
    {
        $space_key = 'ZEN';
        $model_name = 'Pendencias';
        $this->_sync($space_key, $model_name);
    }

    public function actionApiPush()
    {
        $space_key = 'API';
        $model_name = 'Pendencias';
        $this->_sync($space_key, $model_name);
    }

    public function actionClientePush()
    {
        $space_key = 'CLIEN';
        $model_name = 'Pendencias';
        $this->_sync($space_key, $model_name);
    }

    private function _sync($space_key, $model_name) {
        $json = @file_get_contents($this->file);
        $data = json_decode(utf8_encode($json));
        if(!isset($data->push) || !isset($data->push->changes[0])) {
            echo 'Nada para ser sincronizado! (' .__METHOD__.'() '.__LINE__ .')';
            return;
        }
        if(!isset($data->push->changes[0]->commits)) {
            echo 'Nenhum commit presente para ser sincronizado! (' .__METHOD__.'() '.__LINE__ .')';
            return;
        }
        $commits = $data->push->changes[0]->commits;
        foreach($commits as $commit) {
            $link = $commit->links->html->href;
            if (isset($commit->author->user->display_name)) {
                $author = $commit->author->user->display_name;
            } else {
                $author = $commit->author->raw;
            }
            $raw_message = $commit->message;
            $date = $this->_dateParse($commit->date);
            $id_pendencia = $this->_extractIdPendencia($raw_message);
            $page_code = $this->_extractPageCode($raw_message);
            $message = $this->_extractMessage($raw_message);
            // if($page_code) {
            //     $this->_updateConfluence($space_key, $page_code, utf8_decode($date), utf8_decode($author), utf8_decode($link), utf8_decode($message), $id_pendencia, $model_name);
            // }
            if($id_pendencia) {
                $this->_saveCommit($model_name, $id_pendencia, utf8_decode($date), utf8_decode($author), utf8_decode($link), utf8_decode($message), $space_key, $page_code);
            }
        }
        echo 'Finalizado (' .__METHOD__.'() '.__LINE__ .')' . PHP_EOL;
    }

    private function _extractIdPendencia($message) {
        $begin = 'CODIGO_PENDENCIA:';
        return $this->_extract($message, $begin);
    }

    private function _extractPageCode($message) {
        $begin = 'PAGINA_CONFLUENCE:';
        return $this->_extract($message, $begin);
    }

    private function _extractMessage($message) {
        $begin = 'ALTERACOES_FEITAS:';
        return $this->_extract($message, $begin);
    }

    private function _extract($message, $begin) {
        $correct_line = '';
        $lines = explode('//EOL', $message);
        foreach($lines as $line) {
            if(stripos($line, $begin) !== false) {
                $correct_line = trim($line);
            }
        }
        $correct_line = str_replace($begin, '', $correct_line);
        $correct_line = trim($correct_line);
        return $correct_line;
    }

    /*
    * $date string (format 2017-03-10T18:48:06+00:00)
     */
    private function _dateParse($date, $format = 'd/m/Y H:i:s') {
        $date = str_replace('T', ' ', $date);
        $date = substr($date, 0, 19);
        $date = DateTime::createFromFormat('Y-m-d H:i:s', $date);
        $date->sub(new DateInterval("PT3H"));
        return $date->format($format);
    }

    private function _updateConfluence($space_key, $page_code, $date, $author, $link, $message, $id_pendencia = false, $model_pendencia = false) {
        $page_name = "{$page_code} - 6 Commits";
        $page = false;
        try {
            $page = $this->client->getPage(
                new SoapVar($this->token, XSD_STRING, null, null, "token"),
                new SoapVar($space_key, XSD_STRING, null, null, "spacekey"),
                new SoapVar($page_name, XSD_STRING, null, null, "pageTitle")
            );
        } catch( Exception $e) {
            // não tratado pois será criada nova página
        }

        $space_key = utf8_encode($space_key);
        $page_code = utf8_encode($page_code);
        $date = utf8_encode($date);
        $author = utf8_encode($author);
        $link = utf8_encode($link);
        $message = nl2br(utf8_encode($message));

        $content = isset($page->content) ? $page->content : '';
        $content .= "<p><b>{$date}</b> por <b>{$author}</b><br /><b>Mensagem: </b><![CDATA[{$message}]]><br /><b>Link: </b><a href='{$link}' target='_blank'>{$link}</a><br />".($id_pendencia && $model_pendencia ? "<b>Pendencia: </b><a href='https://crm.windel.com.br/index.php?r={$model_pendencia}/view&amp;id={$id_pendencia}' target='_blank'>{$id_pendencia}</a><br />" : "")."</p>";

        if($page) {
            $page->content = $content;
            $this->client->storePage($this->token, $page);
            echo 'Página "'.$page_name.'" do confluence atualizada com o novo commit (' .__METHOD__.'() '.__LINE__ .')' . PHP_EOL;
        } else {
            echo 'Página "'.$page_name.'" do confluence não encontrada (' .__METHOD__.'() '.__LINE__ .')' . PHP_EOL;
            $page2_name = "{$page_code} - 1 Requisitos Funcionais";
            $page2 = false;
            try {
                $page2 = $this->client->getPage(
                    new SoapVar($this->token, XSD_STRING, null, null, "token"),
                    new SoapVar($space_key, XSD_STRING, null, null, "spacekey"),
                    new SoapVar($page2_name, XSD_STRING, null, null, "pageTitle")
                );
            } catch( Exception $e) {
                $this->notifyErrorPage($content, 'Não foi possível identificar a página pai para criação da página de commits');
                echo 'Não foi possível identificar a página pai para criação da página de commits (' .__METHOD__.'() '.__LINE__ .')'. PHP_EOL;
                echo $e->getMessage();
                echo $e->getTraceAsString();
                die;
            }

            $parent_id = $page2->parentId;
            /*try {
                $parent = $this->client->getPage(
                    new SoapVar($this->token, XSD_STRING, null, null, "token"),
                    new SoapVar($parent_id, XSD_LONG, null, null, "pageId")
                );
            } catch( Exception $e) {
                $this->notifyErrorPage($page, 'Não foi possível identificar a página pai para criação da página de commits');
                echo 'Não foi possível identificar a página pai para criação da página de commits (' .__METHOD__.'() '.__LINE__ .')'. PHP_EOL;
                echo $e->getMessage();
                echo $e->getTraceAsString();
                die;
            }*/

            $pageInfo = array(
                "id" => null,
                "type" =>"page",
                "parentId" => $parent_id,
                "title" => $page_name,
                "space" => $space_key,
                "content" => $content,
                "permissions" => 1,
                "version" => 1,
                "contentStatus" => 'current',
                "current" => 1,
                "homePage" => null,
            );
            $this->client->storePage($this->token, $pageInfo);
            echo 'Criada nova página: "'. $page_name .'" no confluence e vinculado commit á ela (' .__METHOD__.'() '.__LINE__ .')'. PHP_EOL;

        }
    }

    private function _saveCommit($model, $id_pendencia, $date, $author, $link, $message, $space_key = false, $page_code = false) {
        $exists = Commits::model()->exists("
            CMT_IDPENDENCIA = '{$id_pendencia}' AND
            CMT_LINK = '{$link}'
        ");

        if (!$exists) {

            $commit = new Commits();
            $commit->CMT_MODEL = $model;
            $commit->CMT_IDPENDENCIA = $id_pendencia;
            $commit->CMT_DATA = $date;
            $commit->CMT_AUTOR = $author;
            $commit->CMT_MENSAGEM = $message;
            $commit->CMT_LINK = $link;

            // if($page_code) {

            //     $page2 = false;
            //     try {
            //         $page2_name = "{$page_code} - 1 Requisitos Funcionais";
            //         $page2 = $this->client->getPage(
            //             new SoapVar($this->token, XSD_STRING, null, null, "token"),
            //             new SoapVar($space_key, XSD_STRING, null, null, "spacekey"),
            //             new SoapVar($page2_name, XSD_STRING, null, null, "pageTitle")
            //         );

            //     } catch( Exception $e) {

            //         $this->notifyError($commit, 'Não foi possível identificar a página pai no confluence para vinculação dos commits no CRM');
            //         echo 'Não foi possível identificar a página pai no confluence para vinculação dos commits no CRM (' .__METHOD__.'() '.__LINE__ .')'. PHP_EOL;
            //         echo $e->getMessage();
            //         echo $e->getTraceAsString();
            //         die;
            //     }
            //     if($page2) {
            //         try {
            //             $parent_id = (int)$page2->parentId;
            //             $commit->CMT_PAGINA_CONFLUENCE = 'http://interno.windel.com.br:8090/pages/viewpage.action?pageId='.$parent_id;

            //         } catch( Exception $e) {

            //             $this->notifyError($commit, 'Não foi possível identificar a página pai no confluence para vinculação dos commits no CRM');
            //             echo 'Não foi possível identificar a página pai no confluence para vinculação dos commits no CRM (' .__METHOD__.'() '.__LINE__ .')'. PHP_EOL;
            //             echo $e->getMessage();
            //             echo $e->getTraceAsString();
            //             die;
            //         }
            //     }
            // }

            $commit->save(false);
            $pendencia = ($model == 'Pendencias' ? Pendencias::model()->findByPk($id_pendencia) : Solicitacoes::model()->findByPk($id_pendencia));
            if(!$pendencia) {
                echo 'Pendência não encontrata na base do CRM. O vínculo será feito, mas é necessário corrigir o código da pendência (' .__METHOD__.'() '.__LINE__ .')' . PHP_EOL;
                $this->notifyError($commit, 'Commit vinculado a pendência inexistente');
            }

            echo 'Commit vinculado a Pendência na base do CRM (' .__METHOD__.'() '.__LINE__ .')' . PHP_EOL;
        } else {
            echo 'Commit já cadastrado na base do CRM, nenhuma ação realizada (' .__METHOD__.'() '.__LINE__ .')' . PHP_EOL;
        }
    }

    private function notifyError($commit, $title) {
        $body = '';
        $body .= '<b>Id do commit</b>: ' . $commit->CMT_ID . PHP_EOL;
        $body .= '<b>Model</b>: ' . $commit->CMT_MODEL . PHP_EOL;
        $body .= '<b>Data</b>: ' . $commit->CMT_DATA . PHP_EOL;
        $body .= '<b>Autor</b>: ' . $commit->CMT_AUTOR . PHP_EOL;
        $body .= '<b>Mensagem</b>: ' . $commit->CMT_MENSAGEM . PHP_EOL;
        $body .= '<b>Link</b>: ' . $commit->CMT_LINK . PHP_EOL;
        Util::sendEmail('marcio@delvale.com.br', $title, nl2br($body));
        echo 'Responsável pelo CRM notificado sobre erro:  '.$title.' (' .__METHOD__.'() '.__LINE__ .')' . PHP_EOL;
    }
    private function notifyErrorPage($message, $title) {
        $message = (array) $message;
        $body = '';
        foreach($message as $key => $value) {
            $body .= "<b>{$key}</b>: {$value}" . PHP_EOL;
        }
        Util::sendEmail('marcio@delvale.com.br', $title, nl2br($body));
        echo 'Responsável pelo CRM notificado sobre erro:  '.$title.' (' .__METHOD__.'() '.__LINE__ .')' . PHP_EOL;
    }

    /*public function actionTestWindelCSPushTest() {
        $this->file = YII_BASE . DS . 'protected' . DS . 'tests' . DS . 'assets' . DS . 'erro.json';
        echo '<pre />';
        $this->actionWindelCSPush();
    }*/
}
