require "pact_broker/dataset"
require "pact_broker/messages"
require "pact_broker/domain/label"
require "pact_broker/string_refinements"
require "pact_broker/pacticipants/generate_display_name"
require "pact_broker/pacticipants/latest_version_for_pacticipant_eager_loader"

module PactBroker
  module Domain
    class Pacticipant < Sequel::Model

      include Messages
      include PactBroker::Pacticipants::GenerateDisplayName
      using PactBroker::StringRefinements

      plugin :insert_ignore, identifying_columns: [:name]
      plugin :upsert, identifying_columns: [:name]
      plugin :timestamps, update_on_create: true

      set_primary_key :id

      one_to_many :versions, :order => :order, :reciprocal => :pacticipant
      one_to_many :labels, :order => :name, :reciprocal => :pacticipant
      one_to_many :pacts
      one_to_one :latest_version, :class => "PactBroker::Domain::Version",
        primary_key: :id, key: :pacticipant_id,
        dataset: lambda { PactBroker::Domain::Version.where(pacticipant_id: id).order(Sequel.desc(:order)).limit(1) },
        eager_loader: PactBroker::Pacticipants::LatestVersionForPacticipantEagerLoader

      one_to_many :branch_heads, class: "PactBroker::Versions::BranchHead", primary_key: :id, key: :pacticipant_id
      one_to_many :branches, class: "PactBroker::Versions::Branch", primary_key: :id, key: :pacticipant_id

      dataset_module do
        include PactBroker::Dataset

        def with_main_branch_set
          exclude(main_branch: nil)
        end

        def label label_name
          filter = name_like(Sequel[:labels][:name], label_name)
          join(:labels, {pacticipant_id: :id}).where(filter)
        end

        def find_by_name(name)
          where(name_like(:name, name))
        end

        def where_name(name)
          where(name_like(:name, name))
        end
      end

      def before_destroy
        PactBroker::Pacts::PactPublication.where(provider: self).delete
        PactBroker::Domain::Verification.where(consumer: self).or(provider: self).delete
        PactBroker::Domain::Version.where(pacticipant: self).delete
        PactBroker::Pacts::PactVersion.where(consumer: self).or(provider: self).delete
        PactBroker::Domain::Label.where(pacticipant: self).destroy
        super
      end

      def before_save
        super
        self.display_name = generate_display_name(name) if display_name.blank?
        self.main_branch = nil if main_branch.blank?
      end

      def to_s
        "Pacticipant: id=#{id}, name=#{name}"
      end

      def any_versions?
        PactBroker::Domain::Version.where(pacticipant: self).any?
      end

      def branch_head_for(branch_name)
        branch_heads.find{ | branch_head | branch_head.branch_name == branch_name }
      end

      def label?(name)
        labels.any? { |label| label.name == name }
      end
    end
  end
end

# Table: pacticipants
# Columns:
#  id                        | integer                     | PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY
#  name                      | text                        |
#  repository_url            | text                        |
#  created_at                | timestamp without time zone | NOT NULL
#  updated_at                | timestamp without time zone | NOT NULL
#  display_name              | text                        |
#  repository_name           | text                        |
#  repository_namespace      | text                        |
#  main_development_branches | text                        |
#  main_branch               | text                        |
# Indexes:
#  pacticipants_pkey     | PRIMARY KEY btree (id)
#  pacticipants_name_key | UNIQUE btree (name)
#  ndx_ppt_name          | btree (name)
# Referenced By:
#  branches                                                     | branches_pacticipant_id_fkey                                    | (pacticipant_id) REFERENCES pacticipants(id) ON DELETE CASCADE
#  currently_deployed_version_ids                               | currently_deployed_version_ids_pacticipant_id_fkey              | (pacticipant_id) REFERENCES pacticipants(id) ON DELETE CASCADE
#  integrations                                                 | integrations_consumer_id_foreign_key                            | (consumer_id) REFERENCES pacticipants(id) ON DELETE CASCADE
#  integrations                                                 | integrations_provider_id_foreign_key                            | (provider_id) REFERENCES pacticipants(id) ON DELETE CASCADE
#  labels                                                       | labels_pacticipant_id_fkey                                      | (pacticipant_id) REFERENCES pacticipants(id)
#  latest_pact_publication_ids_for_consumer_versions            | latest_pact_publication_ids_for_consumer_versi_consumer_id_fkey | (consumer_id) REFERENCES pacticipants(id) ON DELETE CASCADE
#  latest_pact_publication_ids_for_consumer_versions            | latest_pact_publication_ids_for_consumer_versi_provider_id_fkey | (provider_id) REFERENCES pacticipants(id) ON DELETE CASCADE
#  latest_verification_id_for_pact_version_and_provider_version | latest_v_id_for_pv_and_pv_consumer_id_fk                        | (consumer_id) REFERENCES pacticipants(id) ON DELETE CASCADE
#  latest_verification_id_for_pact_version_and_provider_version | latest_v_id_for_pv_and_pv_provider_id_fk                        | (provider_id) REFERENCES pacticipants(id) ON DELETE CASCADE
#  pact_publications                                            | pact_publications_consumer_id_fkey                              | (consumer_id) REFERENCES pacticipants(id)
#  pact_publications                                            | pact_publications_provider_id_fkey                              | (provider_id) REFERENCES pacticipants(id)
#  pact_versions                                                | pact_versions_consumer_id_fkey                                  | (consumer_id) REFERENCES pacticipants(id)
#  pact_versions                                                | pact_versions_provider_id_fkey                                  | (provider_id) REFERENCES pacticipants(id)
#  triggered_webhooks                                           | triggered_webhooks_consumer_id_fkey                             | (consumer_id) REFERENCES pacticipants(id)
#  triggered_webhooks                                           | triggered_webhooks_provider_id_fkey                             | (provider_id) REFERENCES pacticipants(id)
#  verifications                                                | verifications_consumer_id_fkey                                  | (consumer_id) REFERENCES pacticipants(id)
#  verifications                                                | verifications_provider_id_fkey                                  | (provider_id) REFERENCES pacticipants(id)
#  versions                                                     | versions_pacticipant_id_fkey                                    | (pacticipant_id) REFERENCES pacticipants(id)
#  webhook_executions                                           | webhook_executions_consumer_id_fkey                             | (consumer_id) REFERENCES pacticipants(id)
#  webhook_executions                                           | webhook_executions_provider_id_fkey                             | (provider_id) REFERENCES pacticipants(id)
#  webhooks                                                     | fk_webhooks_consumer                                            | (consumer_id) REFERENCES pacticipants(id)
#  webhooks                                                     | fk_webhooks_provider                                            | (provider_id) REFERENCES pacticipants(id)
