# app/controllers/admin/post_reviews_controller.rb
class Admin::PostReviewsController < Admin::BaseController
  include ApplicationHelper # For short_time_simple, short_time_detailed helpers

  before_action :set_post, only: [ :show, :update ]

  def show
    # User related to the post
    slack_uid = @post.airtable_fields["slackId"]&.first
    @user = User.find_by(slack_uid: slack_uid)
    ensure_exists @user # Redirects if user not found

    @target_user_timezone = @user.timezone || "UTC" # Target user's timezone
    @project_repo_mappings_for_user = @user.project_repo_mappings.index_by(&:project_name)

    begin
      post_start_str = @post.airtable_fields["lastPost"]
      post_end_str = @post.airtable_fields["createdAt"]
      @total_post_hackatime_seconds = @post.airtable_fields["hackatimeTime"]&.to_i || 0

      if post_start_str.blank? || post_end_str.blank?
        raise ArgumentError, "Post start or end date is missing from Airtable. lastPost: '#{post_start_str}', createdAt: '#{post_end_str}'"
      end

      post_start_utc = Time.zone.parse(post_start_str)
      post_end_utc = Time.zone.parse(post_end_str)
    rescue ArgumentError, TypeError => e
      Rails.logger.error "Failed to parse post dates from Airtable for post #{@post.id} (User: #{@user.id}): #{e.message}"
      flash.now[:alert] = "Could not parse post dates for post ID #{@post.airtable_id}. Please check Airtable data. Error: #{e.message}"
      @review_start_date = Date.current - 1.day
      @review_end_date = Date.current + 1.day
      @post_start_display = Time.current
      @post_end_display = Time.current
      @commits = []
      @detailed_spans = []
      render and return
    end

    @post_start_display = post_start_utc.in_time_zone(@target_user_timezone)
    @post_end_display = post_end_utc.in_time_zone(@target_user_timezone)

    @review_start_date = (@post_start_display.to_date - 1.day)
    @review_end_date = (@post_end_display.to_date + 1.day)

    query_start_utc = @review_start_date.in_time_zone(@target_user_timezone).beginning_of_day.utc
    query_end_utc = @review_end_date.in_time_zone(@target_user_timezone).end_of_day.utc

    @commits = Commit.where(user: @user, created_at: query_start_utc..query_end_utc).order(created_at: :asc)

    all_heartbeats_for_user_in_review_window = Heartbeat
      .where.not(project: nil)
      .where(user: @user, time: query_start_utc.to_f..query_end_utc.to_f)
      .select(:id, :user_id, :time, :entity, :project, :editor, :language)
      .order(:time)
      .to_a

    @unique_project_names = all_heartbeats_for_user_in_review_window
      .map(&:project)
      .compact
      .reject(&:blank?)
      .uniq
      .sort

    @unique_file_extensions = all_heartbeats_for_user_in_review_window
      .map(&:entity)
      .compact
      .map { |entity| File.extname(entity).delete(".") }
      .reject(&:blank?)
      .uniq
      .sort

    @recommended_project_names = @post.app.projects.map(&:airtable_fields).map { |p| p["name"] }.compact.uniq.sort

    @selected_projects = if params[:projects].present?
      params[:projects].split(",")
    else
      @recommended_project_names
    end

    @selected_extensions = if params[:extensions].present?
      params[:extensions].split(",")
    else
      @unique_file_extensions
    end

    all_heartbeats_for_user_in_review_window = all_heartbeats_for_user_in_review_window.select do |hb|
      @selected_projects.include?(hb.project)
    end

    all_heartbeats_for_user_in_review_window = all_heartbeats_for_user_in_review_window.select do |hb|
      hb.entity.present? && @selected_extensions.include?(File.extname(hb.entity).delete("."))
    end

    @detailed_spans = []
    timeout_duration = 10.minutes.to_i
    if all_heartbeats_for_user_in_review_window.any?
      current_span_heartbeats = []

      all_heartbeats_for_user_in_review_window.each_with_index do |heartbeat, index|
        current_span_heartbeats << heartbeat
        is_last_heartbeat = (index == all_heartbeats_for_user_in_review_window.length - 1)
        time_to_next = is_last_heartbeat ? Float::INFINITY : (all_heartbeats_for_user_in_review_window[index + 1].time - heartbeat.time)

        if time_to_next > timeout_duration || is_last_heartbeat
          if current_span_heartbeats.any?
            start_time_numeric = current_span_heartbeats.first.time
            last_hb_time_numeric = current_span_heartbeats.last.time

            # Split span if it crosses post start or end time
            post_start_numeric = @post_start_display.to_f
            post_end_numeric = @post_end_display.to_f

            # Create spans for each segment
            if start_time_numeric < post_start_numeric && last_hb_time_numeric > post_start_numeric
              # Split at post start
              create_span_for_heartbeats(current_span_heartbeats, start_time_numeric, post_start_numeric)
              create_span_for_heartbeats(current_span_heartbeats, post_start_numeric, last_hb_time_numeric)
            elsif start_time_numeric < post_end_numeric && last_hb_time_numeric > post_end_numeric
              # Split at post end
              create_span_for_heartbeats(current_span_heartbeats, start_time_numeric, post_end_numeric)
              create_span_for_heartbeats(current_span_heartbeats, post_end_numeric, last_hb_time_numeric)
            else
              # No split needed
              create_span_for_heartbeats(current_span_heartbeats, start_time_numeric, last_hb_time_numeric)
            end

            current_span_heartbeats = []
          end
        end
      end
    end

    @current_user_timezone = current_user.timezone
  end

  def update
    approved_seconds = params[:approved_seconds].to_i
    comment = params[:comment]

    fields = {
      "approved_time" => approved_seconds,
      "review_comment" => comment,
      "review_status" => "approved"
    }

    if @post.push_to_airtable!(fields)
      flash[:notice] = "Time approved successfully"
      redirect_to admin_ysws_review_path(@post.app.ysws_submission.airtable_id)
    else
      flash[:alert] = "Failed to approve time"
      redirect_to admin_post_review_path(@post.airtable_id)
    end

  rescue => e
    flash[:alert] = "Failed to approve time: #{e.message}"
    redirect_to admin_post_review_path(@post.airtable_id)
  end

  private

  def create_span_for_heartbeats(heartbeats, start_time, end_time)
    actual_coded_duration_seconds = Heartbeat.where(id: heartbeats.map(&:id)).duration_seconds

    files = heartbeats.map { |h| h.entity&.split("/")&.last }.compact.uniq.sort

    projects_details_for_span = []
    unique_project_names = heartbeats.map(&:project).compact.reject(&:blank?).uniq

    unique_project_names.each do |p_name|
      repo_mapping = @project_repo_mappings_for_user[p_name]
      projects_details_for_span << {
        name: p_name,
        repo_url: repo_mapping&.repo_url
      }
    end

    editors = heartbeats.map(&:editor).compact.uniq.sort
    languages = heartbeats.map(&:language).compact.uniq.sort

    @detailed_spans << {
      id: "span_#{SecureRandom.hex(4)}", # Unique ID for checkbox
      start_time: start_time,
      end_time: end_time,
      duration: actual_coded_duration_seconds,
      files_edited: files,
      projects_edited_details: projects_details_for_span.sort_by { |p| p[:name].downcase },
      editors: editors,
      languages: languages
    }
  end

  def set_post
    @post = Neighborhood::Post.find_by(airtable_id: params[:post_id])
    ensure_exists @post
  end

  def ensure_exists(value)
    unless value.present?
      object_name = value.nil? ? "Record" : value.class.name.demodulize
      redirect_to admin_timeline_path, alert: "#{object_name} not found."
    end
  end
end
