# frozen_string_literal: true

# Controlador de sitios
class SitesController < ApplicationController
  include Pundit
  rescue_from Pundit::NilPolicyError, with: :page_not_found

  before_action :authenticate_usuarie!

  breadcrumb -> { current_usuarie.email }, :edit_usuarie_registration_path
  breadcrumb 'sites.index', :sites_path, match: :exact

  # Ver un listado de sitios
  def index
    authorize Site
    @sites = current_usuarie.sites.order(:title)

    fresh_when @sites
  end

  # No tenemos propiedades de un sitio aún, así que vamos al listado de
  # artículos
  def show
    authorize site

    redirect_to site_posts_path(site, locale: site.default_locale)
  end

  def new
    breadcrumb 'sites.new', :new_site_path

    @site = Site.new
    authorize @site

    @site.deploys.build type: 'DeployLocal'
  end

  def create
    service = SiteService.new(usuarie: current_usuarie,
                              params: site_params)

    if (@site = service.create).persisted?
      redirect_to site_posts_path(@site, locale: @site.default_locale)
    else
      render 'new'
    end
  end

  def edit
    authorize site

    breadcrumb site.title, site_posts_path(site, locale: site.default_locale), match: :exact
    breadcrumb 'sites.edit', site_path(site)

    SiteService.new(site: site).build_deploys
  end

  def update
    authorize site

    service = SiteService.new(site: site, params: site_params,
                              usuarie: current_usuarie)

    if service.update.valid?
      redirect_to site_posts_path(site, locale: site.default_locale)
    else
      render 'edit'
    end
  end

  def enqueue
    authorize site

    # XXX: Convertir en una máquina de estados?
    site.enqueue!
    DeployJob.perform_async site.id

    redirect_to site_posts_path(site, locale: site.default_locale)
  end

  def reorder_posts
    authorize site
    lang = params.require(:posts).require(:lang)

    result = if params[:posts][:force].present?
               site.reorder_collection! lang
             else
               site
                 .reorder_collection(lang, params.require(:posts).require(:order))
             end

    if result
      flash[:info] = I18n.t('info.posts.reorder')
    else
      flash[:danger] = I18n.t('errors.posts.reorder')
    end

    redirect_to site_posts_path(site, locale: site.default_locale)
  end

  def fetch
    authorize site

    @commits = site.repository.commits
  end

  def merge
    authorize site

    if SiteService.new(site: site, usuarie: current_usuarie).merge
      flash[:success] = I18n.t('sites.fetch.merge.success')
    else
      flash[:error] = I18n.t('sites.fetch.merge.error')
    end

    redirect_to sites_path
  end

  # Obtiene y streamea archivos estáticos desde el repositorio mismo,
  # pero sólo los públicos (es decir los archivos subidos desde Sutty).
  def static_file
    authorize site

    file = params.require(:file) + '.' + params.require(:format)

    raise ActionController::RoutingError.new(nil, nil) unless file.start_with? 'public/'

    path = site.relative_path file

    raise ActionController::RoutingError.new(nil, nil) unless File.exist? path

    # TODO: Hacer esto usa recursos, pero menos que generar el sitio
    # cada vez.  Para poder usar X-Accel tendríamos que montar los
    # repositorios en el servidor web, cosa que no queremos, o hacer
    # links simbólicos desde todos los public, o usar un servidor web
    # local que soporte sendfile mejor que Rails (nghttpd?)
    send_file path
  end

  private

  def site
    @site ||= find_site
  end

  def site_params
    params.require(:site)
          .permit(:name, :design_id, :licencia_id, :description, :title,
                  :colaboracion_anonima, :contact, :acepta_invitades,
                  :tienda_api_key, :tienda_url,
                  deploys_attributes: %i[type id _destroy])
  end
end