# coding: utf-8

hestiacp_ruby_gem_version = "3.3.0"
Gem.paths = {
  "GEM_HOME" => "#{__dir__}/vendor/bundle/ruby/#{hestiacp_ruby_gem_version}",
  "GEM_PATH" => "#{__dir__}/vendor/bundle/ruby/#{hestiacp_ruby_gem_version}",
}

require "rubygems"
require "sinatra"
require "puma"

require_relative "classes/config"
require_relative "classes/gitinfo"
require_relative "classes/db"
require_relative "classes/systeminfo"
require_relative "classes/utilities"
require_relative "classes/projects"
require_relative "classes/configs"

def print_error_page(error_status, error_meaasge)
  @page_name = "Ошибка выполнения"
  @status_err = error_status
  @error_msg = error_meaasge
  halt erb(:page5xx)
end

cfg = IniConfig.new()
db = DBase.new()

set :port, cfg.get_port
set :public_folder, File.dirname(__FILE__) + "/public"
use Rack::Session::Pool, :expire_after => 2592000

get "/" do
  @page_name = "Система сборки rpm пакетов"
  repo = GitRepo.new(cfg.get_repo, db)
  if repo.path.nil?
    print_error_page(503, "Путь к репозиториям не существует")
  else
    prj = ProjectsActions.new(cfg.get_projects_path, db)
    if prj.path.nil?
      print_error_page(503, "Путь к проектам не существует")
    else
      repo_data = repo.getrepos
      @repos_number = repo_data.length
      @rcp_number = db.get_recips.length
      @prj_number = prj.get_projects.length
      erb :index
    end
  end
end

get "/repos/:reponame/:branch" do
  @page_name = params["reponame"]
  repo = GitRepo.new(cfg.get_repo, db)
  if repo.path.nil?
    print_error_page(503, "Путь к репозиториям не существует")
  else
    tmp_result = repo.repo_info(params["reponame"], params["branch"])
    if tmp_result[:error].nil?
      @repo_data = tmp_result
      @ip_addr = systeminfo_get_ip
      @user_name = systeminfo_get_username
      @path_to_repo = File.join(repo.path, params["reponame"] + ".git")
      erb :gitinfo
    else
      print_error_page(503, tmp_result[:error])
    end
  end
end

get "/repos/:reponame" do
  @page_name = params["reponame"]
  repo = GitRepo.new(cfg.get_repo, db)
  if repo.path.nil?
    print_error_page(503, "Путь к репозиториям не существует")
  else
    tmp_result = repo.repo_info(params["reponame"])
    if tmp_result[:error].nil?
      @repo_data = tmp_result
      @ip_addr = systeminfo_get_ip
      @user_name = systeminfo_get_username
      @path_to_repo = File.join(repo.path, params["reponame"] + ".git")
      erb :gitinfo
    else
      print_error_page(503, tmp_result[:error])
    end
  end
end

post "/gitdelete/:reponame" do
  input_name = params["reponamedup"]
  repo = GitRepo.new(cfg.get_repo, db)
  if repo.path.nil?
    print_error_page(503, "Путь к репозиториям не существует")
  else
    if params["reponame"] == input_name
      repo.delete_repo(input_name)
    end
    redirect "/repos"
  end
end

get "/gitdelete" do
  redirect "/repos"
end

get "/repos" do
  @page_name = "Список доступных git репозиториев"
  repo = GitRepo.new(cfg.get_repo, db)
  if repo.path.nil?
    print_error_page(503, "Путь к репозиториям не существует")
  else
    @repo_data = repo.getrepos
    erb :gits
  end
end

get "/gitcreate" do
  @page_name = "Создать новый пустой git репозиторий"
  @error_data = session[:gitcreate_error]
  session[:gitcreate_error] = nil
  erb :newgit
end

post "/gitcreate" do
  if request.form_data?
    if params["gitname"].nil?
      session[:gitcreate_error] = "Не задано имя репозитория"
    else
      filename = sanitize_filename(params["gitname"])
      if filename != ""
        repo = GitRepo.new(cfg.get_repo, db)
        if repo.path.nil?
          print_error_page(503, "Путь к репозиториям не существует")
        else
          if repo.create_git(filename, params["gitdescr"]) != 0
            session[:gitcreate_error] = repo.error
          else
            redirect "/repos"
            return
          end
        end
      else
        session[:gitcreate_error] = "Название репозитория должно содержать только символы a-z, A-Z. 0-9 и _"
      end
    end
  end
  redirect "/gitcreate"
end

get "/recips" do
  @page_name = "Список доступных сценариев сборки"
  @rcp_data = db.get_recips
  erb :receips
end

get "/recips/:rcp_id" do
  repo = GitRepo.new(cfg.get_repo, db)
  if repo.path.nil?
    print_error_page(503, "Путь к репозиториям не существует")
  else
    @repo_data = repo.getrepos
    @rcp_id = params["rcp_id"]
    info = db.get_rcp_info_by_id(@rcp_id)
    @page_name = info[:filepath]
    @rcp_name = info[:filepath]
    if session[:rcp_old_description].nil?
      @old_filepath = info[:filepath]
    else
      @old_filepath = session[:rcp_old_filepath]
    end
    if session[:rcp_old_description].nil?
      @old_description = info[:descr]
    else
      @old_description = session[:rcp_old_description]
    end
    if session[:rcp_old_codedata].nil?
      @old_codedata = info[:content]
    else
      @old_codedata = session[:rcp_old_codedata]
    end
    if session[:rcp_old_gitlst].nil?
      @old_gitlst = info[:repos_list]
    else
      @old_gitlst = session[:rcp_old_gitlst]
    end
    @error_data = session[:rcpcreate_error]
    session[:rcpcreate_error] = nil
    session[:rcp_old_filepath] = nil
    session[:rcp_old_description] = nil
    session[:rcp_old_codedata] = nil
    session[:rcp_old_gitlst] = nil
    erb :rcpedit
  end
end

post "/recips/:rcp_id" do
  rcp_id = params["rcp_id"]
  session[:rcp_old_filepath] = params["filepath"]
  session[:rcp_old_description] = params["description"]
  session[:rcp_old_codedata] = params["codedata"]
  session[:rcp_old_gitlst] = params["gitlst"]
  if params["filepath"].nil? || params["description"].nil? || params["filepath"].strip == "" || params["description"].strip == ""
    session[:rcpcreate_error] = "Имя рецепта и описание не должны быть пустыми"
    redirect url("/recips/#{rcp_id}")
  else
    @error_data = db.updaterecip(rcp_id, params["filepath"], params["description"], params["codedata"], params["gitlst"])
    unless @error_data.nil?
      session[:rcpcreate_error] = @error_data
      redirect url("/recips/#{rcp_id}")
    else
      session[:rcp_old_filepath] = nil
      session[:rcp_old_description] = nil
      session[:rcp_old_codedata] = nil
      session[:rcp_old_gitlst] = nil
      redirect "/recips"
    end
  end
end

post "/rcpdelete/:rcp_id" do
  input_name = params["rcpnamedup"]
  rcp_id = params["rcp_id"]
  info = db.get_rcp_info_by_id(rcp_id)
  if info.nil?
    print_error_page(404, "Рецепта не существует")
  else
    if info[:filepath] == input_name
      db.delete_rcp(rcp_id)
    end
    redirect "/recips"
  end
end

post "/rcpdelete" do
  redirect "/recips"
end

get "/rcpcreate" do
  @page_name = "Создать новый рецепт"
  @old_filepath = session[:rcp_old_filepath]
  @old_description = session[:rcp_old_description]
  @old_codedata = session[:rcp_old_codedata]
  @old_gitlst = session[:rcp_old_gitlst]
  repo = GitRepo.new(cfg.get_repo, db)
  if repo.path.nil?
    print_error_page(503, "Путь к репозиториям не существует")
  else
    @repo_data = repo.getrepos
    @error_data = session[:rcpcreate_error]
    session[:rcpcreate_error] = nil
    erb :rcpcrt
  end
end

post "/rcpcreate" do
  session[:rcp_old_filepath] = params["filepath"]
  session[:rcp_old_description] = params["description"]
  session[:rcp_old_codedata] = params["codedata"]
  session[:rcp_old_gitlst] = params["gitlst"]
  if params["filepath"].nil? || params["description"].nil? || params["filepath"].strip == "" || params["description"].strip == ""
    session[:rcpcreate_error] = "Имя рецепта и описание не должны быть пустыми"
    redirect "/rcpcreate"
  else
    @error_data = db.createrecip(params["filepath"], params["description"], params["codedata"], params["gitlst"])
    unless @error_data.nil?
      session[:rcpcreate_error] = @error_data
      redirect "/rcpcreate"
    else
      session[:rcp_old_filepath] = nil
      session[:rcp_old_description] = nil
      session[:rcp_old_codedata] = nil
      session[:rcp_old_gitlst] = nil
      redirect "/recips"
    end
  end
end

get "/bldcfg" do
  @page_name = "Список конфигураций сборки"
  cfgs = ConfigsList.new(cfg)
  result = cfgs.get_configs
  @list_global = result[:global]
  @list_local = result[:local]
  @list_selected = result[:selected]
  erb :cfgslist
end

get "/bldcfginfo" do
  @filename = params["info"]
  if @filename.nil?
    print_error_page(503, "Не задано имя конфигурационного файла")
  else
    unless check_safe_path(@filename)
      print_error_page(503, "Доступ к файлу #{@filename} запрещен")
    else
      unless File.exist?(@filename)
        print_error_page(503, "Файл #{@filename} не существует")
      else
        @page_name = @filename
        @content = File.readlines(@filename)
        erb :cfgsinfo
      end
    end
  end
end

get "/projs" do
  @page_name = "Список проектов"
  prj = ProjectsActions.new(cfg.get_projects_path, db)
  if prj.path.nil?
    print_error_page(503, "Путь к проектам не существует")
  else
    @prj_list = prj.get_projects
    erb :prjlist
  end
end

get "/prjcreate" do
  @page_name = "Создать новый проект"
  @old_name = session[:prj_old_name]
  @old_description = session[:prj_old_description]
  @old_list = session[:prj_old_list]
  cfgs = ConfigsList.new(cfg)
  result = cfgs.get_configs
  @global_list = result[:global]
  @local_list = result[:local]
  @error_data = session[:prjcreate_error]
  session[:prjcreate_error] = nil
  erb :prjcrt
end

post "/prjcreate" do
  session[:prj_old_name] = params["projname"]
  session[:prj_old_description] = params["description"]
  session[:prj_old_list] = params["conflist"]
  if params["projname"].nil? || params["description"].nil? || params["projname"].strip == "" || params["description"].strip == "" || params["conflist"].nil? || params["conflist"].strip == ""
    session[:rcpcreate_error] = "Имя проекта, описание и окружение сборки не должны быть пустыми"
    redirect "/prjcreate"
  else
    prj = ProjectsActions.new(cfg.get_projects_path, db)
    result = prj.create_project(params["projname"], params["description"], params["conflist"])
    if result != 0
      session[:prjcreate_error] = prj.error
      redirect "/prjcreate"
    else
      session[:prj_old_name] = nil
      session[:prj_old_description] = nil
      session[:prj_old_list] = nil
      redirect "/projs"
    end
  end
end

get "/prjedit/:id" do
  unless session[:prj_modal_text].nil?
    @modal_info = session[:prj_modal_info]
    @modal_text = session[:prj_modal_text]
    session[:prj_modal_info] = nil
    session[:prj_modal_text] = nil
  end
  prj = ProjectsActions.new(cfg.get_projects_path, db)
  if prj.path.nil?
    print_error_page(503, "Путь к проектам не существует")
  else
    repo = GitRepo.new(cfg.get_repo, db)
    if repo.path.nil?
      print_error_page(503, "Путь к репозиториям не существует")
    else
      prj_info = prj.get_project(params["id"])
      if prj_info.nil?
        print_error_page(503, "Путь к проектам не существует")
      else
        @page_name = prj_info[:projname]
        @proj_name = prj_info[:projname]
        @proj_descr = prj_info[:descr]
        @proj_id = prj_info[:id]
        repo_lst = repo.getrepos
        proj_repo_list = prj.get_project_gits(prj_info[:id], repo)
        @repo_list = repo_lst.reject do |item|
          fnd = false
          proj_repo_list.each do |item2|
            if item2[:id] == item[:id]
              fnd = true
              break
            end
          end
          fnd
        end
        @proj_repo = proj_repo_list
        erb :prjinfo
      end
    end
  end
end

post "/prjagit/:id" do
  prj = ProjectsActions.new(cfg.get_projects_path, db)
  if prj.path.nil?
    print_error_page(503, "Путь к проектам не существует")
  else
    repo = GitRepo.new(cfg.get_repo, db)
    if repo.path.nil?
      print_error_page(503, "Путь к репозиториям не существует")
    else
      prj_info = prj.get_project(params["id"])
      if prj_info.nil?
        print_error_page(503, "Путь к проектам не существует")
      else
        proj_repo_list = prj.get_project_gits(prj_info[:id], repo)
        git_info = repo.get_repo_short_info_by_id(params["gitlist"].to_i)
        if git_info.nil?
          print_error_page(503, "Репозиторий исчез")
        else
          fnd = false
          proj_repo_list.each do |item|
            if item[:id] == git_info[:id]
              fnd = true
              break
            end
          end
          if fnd
            session[:prj_modal_info] = "Ошибка"
            session[:prj_modal_text] = "Данный git-репозиторий уже добавлен к проекту"
          else
            err = prj.add_git_to_project(prj_info[:id], git_info[:id], repo, git_info[:reponame])
            if err.nil?
              session[:prj_modal_info] = nil
              session[:prj_modal_text] = nil
            else
              session[:prj_modal_info] = "Ошибка добавления git проекта"
              session[:prj_modal_text] = err
            end
          end
        end
      end
    end
  end
  redirect back
end

get "/prjrgit/:id/:git_id" do
  prj = ProjectsActions.new(cfg.get_projects_path, db)
  if prj.path.nil?
    print_error_page(503, "Путь к проектам не существует")
  else
    repo = GitRepo.new(cfg.get_repo, db)
    if repo.path.nil?
      print_error_page(503, "Путь к репозиториям не существует")
    else
      prj_info = prj.get_project(params["id"])
      if prj_info.nil?
        print_error_page(503, "Путь к проектам не существует")
      else
        proj_repo_list = prj.get_project_gits(prj_info[:id], repo)
        git_info = repo.get_repo_short_info_by_id(params["git_id"].to_i)
        if git_info.nil?
          print_error_page(503, "Репозиторий исчез")
        else
          err = prj.renew_git_to_project(prj_info[:id], git_info[:id], repo, git_info[:reponame])
          if err.nil?
            session[:prj_modal_info] = nil
            session[:prj_modal_text] = nil
          else
            session[:prj_modal_info] = "Ошибка обновления git проекта"
            session[:prj_modal_text] = err
          end
        end
      end
    end
  end
  redirect back
end

get "/prjgitf/:id/:git_id" do
  prj = ProjectsActions.new(cfg.get_projects_path, db)
  if prj.path.nil?
    print_error_page(503, "Путь к проектам не существует")
  else
    repo = GitRepo.new(cfg.get_repo, db)
    if repo.path.nil?
      print_error_page(503, "Путь к репозиториям не существует")
    else
      prj_info = prj.get_project(params["id"])
      if prj_info.nil?
        print_error_page(503, "Путь к проектам не существует")
      else
        proj_repo_list = prj.get_project_gits(prj_info[:id], repo)
        git_info = repo.get_repo_short_info_by_id(params["git_id"].to_i)
        if git_info.nil?
          print_error_page(503, "Репозиторий исчез")
        else
          if params["p"].nil?
            filepath = ""
          else
            filepath = params["p"]
          end
          proj_path = prj.get_project_path_git(prj_info[:id], git_info[:reponame])
          f_path = File.join(proj_path, filepath)
          if File.exist?(f_path)
            if File.directory?(f_path)
              @file_content = []
              @files_list = Dir[File.join(f_path, "*")].map do |item|
                if File.directory?(item)
                  { :file => item.delete_prefix(proj_path + "/"), :isdir => true }
                else
                  { :file => item.delete_prefix(proj_path + "/"), :isdir => false }
                end
              end
            else
              @file_content = File.readlines(f_path)
              @files_list = Dir[File.join(File.dirname(f_path), "*")].map do |item|
                if File.directory?(item)
                  { :file => item.delete_prefix(proj_path + "/"), :isdir => true }
                else
                  { :file => item.delete_prefix(proj_path + "/"), :isdir => false }
                end
              end
            end
            if filepath != ""
              if File.dirname(f_path) == proj_path
                fn = ""
              else
                if File.directory?(f_path)
                  fn = File.dirname(f_path).delete_prefix(proj_path + "/")
                else
                  f_path = File.dirname(f_path)
                  if File.dirname(f_path) == proj_path
                    fn = ""
                  else
                    fn = File.dirname(f_path).delete_prefix(proj_path + "/")
                  end
                end
              end
              @files_list = [{ :file => "..", :isdir => true, :fname => fn }] + @files_list
            end
            @page_name = "#{prj_info[:projname]} информация из репозитория #{git_info[:reponame]}"
            @proj_info = prj_info
            @proj_git_name = git_info
            @file_name = filepath
            erb :fileinfo
          else
            print_error_page(503, "Файл не существует")
          end
        end
      end
    end
  end
end

get "/gitbld/:id/:git_id" do
end

get "/prjcfg/:id" do
  unless session[:prjcfg_modal_text].nil?
    @modal_info = session[:prjcfg_modal_info]
    @modal_text = session[:prjcfg_modal_text]
    session[:prjcfg_modal_info] = nil
    session[:prjcfg_modal_text] = nil
  end
  prj = ProjectsActions.new(cfg.get_projects_path, db)
  if prj.path.nil?
    print_error_page(503, "Путь к проектам не существует")
  else
    prj_info = prj.get_project(params["id"])
    if prj_info.nil?
      print_error_page(503, "Путь к проектам не существует")
    else
      @page_name = "#{prj_info[:projname]} редактирование конфигурации сборки"
      @proj_name = prj_info[:projname]
      @proj_descr = prj_info[:descr]
      project_cfg = prj.get_project_config(params["id"])
      @project_cfg_tmpl = File.basename(project_cfg)
      @file_content = File.readlines(project_cfg).join("")
      @proj_id = prj_info[:id]
      erb :prjcfged
    end
  end
end

post "/prjcfg/:id" do
  prj = ProjectsActions.new(cfg.get_projects_path, db)
  if prj.path.nil?
    print_error_page(503, "Путь к проектам не существует")
  else
    prj_info = prj.get_project(params["id"])
    if prj_info.nil?
      print_error_page(503, "Путь к проектам не существует")
    else
      pp params
      unless params["cancel"].nil?
        redirect "/prjedit/#{params["id"]}"
      else
        if params["cfginfo"].nil? || params["cfginfo"].strip == ""
          session[:prjcfg_modal_info] = "Ошибка сохранения файла"
          session[:prjcfg_modal_text] = "Содержимое файла не может быть пустым"
          redirect "/prjcfg/#{params["id"]}"
        else
          project_cfg = prj.get_project_config(params["id"])
          File.open(project_cfg, "w") { |f| f.write(params["cfginfo"]) }
          redirect "/prjcfg/#{params["id"]}"
        end
      end
    end
  end
end

get "/gitspec/:id/:git_id" do
  prj = ProjectsActions.new(cfg.get_projects_path, db)
  if prj.path.nil?
    print_error_page(503, "Путь к проектам не существует")
  else
    repo = GitRepo.new(cfg.get_repo, db)
    if repo.path.nil?
      print_error_page(503, "Путь к репозиториям не существует")
    else
      prj_info = prj.get_project(params["id"])
      if prj_info.nil?
        print_error_page(503, "Путь к проектам не существует")
      else
        git_info = repo.get_repo_short_info_by_id(params["git_id"].to_i)
        @spec_file = db.get_project_repo_spec(params["id"], params["git_id"])
        @page_name = "#{prj_info[:projname]} редактирование spec для git проекта #{git_info[:reponame]}"
        @proj_id = prj_info[:id]
        @git_id = git_info[:id]
        git_path = prj.get_project_path_git(prj_info[:id], git_info[:reponame])
        @files_list = get_spec_files_in_dir(git_path)
        current_spec_data = db.get_project_repo_spec(prj_info[:id], git_info[:id])
        @current_spec = nil
        unless current_spec_data.nil?
          @current_spec = current_spec_data[:spec_name]
        end
        erb :prjspec
      end
    end
  end
end

not_found do
  status 404
  @page_name = "Кто-то потерялся"
  @req_referer = request.referer
  erb :page404
end