<?php

namespace Velis\VersionControl\Git;

use Velis\Model\DataObject;
use Velis\Model\Cacheable;
use Velis\App;
use Velis\Bpm\Ticket\Ticket;
use User\User;
use Velis\Bpm\Ticket\Log;
use Velis\VersionControl\Git\Repository\Revision;
use Velis\Model\Routable;

/**
 * Repository model
 *
 * @author Bartosz Izdebski <bartosz.izdebski@velis.pl>
 * @author Olek Procki <olo@velis.pl>
 */
class Repository extends DataObject implements Cacheable, Routable
{
    /**
     * Returns related sql table
     * @return string
     */
    protected function _getTableName()
    {
        return 'app.repository_tab';
    }


    /**
     * Returns revision url
     * @return string
     */
    public function getName()
    {
        return $this->url;
    }


    /**
     * Get short (directory) name of the repository
     */
    public function getShortName()
    {
        return array_pop(explode(':', $this->url));
    }


    /**
     * Import revisions from repository
     * @return void
     */
    public function importRevisions($revisionHash = null, $revisions = null)
    {
        if (!is_array($revisions)) {
            $git = new Shell($this);
            $revisions = $git->getInfo($this->last_revision_no, null, $revisionHash);
            $revisions = array_reverse($revisions, true);
        }

        foreach ($revisions as $revision) {
            $revisionExistsParams = array(
                'repository_id' => $this->repository_id,
                'revision_no'   => $revision['rev']
            );
            $revisionExists = reset(Revision::listAll($revisionExistsParams));
            if ($revisionExists) {
                continue;
            }

            $params = [
                'repository_id'    => $this->repository_id,
                'revision_no'      => $revision['rev'],
                'message'          => $revision['message'],
                'repository_login' => $revision['author_email'],
                'revision_date'    => $revision['date'],
                'branch'           => $revision['branch'],
                'sql_changed'      => $revision['sql_changed'],
            ];

            // To avoid the problem of false-positive test results,
            // set the status to "0" by default for all enabled test types.
            // This is important to prevent production updates on "yellow light" status.
            if ($revision['branch'] === 'master') {
                $availableTestTypes = App::$config->qa->masterTestsEnabled;
                foreach ($availableTestTypes as $testType) {
                    $params["{$testType}_tests_status"] = 0;
                }
            }

            self::$_db->insert('app.repository_revision_tab', $params);

            $repositoryRevId = self::$_db->currval('app.repository_revision_tab_repository_revision_id_seq');

            if (
                preg_match_all('/(#)([0-9]+)/i', $params['message'], $matches) ||
                preg_match_all('/(Merge branch \')([0-9]+)/i', $params['message'], $matches)
            ) {
                $tickets = Ticket::instance($matches[2]);
                foreach ($tickets as $ticket) {
                    $params = [
                        'repository_revision_id' => $repositoryRevId,
                        'ticket_id' => $ticket->id(),
                        'match_as_resolved' => 0,

                    ];
                    self::$_db->insert('app.repository_revision_ticket_tab', $params);
                }
            }
        }
    }

    /**
     * Returns rewrite route name
     * @return string
     */
    public function getRouteName()
    {
        return 'support-repository-git';
    }

    /**
     * Returns standard url with no rewrite
     * @return string
     */
    public function getStandardUrl()
    {
        return '/support/repository-git/index?repository_id=' . $this->id();
    }

    /**
     * Returns repo directory
     * @return string
     */
    public function repoDirectory()
    {
        if (strpos($this->url, '.git')) {
            return array_pop(explode('/', $this->url, 2));
        }
        return 'repositories' . DIRECTORY_SEPARATOR . $this->getShortName() . '.git';
    }

    /**
     * @param string $branchName
     * @return ?string
     */
    public function getRemoteBranchUrl(string $branchName): ?string
    {
        if ($this->url) {
            $repositoryUrl = 'https://' . preg_replace(['/(git@)|(\.git)/', '/org:/'], ['', 'org/'], $this->url);
            return $repositoryUrl . '/branch/' . $branchName;
        }
         return null;
    }
}
